From 0609c09a94cabb914de800f080d7d8e5199a7488 Mon Sep 17 00:00:00 2001 From: Weijia Wang Date: Tue, 4 Jun 2019 17:27:04 +0800 Subject: [PATCH] repl: fix global object in repl The global object in repl conetxt is copied from main context, which breaks the behavior of `instanceof`. This change reverts https://github.com/nodejs/node/pull/25731. Fixes: https://github.com/nodejs/node/issues/27859 Refs: https://github.com/nodejs/node/pull/25731 --- lib/repl.js | 30 +++++++++++++++++++++---- test/parallel/test-repl-context.js | 1 + test/parallel/test-repl-tab-complete.js | 2 +- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 12461d67de481b..3236ecfe1821f7 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -109,6 +109,19 @@ const kContextId = Symbol('contextId'); let addedNewListener = false; +const GLOBAL_OBJECT_PROPERTIES = [ + 'NaN', 'Infinity', 'undefined', 'eval', 'parseInt', 'parseFloat', 'isNaN', + 'isFinite', 'decodeURI', 'decodeURIComponent', 'encodeURI', + 'encodeURIComponent', 'Object', 'Function', 'Array', 'String', 'Boolean', + 'Number', 'Date', 'RegExp', 'Error', 'EvalError', 'RangeError', + 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError', 'Math', 'JSON' +]; +const GLOBAL_OBJECT_PROPERTY_MAP = {}; +for (var n = 0; n < GLOBAL_OBJECT_PROPERTIES.length; n++) { + GLOBAL_OBJECT_PROPERTY_MAP[GLOBAL_OBJECT_PROPERTIES[n]] = + GLOBAL_OBJECT_PROPERTIES[n]; +} + try { // Hack for require.resolve("./relative") to work properly. module.filename = path.resolve('repl'); @@ -874,10 +887,6 @@ REPLServer.prototype.createContext = function() { }, () => { context = vm.createContext(); }); - for (const name of Object.getOwnPropertyNames(global)) { - Object.defineProperty(context, name, - Object.getOwnPropertyDescriptor(global, name)); - } context.global = context; const _console = new Console(this.outputStream); Object.defineProperty(context, 'console', { @@ -885,6 +894,15 @@ REPLServer.prototype.createContext = function() { writable: true, value: _console }); + + for (const name of Object.getOwnPropertyNames(global)) { + if (name === 'console' || name === 'global') + continue; + if (GLOBAL_OBJECT_PROPERTY_MAP[name] === undefined) { + Object.defineProperty(context, name, + Object.getOwnPropertyDescriptor(global, name)); + } + } } const module = new CJSModule(''); @@ -1455,6 +1473,10 @@ function _memory(cmd) { } function addCommonWords(completionGroups) { + // Global object properties + // (http://www.ecma-international.org/publications/standards/Ecma-262.htm) + completionGroups.push(GLOBAL_OBJECT_PROPERTIES); + // Only words which do not yet exist as global property should be added to // this list. completionGroups.push([ diff --git a/test/parallel/test-repl-context.js b/test/parallel/test-repl-context.js index 287d8adc295d7a..bd5ad7d01dca5f 100644 --- a/test/parallel/test-repl-context.js +++ b/test/parallel/test-repl-context.js @@ -21,6 +21,7 @@ const stream = new ArrayStream(); // Ensure that the repl console instance is not the global one. assert.notStrictEqual(r.context.console, console); + assert.notStrictEqual(r.context.Object, Object); const context = r.createContext(); // Ensure that the repl context gets its own "console" instance. diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index 364d880e8cc479..859cb77df067e8 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -496,7 +496,7 @@ const testNonGlobal = repl.start({ useGlobal: false }); -const builtins = [['Infinity', 'Int16Array', 'Int32Array', +const builtins = [['Infinity', '', 'Int16Array', 'Int32Array', 'Int8Array'], 'I']; if (common.hasIntl) {