From 05d4103b8285495c2dcce6e41960a0cfc7ae7084 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Thu, 21 Apr 2016 11:20:12 +0200 Subject: [PATCH] =?UTF-8?q?repl:=20don=E2=80=99t=20complete=20expressions?= =?UTF-8?q?=20when=20eval=20fails?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of changing the way “simple” expressions are detected, switch to ignoring errors when completing. This approach is more generic than the previous one from 0b66b8f2d, but also changes the way errors are thrown when completing. This reverts the code changes from commit 0b66b8f2d2c. The test case is left intact. Fixes: https://github.com/nodejs/node/issues/6325 PR-URL: https://github.com/nodejs/node/pull/6328 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- lib/repl.js | 5 ++- test/parallel/test-repl-tab-complete.js | 57 +++++++++++++------------ 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 2c952cfbf73609..a7452b8ec731bd 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -628,7 +628,7 @@ ArrayStream.prototype.write = function() {}; const requireRE = /\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/; const simpleExpressionRE = - /^\s*(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/; + /(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/; function intFilter(item) { // filters out anything not starting with A-Z, a-z, $ or _ @@ -806,7 +806,8 @@ REPLServer.prototype.complete = function(line, callback) { }); } } else { - this.eval(expr, this.context, 'repl', function(e, obj) { + const evalExpr = `try { ${expr} } catch (e) {}`; + this.eval(evalExpr, this.context, 'repl', function(e, obj) { // if (e) console.log(e); if (obj != null) { diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index 0c18d8e11ce724..eb4e68ad18d772 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -3,19 +3,13 @@ var common = require('../common'); var assert = require('assert'); var repl = require('repl'); -var referenceErrors = 0; -var expectedReferenceErrors = 0; - -function getDoNotCallFunction() { - expectedReferenceErrors += 1; - return function() { - assert(false); - }; -} -process.on('exit', function() { - assert.strictEqual(referenceErrors, expectedReferenceErrors); -}); +function getNoResultsFunction() { + return common.mustCall((err, data) => { + assert.ifError(err); + assert.deepStrictEqual(data[0], []); + }); +} var works = [['inner.one'], 'inner.o']; const putIn = new common.ArrayStream(); @@ -23,13 +17,7 @@ var testMe = repl.start('', putIn); // Some errors are passed to the domain, but do not callback testMe._domain.on('error', function(err) { - // Errors come from another context, so instanceof doesn't work - var str = err.toString(); - - if (/^ReferenceError:/.test(str)) - referenceErrors++; - else - assert(false); + assert.ifError(err); }); // Tab Complete will not break in an object literal @@ -38,7 +26,7 @@ putIn.run([ 'var inner = {', 'one:1' ]); -testMe.complete('inner.o', getDoNotCallFunction()); +testMe.complete('inner.o', getNoResultsFunction()); testMe.complete('console.lo', common.mustCall(function(error, data) { assert.deepStrictEqual(data, [['console.log'], 'console.lo']); @@ -58,7 +46,7 @@ putIn.run([ '?', '{one: 1} : ' ]); -testMe.complete('inner.o', getDoNotCallFunction()); +testMe.complete('inner.o', getNoResultsFunction()); putIn.run(['.clear']); @@ -74,7 +62,7 @@ testMe.complete('inner.o', common.mustCall(function(error, data) { // When you close the function scope tab complete will not return the // locally scoped variable putIn.run(['};']); -testMe.complete('inner.o', getDoNotCallFunction()); +testMe.complete('inner.o', getNoResultsFunction()); putIn.run(['.clear']); @@ -129,7 +117,7 @@ putIn.run([ ' one:1', '};' ]); -testMe.complete('inner.o', getDoNotCallFunction()); +testMe.complete('inner.o', getNoResultsFunction()); putIn.run(['.clear']); @@ -142,7 +130,7 @@ putIn.run([ ' one:1', '};' ]); -testMe.complete('inner.o', getDoNotCallFunction()); +testMe.complete('inner.o', getNoResultsFunction()); putIn.run(['.clear']); @@ -156,7 +144,7 @@ putIn.run([ ' one:1', '};' ]); -testMe.complete('inner.o', getDoNotCallFunction()); +testMe.complete('inner.o', getNoResultsFunction()); putIn.run(['.clear']); @@ -254,6 +242,21 @@ testMe.complete('obj.', common.mustCall(function(error, data) { putIn.run(['.clear']); putIn.run(['function a() {}']); -testMe.complete('a().b.', common.mustCall((error, data) => { - assert.deepStrictEqual(data, [[], undefined]); +testMe.complete('a().b.', getNoResultsFunction()); + +// Works when prefixed with spaces +putIn.run(['.clear']); +putIn.run(['var obj = {1:"a","1a":"b",a:"b"};']); + +testMe.complete(' obj.', common.mustCall((error, data) => { + assert.strictEqual(data[0].indexOf('obj.1'), -1); + assert.strictEqual(data[0].indexOf('obj.1a'), -1); + assert.notStrictEqual(data[0].indexOf('obj.a'), -1); +})); + +// Works inside assignments +putIn.run(['.clear']); + +testMe.complete('var log = console.lo', common.mustCall((error, data) => { + assert.deepStrictEqual(data, [['console.log'], 'console.lo']); }));