Browse Source

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: https://github.com/nodejs/node/pull/6207
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
process-exit-stdio-flushing
Anna Henningsen 9 years ago
committed by James M Snell
parent
commit
39d905e293
  1. 3
      doc/api/cli.markdown
  2. 3
      lib/internal/bootstrap_node.js
  3. 35
      lib/internal/module.js
  4. 23
      lib/repl.js
  5. 7
      test/parallel/test-cli-eval.js

3
doc/api/cli.markdown

@ -36,7 +36,8 @@ The output of this option is less detailed than this document.
### `-e`, `--eval "script"` ### `-e`, `--eval "script"`
Evaluate the following argument as JavaScript. Evaluate the following argument as JavaScript. The modules which are
predefined in the REPL can also be used in `script`.
### `-p`, `--print "script"` ### `-p`, `--print "script"`

3
lib/internal/bootstrap_node.js

@ -105,6 +105,9 @@
// User passed '-e' or '--eval' arguments to Node without '-i' or // User passed '-e' or '--eval' arguments to Node without '-i' or
// '--interactive' // '--interactive'
preloadModules(); preloadModules();
const internalModule = NativeModule.require('internal/module');
internalModule.addBuiltinLibsToObject(global);
evalScript('[eval]'); evalScript('[eval]');
} else if (process.argv[1]) { } else if (process.argv[1]) {
// make process.argv[1] into a full path // make process.argv[1] into a full path

35
lib/internal/module.js

@ -1,6 +1,10 @@
'use strict'; 'use strict';
exports = module.exports = { makeRequireFunction, stripBOM }; exports = module.exports = {
makeRequireFunction,
stripBOM,
addBuiltinLibsToObject
};
exports.requireDepth = 0; exports.requireDepth = 0;
@ -46,3 +50,32 @@ function stripBOM(content) {
} }
return content; return content;
} }
exports.builtinLibs = ['assert', 'buffer', 'child_process', 'cluster',
'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net',
'os', 'path', 'punycode', 'querystring', 'readline', 'repl', 'stream',
'string_decoder', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'zlib'];
function addBuiltinLibsToObject(object) {
// Make built-in modules available directly (loaded lazily).
exports.builtinLibs.forEach((name) => {
Object.defineProperty(object, name, {
get: () => {
const lib = require(name);
// This implicitly invokes the setter, so that this getter is only
// invoked at most once and does not overwrite anything.
object[name] = lib;
return lib;
},
// Allow the creation of other globals with this name.
set: (val) => {
// Deleting the property before re-assigning it disables the
// getter/setter mechanism.
delete object[name];
object[name] = val;
},
configurable: true,
enumerable: false
});
});
}

23
lib/repl.js

@ -64,10 +64,7 @@ function hasOwnProperty(obj, prop) {
// This is the default "writer" value if none is passed in the REPL options. // This is the default "writer" value if none is passed in the REPL options.
exports.writer = util.inspect; exports.writer = util.inspect;
exports._builtinLibs = ['assert', 'buffer', 'child_process', 'cluster', exports._builtinLibs = internalModule.builtinLibs;
'crypto', 'dgram', 'dns', 'domain', 'events', 'fs', 'http', 'https', 'net',
'os', 'path', 'punycode', 'querystring', 'readline', 'stream',
'string_decoder', 'tls', 'tty', 'url', 'util', 'v8', 'vm', 'zlib'];
const BLOCK_SCOPED_ERROR = 'Block-scoped declarations (let, ' + const BLOCK_SCOPED_ERROR = 'Block-scoped declarations (let, ' +
@ -565,23 +562,7 @@ REPLServer.prototype.createContext = function() {
this.lines = []; this.lines = [];
this.lines.level = []; this.lines.level = [];
// make built-in modules available directly internalModule.addBuiltinLibsToObject(context);
// (loaded lazily)
exports._builtinLibs.forEach((name) => {
Object.defineProperty(context, name, {
get: () => {
var lib = require(name);
this.last = context[name] = lib;
return lib;
},
// allow the creation of other globals with this name
set: (val) => {
delete context[name];
context[name] = val;
},
configurable: true
});
});
Object.defineProperty(context, '_', { Object.defineProperty(context, '_', {
configurable: true, configurable: true,

7
test/parallel/test-cli-eval.js

@ -53,6 +53,13 @@ child.exec(nodejs + ' --eval "require(\'' + filename + '\')"',
assert.equal(status.code, 42); assert.equal(status.code, 42);
}); });
// Check that builtin modules are pre-defined.
child.exec(nodejs + ' --print "os.platform()"',
function(status, stdout, stderr) {
assert.strictEqual(stderr, '');
assert.strictEqual(stdout.trim(), require('os').platform());
});
// module path resolve bug, regression test // module path resolve bug, regression test
child.exec(nodejs + ' --eval "require(\'./test/parallel/test-cli-eval.js\')"', child.exec(nodejs + ' --eval "require(\'./test/parallel/test-cli-eval.js\')"',
function(status, stdout, stderr) { function(status, stdout, stderr) {

Loading…
Cancel
Save