From b7be751447ab5aba65b38eb9c845325fd5b50e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Sat, 16 May 2020 16:31:15 +0200 Subject: [PATCH] repl: support --loader option in builtin REPL Fixes: https://github.com/nodejs/node/issues/33435 PR-URL: https://github.com/nodejs/node/pull/33437 Backport-PR-URL: https://github.com/nodejs/node/pull/35394 Reviewed-By: Gus Caplan Reviewed-By: Ruben Bridgewater --- lib/internal/main/repl.js | 51 ++++++++++--------- lib/internal/modules/run_main.js | 15 +----- lib/internal/process/esm_loader.js | 30 +++++++++-- .../esm_display_syntax_error_import.out | 1 + ...esm_display_syntax_error_import_module.out | 1 + test/message/esm_loader_not_found.out | 8 +-- .../esm_loader_not_found_cjs_hint_bare.out | 2 +- ...esm_loader_not_found_cjs_hint_relative.out | 8 +-- 8 files changed, 65 insertions(+), 51 deletions(-) diff --git a/lib/internal/main/repl.js b/lib/internal/main/repl.js index 693b7048a37f9c..d5ee9b0a7d3643 100644 --- a/lib/internal/main/repl.js +++ b/lib/internal/main/repl.js @@ -7,6 +7,7 @@ const { prepareMainThreadExecution } = require('internal/bootstrap/pre_execution'); +const esmLoader = require('internal/process/esm_loader'); const { evalScript } = require('internal/process/execution'); @@ -32,31 +33,33 @@ if (process.env.NODE_REPL_EXTERNAL_MODULE) { process.exit(1); } - console.log(`Welcome to Node.js ${process.version}.\n` + - 'Type ".help" for more information.'); + esmLoader.loadESM(() => { + console.log(`Welcome to Node.js ${process.version}.\n` + + 'Type ".help" for more information.'); - const cliRepl = require('internal/repl'); - cliRepl.createInternalRepl(process.env, (err, repl) => { - if (err) { - throw err; - } - repl.on('exit', () => { - if (repl._flushing) { - repl.pause(); - return repl.once('flushHistory', () => { - process.exit(); - }); + const cliRepl = require('internal/repl'); + cliRepl.createInternalRepl(process.env, (err, repl) => { + if (err) { + throw err; } - process.exit(); + repl.on('exit', () => { + if (repl._flushing) { + repl.pause(); + return repl.once('flushHistory', () => { + process.exit(); + }); + } + process.exit(); + }); }); - }); - - // If user passed '-e' or '--eval' along with `-i` or `--interactive`, - // evaluate the code in the current context. - if (getOptionValue('[has_eval_string]')) { - evalScript('[eval]', - getOptionValue('--eval'), - getOptionValue('--inspect-brk'), - getOptionValue('--print')); - } + + // If user passed '-e' or '--eval' along with `-i` or `--interactive`, + // evaluate the code in the current context. + if (getOptionValue('[has_eval_string]')) { + evalScript('[eval]', + getOptionValue('--eval'), + getOptionValue('--inspect-brk'), + getOptionValue('--print')); + } + }, false); } diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js index d18a1a295714b8..a94b88f83269fa 100644 --- a/lib/internal/modules/run_main.js +++ b/lib/internal/modules/run_main.js @@ -40,21 +40,10 @@ function shouldUseESMLoader(mainPath) { function runMainESM(mainPath) { const esmLoader = require('internal/process/esm_loader'); const { pathToFileURL } = require('internal/url'); - const { hasUncaughtExceptionCaptureCallback } = - require('internal/process/execution'); - return esmLoader.initializeLoader().then(() => { + esmLoader.loadESM((ESMLoader) => { const main = path.isAbsolute(mainPath) ? pathToFileURL(mainPath).href : mainPath; - return esmLoader.ESMLoader.import(main); - }).catch((e) => { - if (hasUncaughtExceptionCaptureCallback()) { - process._fatalException(e); - return; - } - internalBinding('errors').triggerUncaughtException( - e, - true /* fromPromise */ - ); + return ESMLoader.import(main); }); } diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js index cca1e3e07956a1..7788e7db7d0f91 100644 --- a/lib/internal/process/esm_loader.js +++ b/lib/internal/process/esm_loader.js @@ -5,6 +5,9 @@ const { } = require('internal/errors').codes; const assert = require('internal/assert'); const { Loader } = require('internal/modules/esm/loader'); +const { + hasUncaughtExceptionCaptureCallback, +} = require('internal/process/execution'); const { pathToFileURL } = require('internal/url'); const { getModuleFromWrap, @@ -45,12 +48,13 @@ let ESMLoader = new Loader(); exports.ESMLoader = ESMLoader; let calledInitialize = false; -exports.initializeLoader = initializeLoader; -async function initializeLoader() { +async function initializeLoader(emitWarning) { assert(calledInitialize === false); - process.emitWarning( - 'The ESM module loader is experimental.', - 'ExperimentalWarning', undefined); + if (emitWarning) { + process.emitWarning( + 'The ESM module loader is experimental.', + 'ExperimentalWarning', undefined); + } calledInitialize = true; if (!userLoader) return; @@ -73,3 +77,19 @@ async function initializeLoader() { return exports.ESMLoader = ESMLoader; })(); } + +exports.loadESM = async function loadESM(callback, emitWarning = true) { + try { + await initializeLoader(emitWarning); + await callback(ESMLoader); + } catch (err) { + if (hasUncaughtExceptionCaptureCallback()) { + process._fatalException(err); + return; + } + internalBinding('errors').triggerUncaughtException( + err, + true /* fromPromise */ + ); + } +}; diff --git a/test/message/esm_display_syntax_error_import.out b/test/message/esm_display_syntax_error_import.out index e39744a049b59b..8ca1165766bf77 100644 --- a/test/message/esm_display_syntax_error_import.out +++ b/test/message/esm_display_syntax_error_import.out @@ -6,3 +6,4 @@ SyntaxError: The requested module '../fixtures/es-module-loaders/module-named-ex at ModuleJob._instantiate (internal/modules/esm/module_job.js:*:*) at async ModuleJob.run (internal/modules/esm/module_job.js:*:*) at async Loader.import (internal/modules/esm/loader.js:*:*) + at async Object.loadESM (internal/process/esm_loader.js:*:*) diff --git a/test/message/esm_display_syntax_error_import_module.out b/test/message/esm_display_syntax_error_import_module.out index 0daaeff5b95daf..56035bc0340cc8 100644 --- a/test/message/esm_display_syntax_error_import_module.out +++ b/test/message/esm_display_syntax_error_import_module.out @@ -6,3 +6,4 @@ SyntaxError: The requested module './module-named-exports.mjs' does not provide at ModuleJob._instantiate (internal/modules/esm/module_job.js:*:*) at async ModuleJob.run (internal/modules/esm/module_job.js:*:*) at async Loader.import (internal/modules/esm/loader.js:*:*) + at async Object.loadESM (internal/process/esm_loader.js:*:*) diff --git a/test/message/esm_loader_not_found.out b/test/message/esm_loader_not_found.out index a054dacf2f930a..4fe916b315f9d8 100644 --- a/test/message/esm_loader_not_found.out +++ b/test/message/esm_loader_not_found.out @@ -1,6 +1,6 @@ (node:*) ExperimentalWarning: The ESM module loader is experimental. (node:*) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time -internal/modules/run_main.js:* +internal/process/esm_loader.js:* internalBinding('errors').triggerUncaughtException( ^ Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'i-dont-exist' imported from * @@ -11,8 +11,8 @@ Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'i-dont-exist' imported from * at Loader.getModuleJob (internal/modules/esm/loader.js:*:*) at Loader.import (internal/modules/esm/loader.js:*:*) at internal/process/esm_loader.js:*:* - at Object.initializeLoader (internal/process/esm_loader.js:*:*) - at runMainESM (internal/modules/run_main.js:*:*) - at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:*:*) { + at initializeLoader (internal/process/esm_loader.js:*:*) + at Object.loadESM (internal/process/esm_loader.js:*:*) + at runMainESM (internal/modules/run_main.js:*:*) { code: 'ERR_MODULE_NOT_FOUND' } diff --git a/test/message/esm_loader_not_found_cjs_hint_bare.out b/test/message/esm_loader_not_found_cjs_hint_bare.out index 77c5248bb59423..57c1718f28df9a 100644 --- a/test/message/esm_loader_not_found_cjs_hint_bare.out +++ b/test/message/esm_loader_not_found_cjs_hint_bare.out @@ -1,5 +1,5 @@ (node:*) ExperimentalWarning: The ESM module loader is experimental. -internal/modules/run_main.js:* +internal/process/esm_loader.js:* internalBinding('errors').triggerUncaughtException( ^ diff --git a/test/message/esm_loader_not_found_cjs_hint_relative.out b/test/message/esm_loader_not_found_cjs_hint_relative.out index 82ede3ab9b9ec9..63a3a4aff92def 100644 --- a/test/message/esm_loader_not_found_cjs_hint_relative.out +++ b/test/message/esm_loader_not_found_cjs_hint_relative.out @@ -1,6 +1,6 @@ (node:*) ExperimentalWarning: The ESM module loader is experimental. (node:*) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time -internal/modules/run_main.js:* +internal/process/esm_loader.js:* internalBinding('errors').triggerUncaughtException( ^ @@ -13,8 +13,8 @@ Did you mean to import ./test/common/fixtures.js? at Loader.getModuleJob (internal/modules/esm/loader.js:*:*) at Loader.import (internal/modules/esm/loader.js:*:*) at internal/process/esm_loader.js:*:* - at Object.initializeLoader (internal/process/esm_loader.js:*:*) - at runMainESM (internal/modules/run_main.js:*:*) - at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:*:*) { + at initializeLoader (internal/process/esm_loader.js:*:*) + at Object.loadESM (internal/process/esm_loader.js:*:*) + at runMainESM (internal/modules/run_main.js:*:*) { code: 'ERR_MODULE_NOT_FOUND' }