Update how REPLServer uses contexts

* Always use `this.context` or `self.context`.
* Move `resetContext` to `REPLServer.createContext`.
* Add `REPLServer.resetContext`, memoize `context` here.
* Memoize `exports.repl` in `start`.

Closes GH-851.
This commit is contained in:
Ben Weaver 2011-03-29 14:08:39 -04:00 committed by Ryan Dahl
parent bfa9db9dd6
commit d63a551f86

View File

@ -60,27 +60,14 @@ module.filename = process.cwd() + '/repl';
// hack for repl require to work properly with node_modules folders // hack for repl require to work properly with node_modules folders
module.paths = require('module')._nodeModulePaths(module.filename); module.paths = require('module')._nodeModulePaths(module.filename);
function resetContext() {
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;
for (var i in require.cache) delete require.cache[i];
}
// Can overridden with custom print functions, such as `probe` or `eyes.js` // Can overridden with custom print functions, such as `probe` or `eyes.js`
exports.writer = util.inspect; exports.writer = util.inspect;
function REPLServer(prompt, stream) { function REPLServer(prompt, stream) {
var self = this; var self = this;
if (!context) resetContext();
if (!exports.repl) exports.repl = this; self.resetContext();
self.context = context;
self.bufferedCommand = ''; self.bufferedCommand = '';
if (stream) { if (stream) {
@ -159,7 +146,7 @@ function REPLServer(prompt, stream) {
// First we attempt to eval as expression with parens. // First we attempt to eval as expression with parens.
// This catches '{a : 1}' properly. // This catches '{a : 1}' properly.
ret = vm.runInContext('(' + self.bufferedCommand + ')', ret = vm.runInContext('(' + self.bufferedCommand + ')',
context, self.context,
'repl'); 'repl');
if (typeof ret !== 'function') success = true; if (typeof ret !== 'function') success = true;
} catch (e) { } catch (e) {
@ -168,11 +155,11 @@ function REPLServer(prompt, stream) {
if (!success) { if (!success) {
// Now as statement without parens. // Now as statement without parens.
ret = vm.runInContext(self.bufferedCommand, context, 'repl'); ret = vm.runInContext(self.bufferedCommand, self.context, 'repl');
} }
if (ret !== undefined) { if (ret !== undefined) {
context._ = ret; self.context._ = ret;
self.outputStream.write(exports.writer(ret) + '\n'); self.outputStream.write(exports.writer(ret) + '\n');
} }
@ -215,10 +202,33 @@ exports.REPLServer = REPLServer;
// prompt is a string to print on each line for the prompt, // prompt is a string to print on each line for the prompt,
// source is a stream to use for I/O, defaulting to stdin/stdout. // source is a stream to use for I/O, defaulting to stdin/stdout.
exports.start = function(prompt, source) { exports.start = function(prompt, source) {
return new REPLServer(prompt, source); var repl = new REPLServer(prompt, source);
if (!exports.repl) exports.repl = repl;
return repl;
}; };
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;
};
REPLServer.prototype.resetContext = function(force) {
if (!context || force) {
context = this.createContext();
for (var i in require.cache) delete require.cache[i];
}
this.context = context;
};
REPLServer.prototype.displayPrompt = function() { REPLServer.prototype.displayPrompt = function() {
this.rli.setPrompt(this.bufferedCommand.length ? '... ' : this.prompt); this.rli.setPrompt(this.bufferedCommand.length ? '... ' : this.prompt);
this.rli.prompt(); this.rli.prompt();
@ -503,7 +513,7 @@ function defineDefaultCommands(repl) {
action: function() { action: function() {
this.outputStream.write('Clearing context...\n'); this.outputStream.write('Clearing context...\n');
this.bufferedCommand = ''; this.bufferedCommand = '';
resetContext(); this.resetContext(true);
this.displayPrompt(); this.displayPrompt();
} }
}); });