Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

node: Make builtin libs available for --eval #6207

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc/api/cli.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ The output of this option is less detailed than this document.

### `-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"`
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/bootstrap_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@
// User passed '-e' or '--eval' arguments to Node without '-i' or
// '--interactive'
preloadModules();

const internalModule = NativeModule.require('internal/module');
internalModule.addBuiltinLibsToObject(global);
evalScript('[eval]');
} else if (process.argv[1]) {
// make process.argv[1] into a full path
Expand Down
50 changes: 49 additions & 1 deletion lib/internal/module.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
'use strict';

exports = module.exports = { makeRequireFunction, stripBOM };
exports = module.exports = {
makeRequireFunction,
stripBOM,
addBuiltinLibsToObject
};

exports.requireDepth = 0;

Expand Down Expand Up @@ -46,3 +50,47 @@ function stripBOM(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) => {
// Goals of this mechanism are:
// - Lazy loading of built-in modules
// - Having all built-in modules available as non-enumerable properties
// - Allowing the user to re-assign these variables as if there were no
// pre-existing globals with the same name.

const setReal = (val) => {
// Deleting the property before re-assigning it disables the
// getter/setter mechanism.
delete object[name];
object[name] = val;
};

Object.defineProperty(object, name, {
get: () => {
const lib = require(name);

// Disable the current getter/setter and set up a new
// non-enumerable property.
delete object[name];
Object.defineProperty(object, name, {
get: () => lib,
set: setReal,
configurable: true,
enumerable: false
});

return lib;
},
set: setReal,
configurable: true,
enumerable: false
});
});
}
23 changes: 2 additions & 21 deletions lib/repl.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,7 @@ function hasOwnProperty(obj, prop) {
// This is the default "writer" value if none is passed in the REPL options.
exports.writer = util.inspect;

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


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

// make built-in modules available directly
// (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
});
});
internalModule.addBuiltinLibsToObject(context);

Object.defineProperty(context, '_', {
configurable: true,
Expand Down
7 changes: 7 additions & 0 deletions test/parallel/test-cli-eval.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ child.exec(nodejs + ' --eval "require(\'' + filename + '\')"',
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
child.exec(nodejs + ' --eval "require(\'./test/parallel/test-cli-eval.js\')"',
function(status, stdout, stderr) {
Expand Down