From 7b88a82e33a6bdab0027bbb2707f14c93652bac6 Mon Sep 17 00:00:00 2001 From: monkingxue Date: Wed, 9 May 2018 10:34:57 +0800 Subject: [PATCH 1/5] repl: add friendly tips about how to exit repl Imitate python repl, when the user enters 'exit' or 'quit', no longer prompt 'Reference Error', but prompts 'To exit, press ^D or type .exit'. If the user defines variables named 'exit' or 'quit' , only the value of the variables are output Fixes: https://github.com/nodejs/node/issues/19021 --- lib/repl.js | 32 ++++++++++++++++++++------------ test/parallel/test-repl.js | 24 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 600816a6058fbc..7c3e995e6fedc7 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -214,11 +214,16 @@ function REPLServer(prompt, } function defaultEval(code, context, file, cb) { - var err, result, script, wrappedErr; + var err, result, script, wrappedErr, trimCmd; + var isExitCmd = false; var wrappedCmd = false; var awaitPromise = false; var input = code; + if ((trimCmd = code.trim()) && (trimCmd === 'exit' || trimCmd === 'quit')) { + isExitCmd = true; + } + if (/^\s*\{/.test(code) && /\}\s*$/.test(code)) { // It's confusing for `{ a : 1 }` to be interpreted as a block // statement rather than an object literal. So, we first try @@ -331,18 +336,21 @@ function REPLServer(prompt, } } } catch (e) { - err = e; - - if (err && err.code === 'ERR_SCRIPT_EXECUTION_INTERRUPTED') { + if (isExitCmd) { + self.outputStream.write('(To exit, press ^D or type .exit)\n'); + return self.displayPrompt(); + } else { + err = e; + if (err && err.code === 'ERR_SCRIPT_EXECUTION_INTERRUPTED') { // The stack trace for this case is not very useful anyway. - Object.defineProperty(err, 'stack', { value: '' }); - } - - if (process.domain) { - debug('not recoverable, send to domain'); - process.domain.emit('error', err); - process.domain.exit(); - return; + Object.defineProperty(err, 'stack', { value: '' }); + } + if (process.domain) { + debug('not recoverable, send to domain'); + process.domain.emit('error', err); + process.domain.exit(); + return; + } } } diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index e14398541dd8de..b9c92c3cd63bc0 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -132,6 +132,29 @@ const strictModeTests = [ } ]; +const friendlyExitTests = [ + { + send: 'exit', + expect: '(To exit, press ^D or type .exit)' + }, + { + send: 'quit', + expect: '(To exit, press ^D or type .exit)' + }, + { + send: 'quit = 1', + expect: '1' + }, + { + send: 'quit', + expect: '1' + }, + { + send: 'exit', + expect: '(To exit, press ^D or type .exit)' + }, +]; + const errorTests = [ // Uncaught error throws and prints out { @@ -742,6 +765,7 @@ const tcpTests = [ const [ socket, replServer ] = await startUnixRepl(); await runReplTests(socket, prompt_unix, unixTests); + await runReplTests(socket, prompt_unix, friendlyExitTests); await runReplTests(socket, prompt_unix, errorTests); replServer.replMode = repl.REPL_MODE_STRICT; await runReplTests(socket, prompt_unix, strictModeTests); From 17e127267370681b52fd983dcdb2de057c79d6f1 Mon Sep 17 00:00:00 2001 From: monkingxue Date: Thu, 10 May 2018 10:46:42 +0800 Subject: [PATCH 2/5] style: fix the code style --- lib/repl.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 7c3e995e6fedc7..0ee5ba15517781 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -214,14 +214,15 @@ function REPLServer(prompt, } function defaultEval(code, context, file, cb) { - var err, result, script, wrappedErr, trimCmd; - var isExitCmd = false; + var err, result, script, wrappedErr; + var isExitCommand = false; var wrappedCmd = false; var awaitPromise = false; var input = code; + var trimCommand = code.trim(); - if ((trimCmd = code.trim()) && (trimCmd === 'exit' || trimCmd === 'quit')) { - isExitCmd = true; + if ((trimCommand === 'exit' || trimCommand === 'quit')) { + isExitCommand = true; } if (/^\s*\{/.test(code) && /\}\s*$/.test(code)) { @@ -336,21 +337,20 @@ function REPLServer(prompt, } } } catch (e) { - if (isExitCmd) { + if (isExitCommand) { self.outputStream.write('(To exit, press ^D or type .exit)\n'); return self.displayPrompt(); - } else { - err = e; - if (err && err.code === 'ERR_SCRIPT_EXECUTION_INTERRUPTED') { - // The stack trace for this case is not very useful anyway. - Object.defineProperty(err, 'stack', { value: '' }); - } - if (process.domain) { - debug('not recoverable, send to domain'); - process.domain.emit('error', err); - process.domain.exit(); - return; - } + } + err = e; + if (err && err.code === 'ERR_SCRIPT_EXECUTION_INTERRUPTED') { + // The stack trace for this case is not very useful anyway. + Object.defineProperty(err, 'stack', { value: '' }); + } + if (process.domain) { + debug('not recoverable, send to domain'); + process.domain.emit('error', err); + process.domain.exit(); + return; } } From 51282ef33eca2ba0c8bdbcaa798ffc9dd0b8dead Mon Sep 17 00:00:00 2001 From: monkingxue Date: Fri, 11 May 2018 01:50:08 +0800 Subject: [PATCH 3/5] fix: duplication of command name and variable name Before output the hint, check if defined the command-named variable as an error --- lib/repl.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/repl.js b/lib/repl.js index 0ee5ba15517781..42fcb861aa25a5 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -337,7 +337,8 @@ function REPLServer(prompt, } } } catch (e) { - if (isExitCommand) { + const context = this.useGlobal ? global : this.context; + if (isExitCommand && !context.hasOwnProperty(trimCommand)) { self.outputStream.write('(To exit, press ^D or type .exit)\n'); return self.displayPrompt(); } From 93c16470ed197d4ade507da5a63992c70f263459 Mon Sep 17 00:00:00 2001 From: monkingxue Date: Fri, 11 May 2018 15:02:15 +0800 Subject: [PATCH 4/5] fix: move the check of variables' name to before the command run --- lib/repl.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 42fcb861aa25a5..24c917823aa05e 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -319,10 +319,16 @@ function REPLServer(prompt, breakOnSigint: self.breakEvalOnSigint }; + const localContext = self.useGlobal ? global : self.context; + if (isExitCommand && !localContext.hasOwnProperty(trimCommand)) { + self.outputStream.write('(To exit, press ^D or type .exit)\n'); + return self.displayPrompt(); + } + if (self.useGlobal) { result = script.runInThisContext(scriptOptions); } else { - result = script.runInContext(context, scriptOptions); + result = script.runInContext(localContext, scriptOptions); } } finally { if (self.breakEvalOnSigint) { @@ -337,11 +343,6 @@ function REPLServer(prompt, } } } catch (e) { - const context = this.useGlobal ? global : this.context; - if (isExitCommand && !context.hasOwnProperty(trimCommand)) { - self.outputStream.write('(To exit, press ^D or type .exit)\n'); - return self.displayPrompt(); - } err = e; if (err && err.code === 'ERR_SCRIPT_EXECUTION_INTERRUPTED') { // The stack trace for this case is not very useful anyway. From de3385af1b49dbac8145f654299ecf9b5880371e Mon Sep 17 00:00:00 2001 From: monkingxue Date: Fri, 18 May 2018 12:42:56 +0800 Subject: [PATCH 5/5] style --- lib/repl.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 24c917823aa05e..928e7c6d69cfae 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -219,9 +219,9 @@ function REPLServer(prompt, var wrappedCmd = false; var awaitPromise = false; var input = code; - var trimCommand = code.trim(); + var trimmedCommand = code.trim(); - if ((trimCommand === 'exit' || trimCommand === 'quit')) { + if (trimmedCommand === 'exit' || trimmedCommand === 'quit') { isExitCommand = true; } @@ -320,7 +320,7 @@ function REPLServer(prompt, }; const localContext = self.useGlobal ? global : self.context; - if (isExitCommand && !localContext.hasOwnProperty(trimCommand)) { + if (isExitCommand && !localContext.hasOwnProperty(trimmedCommand)) { self.outputStream.write('(To exit, press ^D or type .exit)\n'); return self.displayPrompt(); }