From 521458a6c2ad1c58c5d408c07db143c0212aa1a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Tue, 10 Dec 2019 15:37:32 +0100 Subject: [PATCH] repl: fix autocomplete when useGlobal is false This fixes two issues in the REPL when it is started with a new context (useGlobal option set to `false`): - The `primordials` object does not contain all builtins, so the filtering based on property names from `primordials` was wrong. - The autocompleter did not take builtin names into account because they are not properties of the context object. A list of all global builtin names is created lazily when needed. It is used for filtering for the copy and for adding those names to the autocompleter list. Fixes: https://github.com/nodejs/node/issues/30792 PR-URL: https://github.com/nodejs/node/pull/30883 Reviewed-By: Ruben Bridgewater Reviewed-By: Rich Trott Reviewed-By: David Carlier --- lib/repl.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 77b6dc7fd52e50..d0c889758f6656 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -119,6 +119,9 @@ const { setImmediate } = require('timers'); // Lazy-loaded. let processTopLevelAwait; +const globalBuiltins = + new Set(vm.runInNewContext('Object.getOwnPropertyNames(globalThis)')); + const parentModule = module; const replMap = new WeakMap(); const domainSet = new WeakSet(); @@ -907,8 +910,8 @@ REPLServer.prototype.createContext = function() { context = vm.createContext(); }); for (const name of ObjectGetOwnPropertyNames(global)) { - // Only set properties on the context that do not exist as primordial. - if (!(name in primordials)) { + // Only set properties that do not already exist as a global builtin. + if (!globalBuiltins.has(name)) { ObjectDefineProperty(context, name, ObjectGetOwnPropertyDescriptor(global, name)); } @@ -1257,8 +1260,14 @@ function complete(line, callback) { completionGroups.push( filteredOwnPropertyNames.call(this, contextProto)); } - completionGroups.push( - filteredOwnPropertyNames.call(this, this.context)); + const contextOwnNames = + filteredOwnPropertyNames.call(this, this.context); + if (!this.useGlobal) { + // When the context is not `global`, builtins are not own + // properties of it. + contextOwnNames.push(...globalBuiltins); + } + completionGroups.push(contextOwnNames); if (filter !== '') addCommonWords(completionGroups); completionGroupsLoaded(); } else {