Skip to content

Commit 96edd85

Browse files
aduh95targos
authored andcommitted
esm: remove support for arrays in import internal method
This avoids initializing arrays that we never use, and simplifies the implementation overall. PR-URL: nodejs#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 09c986e commit 96edd85

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
@@ -109,37 +109,27 @@ class Hooks {
109109
// Cache URLs we've already validated to avoid repeated validation
110110
#validatedUrls = new SafeSet();
111111

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

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

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

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

296260
/**

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)