From 0d07117bc39154e9d5ecb4c13256e194a60d7a9b Mon Sep 17 00:00:00 2001 From: XadillaX Date: Mon, 30 Aug 2021 18:09:37 +0800 Subject: [PATCH] lib,repl: ignore `canBeRequiredByUsers` built-in e.g. `wasi` under no `--experimental-wasi-unstable-preview1` flag shouldn't be pre-required. --- lib/internal/main/eval_string.js | 2 +- lib/internal/modules/cjs/helpers.js | 13 +++++++-- lib/repl.js | 2 +- test/parallel/test-repl-built-in-modules.js | 32 +++++++++++++++++++++ 4 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 test/parallel/test-repl-built-in-modules.js diff --git a/lib/internal/main/eval_string.js b/lib/internal/main/eval_string.js index ad068b935dfee0..2784204f6002e9 100644 --- a/lib/internal/main/eval_string.js +++ b/lib/internal/main/eval_string.js @@ -16,7 +16,7 @@ const { addBuiltinLibsToObject } = require('internal/modules/cjs/helpers'); const { getOptionValue } = require('internal/options'); prepareMainThreadExecution(); -addBuiltinLibsToObject(globalThis); +addBuiltinLibsToObject(globalThis, ''); markBootstrapComplete(); const source = getOptionValue('--eval'); diff --git a/lib/internal/modules/cjs/helpers.js b/lib/internal/modules/cjs/helpers.js index 1e85362a9449d9..bba572b32cb65d 100644 --- a/lib/internal/modules/cjs/helpers.js +++ b/lib/internal/modules/cjs/helpers.js @@ -131,9 +131,16 @@ function stripBOM(content) { return content; } -function addBuiltinLibsToObject(object) { +function addBuiltinLibsToObject(object, dummyModuleName) { // Make built-in modules available directly (loaded lazily). - const { builtinModules } = require('internal/modules/cjs/loader').Module; + const Module = require('internal/modules/cjs/loader').Module; + const { builtinModules } = Module; + + // To require built-in modules in user-land and ignore modules whose + // `canBeRequiredByUsers` is false. So we create a dummy module object and not + // use `require()` directly. + const dummyModule = new Module(dummyModuleName); + ArrayPrototypeForEach(builtinModules, (name) => { // Neither add underscored modules, nor ones that contain slashes (e.g., // 'fs/promises') or ones that are already defined. @@ -157,7 +164,7 @@ function addBuiltinLibsToObject(object) { ObjectDefineProperty(object, name, { get: () => { - const lib = require(name); + const lib = dummyModule.require(name); // Disable the current getter/setter and set up a new // non-enumerable property. diff --git a/lib/repl.js b/lib/repl.js index 19011841519351..7ebfd91fd28999 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -1098,7 +1098,7 @@ REPLServer.prototype.createContext = function() { value: makeRequireFunction(replModule) }); - addBuiltinLibsToObject(context); + addBuiltinLibsToObject(context, ''); return context; }; diff --git a/test/parallel/test-repl-built-in-modules.js b/test/parallel/test-repl-built-in-modules.js new file mode 100644 index 00000000000000..f88b695c0f6177 --- /dev/null +++ b/test/parallel/test-repl-built-in-modules.js @@ -0,0 +1,32 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const cp = require('child_process'); + +function runREPLWithAdditionalFlags(flags) { + // Use -i to force node into interactive mode, despite stdout not being a TTY + const args = ['-i'].concat(flags); + const ret = cp.execFileSync(process.execPath, args, { + input: 'require(\'events\');\nrequire(\'wasi\');', + encoding: 'utf8', + }); + return ret; +} + +// Run REPL in normal mode. +let stdout = runREPLWithAdditionalFlags([]); +assert.match(stdout, /\[Function: EventEmitter\] {/); +assert.match( + stdout, + /Uncaught Error: Cannot find module 'wasi'[\w\W]+- \n/); + +// Run REPL with '--experimental-wasi-unstable-preview1' +stdout = runREPLWithAdditionalFlags([ + '--experimental-wasi-unstable-preview1', +]); +assert.match(stdout, /\[Function: EventEmitter\] {/); +assert.doesNotMatch( + stdout, + /Uncaught Error: Cannot find module 'wasi'[\w\W]+- \n/) +assert.match(stdout, /{ WASI: \[class WASI\] }/);