Skip to content

Commit 39d905e

Browse files
addaleaxjasnell
authored andcommitted
node: make builtin libs available for --eval
Make the builtin libraries available for the `--eval` and `--print` CLI options, using the same mechanism that the REPL uses. This renders workarounds like `node -e 'require("fs").doStuff()'` unnecessary. As part of this, the list of builtin modules and the code for adding the corresponding properties to the target context is moved to `internal/module.js`, and the previously missing `repl` entry is added. PR-URL: #6207 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent 15d970d commit 39d905e

File tree

5 files changed

+48
-23
lines changed

5 files changed

+48
-23
lines changed

doc/api/cli.markdown

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ The output of this option is less detailed than this document.
3636

3737
### `-e`, `--eval "script"`
3838

39-
Evaluate the following argument as JavaScript.
39+
Evaluate the following argument as JavaScript. The modules which are
40+
predefined in the REPL can also be used in `script`.
4041

4142

4243
### `-p`, `--print "script"`

lib/internal/bootstrap_node.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@
105105
// User passed '-e' or '--eval' arguments to Node without '-i' or
106106
// '--interactive'
107107
preloadModules();
108+
109+
const internalModule = NativeModule.require('internal/module');
110+
internalModule.addBuiltinLibsToObject(global);
108111
evalScript('[eval]');
109112
} else if (process.argv[1]) {
110113
// make process.argv[1] into a full path

lib/internal/module.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
'use strict';
22

3-
exports = module.exports = { makeRequireFunction, stripBOM };
3+
exports = module.exports = {
4+
makeRequireFunction,
5+
stripBOM,
6+
addBuiltinLibsToObject
7+
};
48

59
exports.requireDepth = 0;
610

@@ -46,3 +50,32 @@ function stripBOM(content) {
4650
}
4751
return content;
4852
}
53+
54+
exports.builtinLibs = ['assert', 'buffer', 'child_process', 'cluster',
55+
'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net',
56+
'os', 'path', 'punycode', 'querystring', 'readline', 'repl', 'stream',
57+
'string_decoder', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'zlib'];
58+
59+
function addBuiltinLibsToObject(object) {
60+
// Make built-in modules available directly (loaded lazily).
61+
exports.builtinLibs.forEach((name) => {
62+
Object.defineProperty(object, name, {
63+
get: () => {
64+
const lib = require(name);
65+
// This implicitly invokes the setter, so that this getter is only
66+
// invoked at most once and does not overwrite anything.
67+
object[name] = lib;
68+
return lib;
69+
},
70+
// Allow the creation of other globals with this name.
71+
set: (val) => {
72+
// Deleting the property before re-assigning it disables the
73+
// getter/setter mechanism.
74+
delete object[name];
75+
object[name] = val;
76+
},
77+
configurable: true,
78+
enumerable: false
79+
});
80+
});
81+
}

lib/repl.js

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,7 @@ function hasOwnProperty(obj, prop) {
6464
// This is the default "writer" value if none is passed in the REPL options.
6565
exports.writer = util.inspect;
6666

67-
exports._builtinLibs = ['assert', 'buffer', 'child_process', 'cluster',
68-
'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net',
69-
'os', 'path', 'punycode', 'querystring', 'readline', 'stream',
70-
'string_decoder', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'zlib'];
67+
exports._builtinLibs = internalModule.builtinLibs;
7168

7269

7370
const BLOCK_SCOPED_ERROR = 'Block-scoped declarations (let, ' +
@@ -565,23 +562,7 @@ REPLServer.prototype.createContext = function() {
565562
this.lines = [];
566563
this.lines.level = [];
567564

568-
// make built-in modules available directly
569-
// (loaded lazily)
570-
exports._builtinLibs.forEach((name) => {
571-
Object.defineProperty(context, name, {
572-
get: () => {
573-
var lib = require(name);
574-
this.last = context[name] = lib;
575-
return lib;
576-
},
577-
// allow the creation of other globals with this name
578-
set: (val) => {
579-
delete context[name];
580-
context[name] = val;
581-
},
582-
configurable: true
583-
});
584-
});
565+
internalModule.addBuiltinLibsToObject(context);
585566

586567
Object.defineProperty(context, '_', {
587568
configurable: true,

test/parallel/test-cli-eval.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ child.exec(nodejs + ' --eval "require(\'' + filename + '\')"',
5353
assert.equal(status.code, 42);
5454
});
5555

56+
// Check that builtin modules are pre-defined.
57+
child.exec(nodejs + ' --print "os.platform()"',
58+
function(status, stdout, stderr) {
59+
assert.strictEqual(stderr, '');
60+
assert.strictEqual(stdout.trim(), require('os').platform());
61+
});
62+
5663
// module path resolve bug, regression test
5764
child.exec(nodejs + ' --eval "require(\'./test/parallel/test-cli-eval.js\')"',
5865
function(status, stdout, stderr) {

0 commit comments

Comments
 (0)