diff --git a/doc/api/repl.markdown b/doc/api/repl.markdown index c0b9789e1b48..7bce1f7e50f7 100644 --- a/doc/api/repl.markdown +++ b/doc/api/repl.markdown @@ -83,28 +83,12 @@ The special variable `_` (underscore) contains the result of the last expression > _ += 1 4 -The REPL provides access to any variables in the global scope. You can expose -a variable to the REPL explicitly by assigning it to the `context` object -associated with each `REPLServer`. For example: - - // repl_test.js - var repl = require("repl"), - msg = "message"; - - repl.start().context.m = msg; - -Things in the `context` object appear as local within the REPL: - - mjr:~$ node repl_test.js - > m - 'message' +The REPL provides access to any variables in the global scope. There are a few special REPL commands: - `.break` - While inputting a multi-line expression, sometimes you get lost or just don't care about completing it. `.break` will start over. - - `.clear` - Resets the `context` object to an empty object and clears any - multi-line expression. - `.exit` - Close the I/O stream, which will cause the REPL to exit. - `.help` - Show this list of special commands. diff --git a/lib/repl.js b/lib/repl.js index 3da7b61e4ff4..0ac6bc5217df 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -46,6 +46,10 @@ var path = require('path'); var fs = require('fs'); var rl = require('readline'); +global.module = module; +global.exports = exports; +global.require = require; + // If obj.hasOwnProperty has been overridden, then calling // obj.hasOwnProperty(prop) will break. // See: https://github.com/joyent/node/issues/1707 @@ -53,9 +57,6 @@ function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } - -var context; - exports.disableColors = process.env.NODE_DISABLE_COLORS ? true : false; // hack for require.resolve("./relative") to work properly. @@ -71,16 +72,27 @@ exports.writer = util.inspect; function REPLServer(prompt, stream, eval) { var self = this; - self.eval = eval || function(code, context, file, cb) { + var contextWarning; + Object.defineProperty(this, 'context', { + get: function() { + if (!contextWarning) { + contextWarning = 'repl.context is deprecated.'; + console.error(contextWarning); + } + return global; + } + }); + + + self.eval = eval || function(code, file, cb) { try { - var err, result = vm.runInContext(code, context, file); + var err, result = vm.runInThisContext(code, file); } catch (e) { err = e; } cb(err, result); }; - self.resetContext(); self.bufferedCommand = ''; if (stream) { @@ -173,14 +185,13 @@ function REPLServer(prompt, stream, eval) { // First we attempt to eval as expression with parens. // This catches '{a : 1}' properly. self.eval('(' + evalCmd + ')', - self.context, 'repl', function(e, ret) { if (e && !isSyntaxError(e)) return finish(e); if (typeof ret === 'function' || e) { // Now as statement without parens. - self.eval(evalCmd, self.context, 'repl', finish); + self.eval(evalCmd, 'repl', finish); } else { finish(null, ret); } @@ -218,7 +229,7 @@ function REPLServer(prompt, stream, eval) { // If we got any output - print it (if no error) if (!e && ret !== undefined) { - self.context._ = ret; + global._ = ret; self.outputStream.write(exports.writer(ret) + '\n'); } @@ -245,25 +256,12 @@ exports.start = function(prompt, source, eval) { }; -REPLServer.prototype.createContext = function() { - var context = vm.createContext(); - - for (var i in global) context[i] = global[i]; - context.module = module; - context.require = require; - context.global = context; - context.global.global = context; - - return context; -}; - +var resetWarning; REPLServer.prototype.resetContext = function(force) { - if (!context || force) { - context = this.createContext(); - for (var i in require.cache) delete require.cache[i]; + if (!resetWarning) { + resetWarning = 'REPLServer.resetContext is deprecated.'; + console.error(resetWarning); } - - this.context = context; }; REPLServer.prototype.displayPrompt = function() { @@ -413,26 +411,9 @@ REPLServer.prototype.complete = function(line, callback) { if (!expr) { // If context is instance of vm.ScriptContext // Get global vars synchronously - if (this.context.constructor.name === 'Context') { - completionGroups.push(Object.getOwnPropertyNames(this.context)); - addStandardGlobals(); - completionGroupsLoaded(); - } else { - this.eval('.scope', this.context, 'repl', function(err, globals) { - if (err || !globals) { - addStandardGlobals(); - } else if (Array.isArray(globals[0])) { - // Add grouped globals - globals.forEach(function(group) { - completionGroups.push(group); - }); - } else { - completionGroups.push(globals); - addStandardGlobals(); - } - completionGroupsLoaded(); - }); - } + completionGroups.push(Object.getOwnPropertyNames(global)); + addStandardGlobals(); + completionGroupsLoaded(); function addStandardGlobals() { // Global object properties @@ -457,7 +438,7 @@ REPLServer.prototype.complete = function(line, callback) { } } else { - this.eval(expr, this.context, 'repl', function(e, obj) { + this.eval(expr, 'repl', function(e, obj) { // if (e) console.log(e); if (obj != null) { @@ -584,16 +565,6 @@ function defineDefaultCommands(repl) { } }); - repl.defineCommand('clear', { - help: 'Break, and also clear the local context', - action: function() { - this.outputStream.write('Clearing context...\n'); - this.bufferedCommand = ''; - this.resetContext(true); - this.displayPrompt(); - } - }); - repl.defineCommand('exit', { help: 'Exit the repl', action: function() { @@ -628,32 +599,3 @@ function trimWhitespace(cmd) { function regexpEscape(s) { return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); } - - -/** - * Converts commands that use var and function () to use the - * local exports.context when evaled. This provides a local context - * on the REPL. - * - * @param {String} cmd The cmd to convert. - * @return {String} The converted command. - */ -REPLServer.prototype.convertToContext = function(cmd) { - var self = this, matches, - scopeVar = /^\s*var\s*([_\w\$]+)(.*)$/m, - scopeFunc = /^\s*function\s*([_\w\$]+)/; - - // Replaces: var foo = "bar"; with: self.context.foo = bar; - matches = scopeVar.exec(cmd); - if (matches && matches.length === 3) { - return 'self.context.' + matches[1] + matches[2]; - } - - // Replaces: function foo() {}; with: foo = function foo() {}; - matches = scopeFunc.exec(self.bufferedCommand); - if (matches && matches.length === 2) { - return matches[1] + ' = ' + self.bufferedCommand; - } - - return cmd; -}; diff --git a/test/common.js b/test/common.js index a906217823cb..a8ebb871f96e 100644 --- a/test/common.js +++ b/test/common.js @@ -123,6 +123,17 @@ process.on('exit', function() { knownGlobals.push(DataView); } + // repl pollution + if (global.hasOwnProperty('module')) { + knownGlobals.push(global.module); + } + if (global.hasOwnProperty('require')) { + knownGlobals.push(global.require); + } + if (global.hasOwnProperty('exports')) { + knownGlobals.push(global.exports); + } + for (var x in global) { var found = false;