Skip to content

Commit 064b8b2

Browse files
committed
Correct macro-require for relative paths
Calls to `require` in macros were resolving relative to the eslc executable, not relative to the current working directory. This fixes that, such that cwd should always be used. I thought existing tests were catching this, but turns out the test was creating the temporary files that it used in the eslisp project directory, which totally misses the point. The files are now created in a separate tmp directory, and the eslc command is run in full in that dir. Fixes #25.
1 parent 09b26b7 commit 064b8b2

File tree

3 files changed

+41
-11
lines changed

3 files changed

+41
-11
lines changed

makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ lib/%.js: src/%.ls
1414
clean:
1515
@rm -rf lib/
1616

17-
test:
17+
test: all
1818
@lsc test.ls
1919

2020
test-readme: all readme.markdown

src/built-in-macros.ls

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,25 @@ contents =
398398
\macro : (env, ...args) ->
399399

400400
compile-as-macro = (es-ast) ->
401-
# This is deliberately defined in the closure here, so it's in scope
402-
# during the `eval` and available to the code being compiled.
403-
root-require = require.main.require.bind require.main
401+
402+
# This hack around require makes loading macros from relative paths work.
403+
#
404+
# It was guided by LiveScript's implementation
405+
# https://github.com/gkz/LiveScript/blob/a7525ce6fe7d4906f5d401edf94f15fe5a6b471e/src/node.ls#L10-L18
406+
# which originally derives from the Coco language.
407+
#
408+
# The gist of it is to use the main module's `require` method, such that
409+
# the current working directory is the root relative to which packages
410+
# are searched.
411+
412+
{main} = require
413+
dirname = "."
414+
main
415+
..paths = main.constructor._node-module-paths process.cwd!
416+
..filename = dirname
417+
418+
root-require = main.require.bind main
419+
404420
let require = root-require
405421
eval "(#{env.compile-to-js es-ast})"
406422

test.ls

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -837,18 +837,32 @@ test "compiler types are converted to JS ones when passed to macros" ->
837837

838838
test "macros can be required relative to root directory" ->
839839

840+
{ exec-sync } = require \child_process
841+
842+
{ name : dir-name, fd } = tmp.dir-sync!
843+
840844
# Create dummy temporary file
841-
file-name = "./#{uuid.v4!}.js"
842-
fd = fs.open-sync file-name, \a+
843-
fs.write-sync fd, "module.exports = function() { }"
845+
module-basename = "#{uuid.v4!}.js"
846+
module-path = path.join dir-name, module-basename
847+
module-fd = fs.open-sync module-path, \a+
848+
fs.write-sync module-fd, "module.exports = function() { }"
844849

845-
esl """
846-
(macro (object x (require "#file-name")))
850+
851+
main-basename = "#{uuid.v4!}.js"
852+
main-path = path.join dir-name, main-basename
853+
main-fd = fs.open-sync main-path, \a+
854+
fs.write-sync main-fd, """
855+
(macro (object x (require "./#module-basename")))
847856
(x)
848857
"""
849-
..`@equals` ""
850858
851-
fs.unlink-sync file-name
859+
eslc-path = path.join process.cwd!, "bin/eslc"
860+
try
861+
exec-sync "#eslc-path #main-basename", cwd : dir-name
862+
..to-string! `@equals` "\n"
863+
finally
864+
e <~ rimraf dir-name
865+
@equals e, null
852866

853867
test "macros can be required from node_modules relative to root directory" ->
854868

0 commit comments

Comments
 (0)