From 969b0b74e05cc405793812fa7e09e649148ac32a Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 24 Feb 2020 18:57:19 +0100 Subject: [PATCH] repl: align preview with the actual executed code This adds preview output for input that may not be wrapped. PR-URL: https://github.com/nodejs/node/pull/32154 Reviewed-By: Shelley Vohr Reviewed-By: James M Snell --- lib/internal/repl/utils.js | 25 ++++++++++++++++++++----- test/parallel/test-repl-preview.js | 8 +++++++- test/parallel/test-repl.js | 22 ++++++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/lib/internal/repl/utils.js b/lib/internal/repl/utils.js index 49a40e3030a3e2..476760a08d5934 100644 --- a/lib/internal/repl/utils.js +++ b/lib/internal/repl/utils.js @@ -136,6 +136,8 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { let previewCompletionCounter = 0; let completionPreview = null; + let wrapped = false; + function getPreviewPos() { const displayPos = repl._getDisplayPos(`${repl._prompt}${repl.line}`); const cursorPos = repl.line.length !== repl.cursor ? @@ -244,8 +246,9 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { function getInputPreview(input, callback) { // For similar reasons as `defaultEval`, wrap expressions starting with a // curly brace with parenthesis. - if (input.startsWith('{') && !input.endsWith(';')) { + if (input.startsWith('{') && !input.endsWith(';') && !wrapped) { input = `(${input})`; + wrapped = true; } sendInspectorCommand((session) => { session.post('Runtime.evaluate', { @@ -329,13 +332,19 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { return; } - getInputPreview(line, (error, inspected) => { + const inputPreviewCallback = (error, inspected) => { + if (inspected === null) { + return; + } + + wrapped = false; + // Ignore the output if the value is identical to the current line and the // former preview is not identical to this preview. - if ((line === inspected && lastInputPreview !== inspected) || - inspected === null) { + if (line === inspected && lastInputPreview !== inspected) { return; } + if (error) { debug('Error while generating preview', error); return; @@ -386,7 +395,13 @@ function setupPreview(repl, contextSymbol, bufferSymbol, active) { repl.output.write(`\n${result}`); cursorTo(repl.output, cursorPos.cols); moveCursor(repl.output, 0, -rows - 1); - }); + }; + + getInputPreview(line, inputPreviewCallback); + if (wrapped) { + getInputPreview(line, inputPreviewCallback); + } + wrapped = false; }; // -------------------------------------------------------------------------// diff --git a/test/parallel/test-repl-preview.js b/test/parallel/test-repl-preview.js index b36b99cca7c40e..185052b9b7ce45 100644 --- a/test/parallel/test-repl-preview.js +++ b/test/parallel/test-repl-preview.js @@ -125,7 +125,13 @@ async function tests(options) { '\x1B[90m{ a: true }\x1B[39m\x1B[20G\x1B[1A\x1B[1B\x1B[2K\x1B[1A;', '\x1B[90mtrue\x1B[39m\x1B[21G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', '\x1B[33mtrue\x1B[39m', - '\x1B[1G\x1B[0Jrepl > \x1B[8G'] + '\x1B[1G\x1B[0Jrepl > \x1B[8G'], + ['{};1', [2, 4], '\x1B[33m1\x1B[39m', + '{};1', + '\x1B[90m1\x1B[39m\x1B[12G\x1B[1A\x1B[1B\x1B[2K\x1B[1A\r', + '\x1B[33m1\x1B[39m', + '\x1B[1G\x1B[0Jrepl > \x1B[8G' + ] ]; const hasPreview = repl.terminal && diff --git a/test/parallel/test-repl.js b/test/parallel/test-repl.js index 67ec86cc2c5472..a7b0b453e9068c 100644 --- a/test/parallel/test-repl.js +++ b/test/parallel/test-repl.js @@ -457,6 +457,28 @@ const errorTests = [ /'thefourtheye'/ ] }, + // Check for wrapped objects. + { + send: '{ a: 1 }.a', // ({ a: 1 }.a); + expect: '1' + }, + { + send: '{ a: 1 }.a;', // { a: 1 }.a; + expect: [ + kSource, + kArrow, + '', + /^Uncaught SyntaxError: / + ] + }, + { + send: '{ a: 1 }["a"] === 1', // ({ a: 1 }['a'] === 1); + expect: 'true' + }, + { + send: '{ a: 1 }["a"] === 1;', // { a: 1 }; ['a'] === 1; + expect: 'false' + }, // Empty lines in the REPL should be allowed { send: '\n\r\n\r\n',