From 200ae1da5a5ed5de138d13aad75eb25d64d45664 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 18 Dec 2020 14:57:59 +0100 Subject: [PATCH] repl: disable blocking completions by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s not okay for the REPL to be blocked for multiple seconds after entering `require('` because the completion is performing blocking fs operations on potentially huge directories. Turning the REPL completion function asynchronous would be the right thing to do here, but unfortunately the way the code is structured doesn’t play well with that (in particular, it breaks the preview feature). Therefore, disable these blocking calls by default. Refs: https://github.com/nodejs/node/pull/33282#issuecomment-733646794 --- lib/repl.js | 7 +++++-- test/parallel/test-repl-tab-complete.js | 7 ++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 3b95bd7f29c85f..3368b5997ae01d 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -298,6 +298,7 @@ function REPLServer(prompt, configurable: true }); + this.allowBlockingCompletions = !!options.allowBlockingCompletions; this.useColors = !!options.useColors; this._domain = options.domain || domain.create(); this.useGlobal = !!useGlobal; @@ -1204,7 +1205,8 @@ function complete(line, callback) { if (completeOn.length) { filter = completeOn; } - } else if (RegExpPrototypeTest(requireRE, line)) { + } else if (RegExpPrototypeTest(requireRE, line) && + this.allowBlockingCompletions) { // require('...') const extensions = ObjectKeys(this.context.require.extensions); const indexes = ArrayPrototypeMap(extensions, @@ -1265,7 +1267,8 @@ function complete(line, callback) { if (!subdir) { ArrayPrototypePush(completionGroups, _builtinLibs); } - } else if (RegExpPrototypeTest(fsAutoCompleteRE, line)) { + } else if (RegExpPrototypeTest(fsAutoCompleteRE, line) && + this.allowBlockingCompletions) { [completionGroups, completeOn] = completeFSFunctions(line); // Handle variable member lookup. // We support simple chained expressions like the following (no function diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index cc3dce1093fe4e..bfcf810ddd6125 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -51,7 +51,12 @@ function getNoResultsFunction() { const works = [['inner.one'], 'inner.o']; const putIn = new ArrayStream(); -const testMe = repl.start('', putIn); +const testMe = repl.start({ + prompt: '', + input: putIn, + output: process.stdout, + allowBlockingCompletions: true +}); // Some errors are passed to the domain, but do not callback testMe._domain.on('error', assert.ifError);