repl: make REPL support multiline template literals

Let REPL enter multiline mode if user's input contains unterminated
template literals.

PR-URL: https://github.com/iojs/io.js/pull/333
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
This commit is contained in:
Xiaowei Li 2015-01-19 13:42:05 +08:00 коммит произвёл Ben Noordhuis
Родитель 2253d30d9c
Коммит b7365c1559
2 изменённых файлов: 32 добавлений и 6 удалений

Просмотреть файл

@ -87,6 +87,8 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
self.useGlobal = !!useGlobal;
self.ignoreUndefined = !!ignoreUndefined;
self._inTemplateLiteral = false;
// just for backwards compat, see github.com/joyent/node/pull/7127
self.rli = this;
@ -102,7 +104,7 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
});
} catch (e) {
debug('parse error %j', code, e);
if (isRecoverableError(e))
if (isRecoverableError(e, self))
err = new Recoverable(e);
else
err = e;
@ -226,7 +228,13 @@ function REPLServer(prompt, stream, eval_, useGlobal, ignoreUndefined) {
debug('line %j', cmd);
sawSIGINT = false;
var skipCatchall = false;
cmd = trimWhitespace(cmd);
// leading whitespaces in template literals should not be trimmed.
if (self._inTemplateLiteral) {
self._inTemplateLiteral = false;
} else {
cmd = trimWhitespace(cmd);
}
// Check to see if a REPL keyword was used. If it returns true,
// display next prompt and return.
@ -928,10 +936,17 @@ REPLServer.prototype.convertToContext = function(cmd) {
// If the error is that we've unexpectedly ended the input,
// then let the user try to recover by adding more input.
function isRecoverableError(e) {
return e &&
e.name === 'SyntaxError' &&
/^(Unexpected end of input|Unexpected token :)/.test(e.message);
function isRecoverableError(e, self) {
if (e && e.name === 'SyntaxError') {
var message = e.message;
if (message === 'Unterminated template literal' ||
message === 'Missing } in template expression') {
self._inTemplateLiteral = true;
return true;
}
return /^(Unexpected end of input|Unexpected token :)/.test(message);
}
return false;
}
function Recoverable(err) {

Просмотреть файл

@ -104,6 +104,17 @@ function error_test() {
// But passing the same string to eval() should throw
{ client: client_unix, send: 'eval("function test_func() {")',
expect: /^SyntaxError: Unexpected end of input/ },
// Can handle multiline template literals
{ client: client_unix, send: '`io.js',
expect: prompt_multiline },
// Special REPL commands still available
{ client: client_unix, send: '.break',
expect: prompt_unix },
// Template expressions can cross lines
{ client: client_unix, send: '`io.js ${"1.0"',
expect: prompt_multiline },
{ client: client_unix, send: '+ ".2"}`',
expect: `'io.js 1.0.2'\n${prompt_unix}` },
// Floating point numbers are not interpreted as REPL commands.
{ client: client_unix, send: '.1234',
expect: '0.1234' },