From 457f24f19c6fc1f14df8d2fa9554bc9f1bdd5eb2 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 15 Apr 2016 02:03:12 +0200 Subject: [PATCH] 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 Reviewed-By: Colin Ihrig --- doc/api/cli.markdown | 3 ++- lib/internal/bootstrap_node.js | 3 +++ lib/internal/module.js | 35 +++++++++++++++++++++++++++++++++- lib/repl.js | 23 ++-------------------- test/parallel/test-cli-eval.js | 7 +++++++ 5 files changed, 48 insertions(+), 23 deletions(-) diff --git a/doc/api/cli.markdown b/doc/api/cli.markdown index 13e8a396e40c2a..3752e9ab4779cb 100644 --- a/doc/api/cli.markdown +++ b/doc/api/cli.markdown @@ -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"` diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index c3cb24d3485e53..30f05e90e7c792 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -94,6 +94,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 diff --git a/lib/internal/module.js b/lib/internal/module.js index 29f88999dbf72f..10ab0bb0c0a979 100644 --- a/lib/internal/module.js +++ b/lib/internal/module.js @@ -1,6 +1,10 @@ 'use strict'; -exports = module.exports = { makeRequireFunction, stripBOM }; +exports = module.exports = { + makeRequireFunction, + stripBOM, + addBuiltinLibsToObject +}; exports.requireDepth = 0; @@ -44,3 +48,32 @@ 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) => { + 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 + }); + }); +} diff --git a/lib/repl.js b/lib/repl.js index e63016e526d36c..baa41a85a7d248 100644 --- a/lib/repl.js +++ b/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. 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, const, function, ' + @@ -559,23 +556,7 @@ REPLServer.prototype.createContext = function() { this.lines = []; this.lines.level = []; - // make built-in modules available directly - // (loaded lazily) - exports._builtinLibs.forEach(function(name) { - Object.defineProperty(context, name, { - get: function() { - var lib = require(name); - context._ = context[name] = lib; - return lib; - }, - // allow the creation of other globals with this name - set: function(val) { - delete context[name]; - context[name] = val; - }, - configurable: true - }); - }); + internalModule.addBuiltinLibsToObject(context); return context; }; diff --git a/test/parallel/test-cli-eval.js b/test/parallel/test-cli-eval.js index d1db3a815f5df5..a58c023eb6d835 100644 --- a/test/parallel/test-cli-eval.js +++ b/test/parallel/test-cli-eval.js @@ -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) {