|
|
@ -171,43 +171,36 @@ function REPLServer(prompt, stream) { |
|
|
|
e.constructor.name === 'SyntaxError')) { |
|
|
|
finish(e); |
|
|
|
} else { |
|
|
|
tryExpr(); |
|
|
|
tryExpr(e); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (typeof ret !== 'function') { |
|
|
|
return tryExpr(ret); |
|
|
|
} |
|
|
|
|
|
|
|
tryExpr(); |
|
|
|
tryExpr(typeof ret === 'function', ret); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
// Now as statement without parens.
|
|
|
|
function tryExpr(ret) { |
|
|
|
|
|
|
|
self.bufferedCommand = ''; |
|
|
|
|
|
|
|
if (ret !== undefined) { |
|
|
|
self.context._ = ret; |
|
|
|
self.outputStream.write(exports.writer(ret) + '\n'); |
|
|
|
return finish(null); |
|
|
|
} |
|
|
|
function tryExpr(e, ret) { |
|
|
|
if (!e) return finish(null, ret); |
|
|
|
|
|
|
|
self.eval(self.bufferedCommand, self.context, |
|
|
|
'repl', function(e, ret) { |
|
|
|
|
|
|
|
if (e) { |
|
|
|
// instanceof doesn't work across context switches.
|
|
|
|
if (!(e && e.constructor && e.constructor.name === 'SyntaxError')) { |
|
|
|
if (!(e && e.constructor && |
|
|
|
e.constructor.name === 'SyntaxError')) { |
|
|
|
return finish(e); |
|
|
|
// It could also be an error from JSON.parse
|
|
|
|
// It could also be an error from JSON.parse
|
|
|
|
} else if (e && |
|
|
|
e.stack && |
|
|
|
e.stack.match(/^SyntaxError: Unexpected token .*\n/) && |
|
|
|
e.stack.match(/\n at Object.parse \(native\)\n/)) { |
|
|
|
return finish(e); |
|
|
|
} else { |
|
|
|
finish(true); |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
finish(null, ret); |
|
|
@ -222,12 +215,23 @@ function REPLServer(prompt, stream) { |
|
|
|
if (e) { |
|
|
|
if (e.stack) { |
|
|
|
self.outputStream.write(e.stack + '\n'); |
|
|
|
} else if (e === true) { |
|
|
|
self.displayPrompt(); |
|
|
|
return; |
|
|
|
} else { |
|
|
|
self.outputStream.write(e.toString() + '\n'); |
|
|
|
} |
|
|
|
// On error: Print the error and clear the buffer
|
|
|
|
self.bufferedCommand = ''; |
|
|
|
} else { |
|
|
|
self.bufferedCommand = ''; |
|
|
|
} |
|
|
|
|
|
|
|
if (ret !== undefined) { |
|
|
|
self.context._ = ret; |
|
|
|
self.outputStream.write(exports.writer(ret) + '\n'); |
|
|
|
} |
|
|
|
|
|
|
|
self.displayPrompt(); |
|
|
|
}; |
|
|
|
}); |
|
|
@ -413,25 +417,48 @@ REPLServer.prototype.complete = function(line, callback) { |
|
|
|
// Resolve expr and get its completions.
|
|
|
|
var obj, memberGroups = []; |
|
|
|
if (!expr) { |
|
|
|
completionGroups.push(Object.getOwnPropertyNames(this.context)); |
|
|
|
// Global object properties
|
|
|
|
// (http://www.ecma-international.org/publications/standards/Ecma-262.htm)
|
|
|
|
completionGroups.push(['NaN', 'Infinity', 'undefined', |
|
|
|
'eval', 'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'decodeURI', |
|
|
|
'decodeURIComponent', 'encodeURI', 'encodeURIComponent', |
|
|
|
'Object', 'Function', 'Array', 'String', 'Boolean', 'Number', |
|
|
|
'Date', 'RegExp', 'Error', 'EvalError', 'RangeError', |
|
|
|
'ReferenceError', 'SyntaxError', 'TypeError', 'URIError', |
|
|
|
'Math', 'JSON']); |
|
|
|
// Common keywords. Exclude for completion on the empty string, b/c
|
|
|
|
// they just get in the way.
|
|
|
|
if (filter) { |
|
|
|
completionGroups.push(['break', 'case', 'catch', 'const', |
|
|
|
'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export', |
|
|
|
'false', 'finally', 'for', 'function', 'if', 'import', 'in', |
|
|
|
'instanceof', 'let', 'new', 'null', 'return', 'switch', 'this', |
|
|
|
'throw', 'true', 'try', 'typeof', 'undefined', 'var', 'void', |
|
|
|
'while', 'with', 'yield']); |
|
|
|
if (this.context.constructor.name === 'Context') { |
|
|
|
completionGroups.push(Object.getOwnPropertyNames(this.context)); |
|
|
|
next(); |
|
|
|
} else { |
|
|
|
this.eval('.scope', this.context, 'repl', function(err, globals) { |
|
|
|
if (Array.isArray(globals[0])) { |
|
|
|
// Add grouped globals
|
|
|
|
globals.forEach(function(group) { |
|
|
|
completionGroups.push(group); |
|
|
|
}); |
|
|
|
finish(); |
|
|
|
} else { |
|
|
|
completionGroups.push(globals); |
|
|
|
next(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
function next() { |
|
|
|
// Global object properties
|
|
|
|
// (http://www.ecma-international.org/publications/standards/Ecma-262.htm)
|
|
|
|
completionGroups.push(['NaN', 'Infinity', 'undefined', |
|
|
|
'eval', 'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'decodeURI', |
|
|
|
'decodeURIComponent', 'encodeURI', 'encodeURIComponent', |
|
|
|
'Object', 'Function', 'Array', 'String', 'Boolean', 'Number', |
|
|
|
'Date', 'RegExp', 'Error', 'EvalError', 'RangeError', |
|
|
|
'ReferenceError', 'SyntaxError', 'TypeError', 'URIError', |
|
|
|
'Math', 'JSON']); |
|
|
|
// Common keywords. Exclude for completion on the empty string, b/c
|
|
|
|
// they just get in the way.
|
|
|
|
if (filter) { |
|
|
|
completionGroups.push(['break', 'case', 'catch', 'const', |
|
|
|
'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export', |
|
|
|
'false', 'finally', 'for', 'function', 'if', 'import', 'in', |
|
|
|
'instanceof', 'let', 'new', 'null', 'return', 'switch', 'this', |
|
|
|
'throw', 'true', 'try', 'typeof', 'undefined', 'var', 'void', |
|
|
|
'while', 'with', 'yield']); |
|
|
|
} |
|
|
|
|
|
|
|
finish(); |
|
|
|
} |
|
|
|
} else { |
|
|
|
this.eval(expr, this.context, 'repl', function(e, obj) { |
|
|
|