GeezerVison is showing github.com — repl: lazy-load acorn and defer vm context creation · nodejs/node@00dea28
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/internal/repl/completion.js +8-10Lines changed: 8 additions & 10 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -33,7 +33,7 @@ const { | 33 | 33 | const { | 34 | 34 | kContextId, | 35 | 35 | getREPLResourceName, | 36 | | - globalBuiltins, | | 36 | + getGlobalBuiltins, | 37 | 37 | getReplBuiltinLibs, | 38 | 38 | fixReplRequire, | 39 | 39 | } = require('internal/repl/utils'); | @@ -61,13 +61,6 @@ const { | 61 | 61 | getOwnNonIndexProperties, | 62 | 62 | } = internalBinding('util'); | 63 | 63 |
| 64 | | -const { | 65 | | - isIdentifierStart, | 66 | | - isIdentifierChar, | 67 | | - parse: acornParse, | 68 | | -} = require('internal/deps/acorn/acorn/dist/acorn'); | 69 | | -const acornWalk = require('internal/deps/acorn/acorn-walk/dist/walk'); | 70 | | - | 71 | 64 | const importRE = /\bimport\s*\(\s*['"`](([\w@./:-]+\/)?(?:[\w@./:-]*))(?![^'"`])$/; | 72 | 65 | const requireRE = /\brequire\s*\(\s*['"`](([\w@./:-]+\/)?(?:[\w@./:-]*))(?![^'"`])$/; | 73 | 66 | const fsAutoCompleteRE = /fs(?:\.promises)?\.\s*[a-z][a-zA-Z]+\(\s*["'](.*)/; | @@ -87,6 +80,8 @@ function isIdentifier(str) { | 87 | 80 | if (str === '') { | 88 | 81 | return false; | 89 | 82 | } | | 83 | + const { isIdentifierStart, isIdentifierChar } = | | 84 | + require('internal/deps/acorn/acorn/dist/acorn'); | 90 | 85 | const first = StringPrototypeCodePointAt(str, 0); | 91 | 86 | if (!isIdentifierStart(first)) { | 92 | 87 | return false; | @@ -374,8 +369,8 @@ function complete(line, callback) { | 374 | 369 | if (!this.useGlobal) { | 375 | 370 | // When the context is not `global`, builtins are not own | 376 | 371 | // properties of it. | 377 | | - // `globalBuiltins` is a `SafeSet`, not an Array-like. | 378 | | - ArrayPrototypePush(contextOwnNames, ...globalBuiltins); | | 372 | + // `getGlobalBuiltins()` is a `SafeSet`, not an Array-like. | | 373 | + ArrayPrototypePush(contextOwnNames, ...getGlobalBuiltins()); | 379 | 374 | } | 380 | 375 | ArrayPrototypePush(completionGroups, contextOwnNames); | 381 | 376 | if (filter !== '') addCommonWords(completionGroups); | @@ -387,6 +382,7 @@ function complete(line, callback) { | 387 | 382 | // so in order to make it correct we add an identifier to its end (e.g. `obj.foo.x`) | 388 | 383 | const parsableCompleteTarget = completeTarget.endsWith('.') ? `${completeTarget}x` : completeTarget; | 389 | 384 |
| | 385 | + const { parse: acornParse } = require('internal/deps/acorn/acorn/dist/acorn'); | 390 | 386 | let completeTargetAst; | 391 | 387 | try { | 392 | 388 | completeTargetAst = acornParse( | @@ -551,6 +547,7 @@ function findExpressionCompleteTarget(code) { | 551 | 547 | return !result ? result : `${result}.`; | 552 | 548 | } | 553 | 549 |
| | 550 | + const { parse: acornParse } = require('internal/deps/acorn/acorn/dist/acorn'); | 554 | 551 | let ast; | 555 | 552 | try { | 556 | 553 | ast = acornParse(code, { __proto__: null, sourceType: 'module', ecmaVersion: 'latest' }); | @@ -625,6 +622,7 @@ function findExpressionCompleteTarget(code) { | 625 | 622 |
| 626 | 623 | // Walk the AST for the current block of code, and check whether it contains any | 627 | 624 | // statement or expression type that would potentially have side effects if evaluated. | | 625 | + const acornWalk = require('internal/deps/acorn/acorn-walk/dist/walk'); | 628 | 626 | let isAllowed = true; | 629 | 627 | const disallow = () => isAllowed = false; | 630 | 628 | acornWalk.simple(lastBodyStatement, { | |
Collapse file Copy file name to clipboardExpand all lines: lib/internal/repl/utils.js +10-6Lines changed: 10 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -20,10 +20,8 @@ const { | 20 | 20 | Symbol, | 21 | 21 | } = primordials; | 22 | 22 |
| 23 | | -const { tokTypes: tt, Parser: AcornParser } = | 24 | | - require('internal/deps/acorn/acorn/dist/acorn'); | 25 | | - | 26 | 23 | const { sendInspectorCommand } = require('internal/util/inspector'); | | 24 | +const { getLazy } = require('internal/util'); | 27 | 25 |
| 28 | 26 | const { | 29 | 27 | ERR_INSPECTOR_NOT_AVAILABLE, | @@ -80,6 +78,9 @@ function isRecoverableError(e, code) { | 80 | 78 | isRecoverableError(e, `(${code}`)) | 81 | 79 | return true; | 82 | 80 |
| | 81 | + const { tokTypes: tt, Parser: AcornParser } = | | 82 | + require('internal/deps/acorn/acorn/dist/acorn'); | | 83 | + | 83 | 84 | let recoverable = false; | 84 | 85 |
| 85 | 86 | // Determine if the point of any error raised is at the end of the input. | @@ -756,6 +757,8 @@ function setupReverseSearch(repl) { | 756 | 757 | const startsWithBraceRegExp = /^\s*{/; | 757 | 758 | const endsWithSemicolonRegExp = /;\s*$/; | 758 | 759 | function isValidSyntax(input) { | | 760 | + const { Parser: AcornParser } = | | 761 | + require('internal/deps/acorn/acorn/dist/acorn'); | 759 | 762 | try { | 760 | 763 | AcornParser.parse(input, { | 761 | 764 | ecmaVersion: 'latest', | @@ -815,8 +818,9 @@ function getREPLResourceName() { | 815 | 818 | return `REPL${nextREPLResourceNumber++}`; | 816 | 819 | } | 817 | 820 |
| 818 | | -const globalBuiltins = | 819 | | - new SafeSet(vm.runInNewContext('Object.getOwnPropertyNames(globalThis)')); | | 821 | +// Creating a new context is expensive, so only do it on first use. | | 822 | +const getGlobalBuiltins = getLazy(() => | | 823 | + new SafeSet(vm.runInNewContext('Object.getOwnPropertyNames(globalThis)'))); | 820 | 824 |
| 821 | 825 | let _builtinLibs = ArrayPrototypeFilter( | 822 | 826 | CJSModule.builtinModules, | @@ -848,7 +852,7 @@ module.exports = { | 848 | 852 | isValidSyntax, | 849 | 853 | kContextId, | 850 | 854 | getREPLResourceName, | 851 | | - globalBuiltins, | | 855 | + getGlobalBuiltins, | 852 | 856 | getReplBuiltinLibs, | 853 | 857 | setReplBuiltinLibs, | 854 | 858 | fixReplRequire, | |
Collapse file Copy file name to clipboardExpand all lines: lib/repl.js +4-6Lines changed: 4 additions & 6 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -89,10 +89,6 @@ const { | 89 | 89 | makeRequireFunction, | 90 | 90 | addBuiltinLibsToObject, | 91 | 91 | } = require('internal/modules/helpers'); | 92 | | -const { | 93 | | - parse: acornParse, | 94 | | -} = require('internal/deps/acorn/acorn/dist/acorn'); | 95 | | -const acornWalk = require('internal/deps/acorn/acorn-walk/dist/walk'); | 96 | 92 | const { | 97 | 93 | decorateErrorStack, | 98 | 94 | isError, | @@ -153,7 +149,7 @@ const { | 153 | 149 | isValidSyntax, | 154 | 150 | kContextId, | 155 | 151 | getREPLResourceName, | 156 | | - globalBuiltins, | | 152 | + getGlobalBuiltins, | 157 | 153 | getReplBuiltinLibs, | 158 | 154 | setReplBuiltinLibs, | 159 | 155 | fixReplRequire, | @@ -249,6 +245,8 @@ writer.options = { ...inspect.defaultOptions, showProxy: true }; | 249 | 245 |
| 250 | 246 | // Converts static import statement to dynamic import statement | 251 | 247 | const toDynamicImport = (codeLine) => { | | 248 | + const { parse: acornParse } = require('internal/deps/acorn/acorn/dist/acorn'); | | 249 | + const acornWalk = require('internal/deps/acorn/acorn-walk/dist/walk'); | 252 | 250 | let dynamicImportStatement = ''; | 253 | 251 | const ast = acornParse(codeLine, { __proto__: null, sourceType: 'module', ecmaVersion: 'latest' }); | 254 | 252 | acornWalk.ancestor(ast, { | @@ -1139,7 +1137,7 @@ class REPLServer extends Interface { | 1139 | 1137 | }); | 1140 | 1138 | ArrayPrototypeForEach(ObjectGetOwnPropertyNames(globalThis), (name) => { | 1141 | 1139 | // Only set properties that do not already exist as a global builtin. | 1142 | | - if (!globalBuiltins.has(name)) { | | 1140 | + if (!getGlobalBuiltins().has(name)) { | 1143 | 1141 | ObjectDefineProperty(context, name, | 1144 | 1142 | { | 1145 | 1143 | __proto__: null, | |
|