Skip to content

Commit 9f3466b

Browse files
authored
esm: remove support for arrays in import internal method
This avoids initializing arrays that we never use, and simplifies the implementation overall. PR-URL: #48296 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Jacob Smith <[email protected]> Reviewed-By: Geoffrey Booth <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 5c27cc2 commit 9f3466b

File tree

4 files changed

+34
-76
lines changed

4 files changed

+34
-76
lines changed

lib/internal/modules/esm/hooks.js

+16-26
Original file line numberDiff line numberDiff line change
@@ -110,37 +110,27 @@ class Hooks {
110110
// Cache URLs we've already validated to avoid repeated validation
111111
#validatedUrls = new SafeSet();
112112

113-
constructor(userLoaders) {
114-
this.addCustomLoaders(userLoaders);
115-
}
116-
117113
/**
118114
* Collect custom/user-defined module loader hook(s).
119115
* After all hooks have been collected, the global preload hook(s) must be initialized.
120-
* @param {import('./loader.js).KeyedExports} customLoaders Exports from user-defined loaders
121-
* (as returned by `ModuleLoader.import()`).
116+
* @param {string} url Custom loader specifier
117+
* @param {Record<string, unknown>} exports
122118
*/
123-
addCustomLoaders(customLoaders = []) {
124-
for (let i = 0; i < customLoaders.length; i++) {
125-
const {
126-
exports,
127-
url,
128-
} = customLoaders[i];
129-
const {
130-
globalPreload,
131-
resolve,
132-
load,
133-
} = pluckHooks(exports);
119+
addCustomLoader(url, exports) {
120+
const {
121+
globalPreload,
122+
resolve,
123+
load,
124+
} = pluckHooks(exports);
134125

135-
if (globalPreload) {
136-
ArrayPrototypePush(this.#chains.globalPreload, { fn: globalPreload, url });
137-
}
138-
if (resolve) {
139-
ArrayPrototypePush(this.#chains.resolve, { fn: resolve, url });
140-
}
141-
if (load) {
142-
ArrayPrototypePush(this.#chains.load, { fn: load, url });
143-
}
126+
if (globalPreload) {
127+
ArrayPrototypePush(this.#chains.globalPreload, { fn: globalPreload, url });
128+
}
129+
if (resolve) {
130+
ArrayPrototypePush(this.#chains.resolve, { fn: resolve, url });
131+
}
132+
if (load) {
133+
ArrayPrototypePush(this.#chains.load, { fn: load, url });
144134
}
145135
}
146136

lib/internal/modules/esm/loader.js

+5-41
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@
44
require('internal/modules/cjs/loader');
55

66
const {
7-
Array,
8-
ArrayIsArray,
97
FunctionPrototypeCall,
108
ObjectSetPrototypeOf,
119
PromisePrototypeThen,
12-
SafePromiseAllReturnArrayLike,
1310
SafeWeakMap,
1411
} = primordials;
1512

@@ -236,51 +233,18 @@ class DefaultModuleLoader {
236233
*
237234
* This method must NOT be renamed: it functions as a dynamic import on a
238235
* loader module.
239-
* @param {string | string[]} specifiers Path(s) to the module.
236+
* @param {string} specifier The first parameter of an `import()` expression.
240237
* @param {string} parentURL Path of the parent importing the module.
241238
* @param {Record<string, string>} importAssertions Validations for the
242239
* module import.
243240
* @returns {Promise<ExportedHooks | KeyedExports[]>}
244241
* A collection of module export(s) or a list of collections of module
245242
* export(s).
246243
*/
247-
async import(specifiers, parentURL, importAssertions) {
248-
// For loaders, `import` is passed multiple things to process, it returns a
249-
// list pairing the url and exports collected. This is especially useful for
250-
// error messaging, to identity from where an export came. But, in most
251-
// cases, only a single url is being "imported" (ex `import()`), so there is
252-
// only 1 possible url from which the exports were collected and it is
253-
// already known to the caller. Nesting that in a list would only ever
254-
// create redundant work for the caller, so it is later popped off the
255-
// internal list.
256-
const wasArr = ArrayIsArray(specifiers);
257-
if (!wasArr) { specifiers = [specifiers]; }
258-
259-
const count = specifiers.length;
260-
const jobs = new Array(count);
261-
262-
for (let i = 0; i < count; i++) {
263-
jobs[i] = PromisePrototypeThen(
264-
this
265-
.getModuleJob(specifiers[i], parentURL, importAssertions)
266-
.run(),
267-
({ module }) => module.getNamespace(),
268-
);
269-
}
270-
271-
const namespaces = await SafePromiseAllReturnArrayLike(jobs);
272-
273-
if (!wasArr) { return namespaces[0]; } // We can skip the pairing below
274-
275-
for (let i = 0; i < count; i++) {
276-
namespaces[i] = {
277-
__proto__: null,
278-
url: specifiers[i],
279-
exports: namespaces[i],
280-
};
281-
}
282-
283-
return namespaces;
244+
async import(specifier, parentURL, importAssertions) {
245+
const moduleJob = this.getModuleJob(specifier, parentURL, importAssertions);
246+
const { module } = await moduleJob.run();
247+
return module.getNamespace();
284248
}
285249

286250
/**

lib/internal/modules/esm/utils.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ function isLoaderWorker() {
108108
}
109109

110110
async function initializeHooks() {
111-
const customLoaderPaths = getOptionValue('--experimental-loader');
111+
const customLoaderURLs = getOptionValue('--experimental-loader');
112112

113113
let cwd;
114114
try {
@@ -149,17 +149,17 @@ async function initializeHooks() {
149149

150150
const parentURL = pathToFileURL(cwd).href;
151151

152-
for (let i = 0; i < customLoaderPaths.length; i++) {
153-
const customLoaderPath = customLoaderPaths[i];
152+
for (let i = 0; i < customLoaderURLs.length; i++) {
153+
const customLoaderURL = customLoaderURLs[i];
154154

155155
// Importation must be handled by internal loader to avoid polluting user-land
156-
const keyedExportsSublist = await privateModuleLoader.import(
157-
[customLoaderPath], // Import can handle multiple paths, but custom loaders must be sequential
156+
const keyedExports = await privateModuleLoader.import(
157+
customLoaderURL,
158158
parentURL,
159159
kEmptyObject,
160160
);
161161

162-
hooks.addCustomLoaders(keyedExportsSublist);
162+
hooks.addCustomLoader(customLoaderURL, keyedExports);
163163
}
164164

165165
const preloadScripts = hooks.initializeGlobalPreload();

lib/internal/process/esm_loader.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
'use strict';
22

3+
const {
4+
SafePromiseAllReturnVoid,
5+
} = primordials;
6+
37
const { createModuleLoader } = require('internal/modules/esm/loader');
48
const { getOptionValue } = require('internal/options');
59
const {
@@ -27,11 +31,11 @@ module.exports = {
2731
cwd = '/';
2832
}
2933
const parentURL = pathToFileURL(cwd).href;
30-
await esmLoader.import(
31-
userImports,
34+
await SafePromiseAllReturnVoid(userImports, (specifier) => esmLoader.import(
35+
specifier,
3236
parentURL,
3337
kEmptyObject,
34-
);
38+
));
3539
}
3640
await callback(esmLoader);
3741
} catch (err) {

0 commit comments

Comments
 (0)