From 8d672b8e5364e0a00f4df623d0b514755df36d14 Mon Sep 17 00:00:00 2001 From: Antoine du Hamel Date: Sat, 7 Nov 2020 10:19:54 +0100 Subject: [PATCH] esm: refactor to use more primordials PR-URL: https://github.com/nodejs/node/pull/36019 Reviewed-By: Rich Trott --- .../modules/esm/create_dynamic_module.js | 4 ++-- lib/internal/modules/esm/get_format.js | 10 ++++++-- lib/internal/modules/esm/get_source.js | 12 ++++++---- lib/internal/modules/esm/loader.js | 5 ++-- lib/internal/modules/esm/module_job.js | 24 ++++++++++++------- lib/internal/modules/esm/resolve.js | 3 ++- lib/internal/modules/esm/translators.js | 16 +++++++++---- test/parallel/test-bootstrap-modules.js | 2 ++ 8 files changed, 50 insertions(+), 26 deletions(-) diff --git a/lib/internal/modules/esm/create_dynamic_module.js b/lib/internal/modules/esm/create_dynamic_module.js index e831db8daaf476..f7c20083b6c918 100644 --- a/lib/internal/modules/esm/create_dynamic_module.js +++ b/lib/internal/modules/esm/create_dynamic_module.js @@ -5,7 +5,7 @@ const { ArrayPrototypeMap, JSONStringify, ObjectCreate, - Set, + SafeSet, } = primordials; let debug = require('internal/util/debuglog').debuglog('esm', (fn) => { @@ -38,7 +38,7 @@ import.meta.done(); const { ModuleWrap, callbackMap } = internalBinding('module_wrap'); const m = new ModuleWrap(`${url}`, undefined, source, 0, 0); - const readyfns = new Set(); + const readyfns = new SafeSet(); const reflect = { exports: ObjectCreate(null), onReady: (cb) => { readyfns.add(cb); }, diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js index 16e2ad5e2d5c3e..51b207ea75d131 100644 --- a/lib/internal/modules/esm/get_format.js +++ b/lib/internal/modules/esm/get_format.js @@ -1,5 +1,8 @@ 'use strict'; -const { StringPrototypeStartsWith } = primordials; +const { + RegExpPrototypeExec, + StringPrototypeStartsWith, +} = primordials; const { extname } = require('path'); const { getOptionValue } = require('internal/options'); @@ -39,7 +42,10 @@ function defaultGetFormat(url, context, defaultGetFormatUnused) { } const parsed = new URL(url); if (parsed.protocol === 'data:') { - const [ , mime ] = /^([^/]+\/[^;,]+)(?:[^,]*?)(;base64)?,/.exec(parsed.pathname) || [ null, null, null ]; + const [ , mime ] = RegExpPrototypeExec( + /^([^/]+\/[^;,]+)(?:[^,]*?)(;base64)?,/, + parsed.pathname, + ) || [ null, null, null ]; const format = ({ '__proto__': null, 'text/javascript': 'module', diff --git a/lib/internal/modules/esm/get_source.js b/lib/internal/modules/esm/get_source.js index 54dbd029fcfc22..b2cf0c3bd28aa2 100644 --- a/lib/internal/modules/esm/get_source.js +++ b/lib/internal/modules/esm/get_source.js @@ -1,5 +1,8 @@ 'use strict'; +const { + RegExpPrototypeExec, +} = primordials; const { getOptionValue } = require('internal/options'); // Do not eagerly grab .manifest, it may be in TDZ const policy = getOptionValue('--experimental-policy') ? @@ -8,14 +11,13 @@ const policy = getOptionValue('--experimental-policy') ? const { Buffer } = require('buffer'); -const fs = require('fs'); -const { URL } = require('url'); -const { promisify } = require('internal/util'); +const fs = require('internal/fs/promises').exports; +const { URL } = require('internal/url'); const { ERR_INVALID_URL, ERR_INVALID_URL_SCHEME, } = require('internal/errors').codes; -const readFileAsync = promisify(fs.readFile); +const readFileAsync = fs.readFile; const DATA_URL_PATTERN = /^[^/]+\/[^,;]+(?:[^,]*?)(;base64)?,([\s\S]*)$/; @@ -25,7 +27,7 @@ async function defaultGetSource(url, { format } = {}, defaultGetSource) { if (parsed.protocol === 'file:') { source = await readFileAsync(parsed); } else if (parsed.protocol === 'data:') { - const match = DATA_URL_PATTERN.exec(parsed.pathname); + const match = RegExpPrototypeExec(DATA_URL_PATTERN, parsed.pathname); if (!match) { throw new ERR_INVALID_URL(url); } diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 110464cbdb1da3..232177698c73f6 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -7,6 +7,7 @@ const { FunctionPrototypeBind, ObjectSetPrototypeOf, SafeWeakMap, + StringPrototypeStartsWith, } = primordials; const { @@ -126,8 +127,8 @@ class Loader { } if (this._resolve === defaultResolve && - !url.startsWith('file:') && - !url.startsWith('data:') + !StringPrototypeStartsWith(url, 'file:') && + !StringPrototypeStartsWith(url, 'data:') ) { throw new ERR_INVALID_RETURN_PROPERTY( 'file: or data: url', 'loader resolve', 'url', url diff --git a/lib/internal/modules/esm/module_job.js b/lib/internal/modules/esm/module_job.js index 7b8f146771c530..549d43cc20e119 100644 --- a/lib/internal/modules/esm/module_job.js +++ b/lib/internal/modules/esm/module_job.js @@ -2,10 +2,15 @@ const { ArrayPrototypeJoin, + ArrayPrototypeMap, + ArrayPrototypePush, + FunctionPrototype, ObjectSetPrototypeOf, PromiseAll, + PromiseResolve, + PromisePrototypeCatch, + ReflectApply, SafeSet, - SafePromise, StringPrototypeIncludes, StringPrototypeMatch, StringPrototypeReplace, @@ -16,9 +21,9 @@ const { ModuleWrap } = internalBinding('module_wrap'); const { decorateErrorStack } = require('internal/util'); const assert = require('internal/assert'); -const resolvedPromise = SafePromise.resolve(); +const resolvedPromise = PromiseResolve(); -function noop() {} +const noop = FunctionPrototype; let hasPausedEntry = false; @@ -35,7 +40,7 @@ class ModuleJob { this.module = undefined; // Expose the promise to the ModuleWrap directly for linking below. // `this.module` is also filled in below. - this.modulePromise = moduleProvider.call(loader, url, isMain); + this.modulePromise = ReflectApply(moduleProvider, loader, [url, isMain]); // Wait for the ModuleWrap instance being linked with all dependencies. const link = async () => { @@ -49,21 +54,21 @@ class ModuleJob { const dependencyJobs = []; const promises = this.module.link(async (specifier) => { const jobPromise = this.loader.getModuleJob(specifier, url); - dependencyJobs.push(jobPromise); + ArrayPrototypePush(dependencyJobs, jobPromise); const job = await jobPromise; return job.modulePromise; }); if (promises !== undefined) - await SafePromise.all(promises); + await PromiseAll(promises); - return SafePromise.all(dependencyJobs); + return PromiseAll(dependencyJobs); }; // Promise for the list of all dependencyJobs. this.linked = link(); // This promise is awaited later anyway, so silence // 'unhandled rejection' warnings. - this.linked.catch(noop); + PromisePrototypeCatch(this.linked, noop); // instantiated == deep dependency jobs wrappers are instantiated, // and module wrapper is instantiated. @@ -85,7 +90,8 @@ class ModuleJob { } jobsInGraph.add(moduleJob); const dependencyJobs = await moduleJob.linked; - return PromiseAll(dependencyJobs.map(addJobsToDependencyGraph)); + return PromiseAll( + ArrayPrototypeMap(dependencyJobs, addJobsToDependencyGraph)); }; await addJobsToDependencyGraph(this); diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js index 21459cf3d1e753..dadad4ff57cb66 100644 --- a/lib/internal/modules/esm/resolve.js +++ b/lib/internal/modules/esm/resolve.js @@ -837,7 +837,8 @@ function defaultResolve(specifier, context = {}, defaultResolveUnused) { [internalFS.realpathCacheKey]: realpathCache }); const old = url; - url = pathToFileURL(real + (urlPath.endsWith(sep) ? '/' : '')); + url = pathToFileURL( + real + (StringPrototypeEndsWith(urlPath, sep) ? '/' : '')); url.search = old.search; url.hash = old.hash; } diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js index 9ebe8586ba9270..66636d9ce092b5 100644 --- a/lib/internal/modules/esm/translators.js +++ b/lib/internal/modules/esm/translators.js @@ -3,6 +3,7 @@ /* global WebAssembly */ const { + ArrayPrototypeMap, Boolean, JSONParse, ObjectGetPrototypeOf, @@ -14,6 +15,7 @@ const { SafeMap, SafeSet, StringPrototypeReplace, + StringPrototypeSlice, StringPrototypeSplit, StringPrototypeStartsWith, SyntaxErrorPrototype, @@ -277,9 +279,9 @@ function cjsPreparseModuleExports(filename) { translators.set('builtin', async function builtinStrategy(url) { debug(`Translating BuiltinModule ${url}`); // Slice 'node:' scheme - const id = url.slice(5); + const id = StringPrototypeSlice(url, 5); const module = loadNativeModule(id, url, true); - if (!url.startsWith('node:') || !module) { + if (!StringPrototypeStartsWith(url, 'node:') || !module) { throw new ERR_UNKNOWN_BUILTIN_MODULE(url); } debug(`Loading BuiltinModule ${url}`); @@ -291,7 +293,8 @@ translators.set('json', async function jsonStrategy(url) { emitExperimentalWarning('Importing JSON modules'); debug(`Translating JSONModule ${url}`); debug(`Loading JSONModule ${url}`); - const pathname = url.startsWith('file:') ? fileURLToPath(url) : null; + const pathname = StringPrototypeStartsWith(url, 'file:') ? + fileURLToPath(url) : null; let modulePath; let module; if (pathname) { @@ -365,8 +368,11 @@ translators.set('wasm', async function(url) { } const imports = - WebAssembly.Module.imports(compiled).map(({ module }) => module); - const exports = WebAssembly.Module.exports(compiled).map(({ name }) => name); + ArrayPrototypeMap(WebAssembly.Module.imports(compiled), + ({ module }) => module); + const exports = + ArrayPrototypeMap(WebAssembly.Module.exports(compiled), + ({ name }) => name); return createDynamicModule(imports, exports, url, (reflect) => { const { exports } = new WebAssembly.Instance(compiled, reflect.imports); diff --git a/test/parallel/test-bootstrap-modules.js b/test/parallel/test-bootstrap-modules.js index 4f6f750cb13df7..5fec2699bebe48 100644 --- a/test/parallel/test-bootstrap-modules.js +++ b/test/parallel/test-bootstrap-modules.js @@ -46,6 +46,8 @@ const expectedModules = new Set([ 'NativeModule internal/fixed_queue', 'NativeModule internal/fs/dir', 'NativeModule internal/fs/utils', + 'NativeModule internal/fs/promises', + 'NativeModule internal/fs/rimraf', 'NativeModule internal/idna', 'NativeModule internal/linkedlist', 'NativeModule internal/modules/run_main',