From b91d22cc8d31ed919b73ab49fe00baa61cb1b896 Mon Sep 17 00:00:00 2001 From: Corey Farrell Date: Fri, 22 Nov 2019 22:06:43 -0500 Subject: [PATCH] repl: fix referrer for dynamic import The ESM loader does not accept a directory as the referrer, it requires a path within the directory. Add `/repl` to ensure relative dynamic imports can succeed. Fixes: https://github.com/nodejs/node/issues/19570 PR-URL: https://github.com/nodejs/node/pull/30609 Reviewed-By: Gus Caplan Reviewed-By: Anna Henningsen Reviewed-By: Ben Coe --- lib/repl.js | 8 +++++--- test/parallel/test-repl-import-referrer.js | 24 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 test/parallel/test-repl-import-referrer.js diff --git a/lib/repl.js b/lib/repl.js index e304bc2e77c707..c1473588d3942c 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -332,10 +332,12 @@ function REPLServer(prompt, if (code === '\n') return cb(null); - let pwd; + let parentURL; try { const { pathToFileURL } = require('url'); - pwd = pathToFileURL(process.cwd()).href; + // Adding `/repl` prevents dynamic imports from loading relative + // to the parent of `process.cwd()`. + parentURL = pathToFileURL(path.join(process.cwd(), 'repl')).href; } catch { } while (true) { @@ -350,7 +352,7 @@ function REPLServer(prompt, filename: file, displayErrors: true, importModuleDynamically: async (specifier) => { - return asyncESM.ESMLoader.import(specifier, pwd); + return asyncESM.ESMLoader.import(specifier, parentURL); } }); } catch (e) { diff --git a/test/parallel/test-repl-import-referrer.js b/test/parallel/test-repl-import-referrer.js new file mode 100644 index 00000000000000..33bc442e6f69c8 --- /dev/null +++ b/test/parallel/test-repl-import-referrer.js @@ -0,0 +1,24 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const cp = require('child_process'); +const fixtures = require('../common/fixtures'); + +const args = ['--interactive', '--experimental-repl-await']; +const opts = { cwd: fixtures.path('es-modules') }; +const child = cp.spawn(process.execPath, args, opts); + +let output = ''; +child.stdout.setEncoding('utf8'); +child.stdout.on('data', (data) => { + output += data; +}); + +child.on('exit', common.mustCall(() => { + const results = output.replace(/^> /mg, '').split('\n').slice(2); + assert.deepStrictEqual(results, ['[Module] { message: \'A message\' }', '']); +})); + +child.stdin.write('await import(\'./message.mjs\');\n'); +child.stdin.write('.exit'); +child.stdin.end();