@ -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 . runInThis Context ( 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 < name > ( ) 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 ;
} ;