mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
esm,loader: tidy ESMLoader internals
PR-URL: https://github.com/nodejs/node/pull/44701 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
'use strict';
|
||||
const {
|
||||
RegExpPrototypeExec,
|
||||
ObjectAssign,
|
||||
ObjectCreate,
|
||||
ObjectPrototypeHasOwnProperty,
|
||||
PromisePrototypeThen,
|
||||
PromiseResolve,
|
||||
@@ -25,13 +23,14 @@ const { getPackageType, getPackageScopeConfig } = require('internal/modules/esm/
|
||||
const { URL, fileURLToPath } = require('internal/url');
|
||||
const { ERR_UNKNOWN_FILE_EXTENSION } = require('internal/errors').codes;
|
||||
|
||||
const protocolHandlers = ObjectAssign(ObjectCreate(null), {
|
||||
const protocolHandlers = {
|
||||
'__proto__': null,
|
||||
'data:': getDataProtocolModuleFormat,
|
||||
'file:': getFileProtocolModuleFormat,
|
||||
'http:': getHttpProtocolModuleFormat,
|
||||
'https:': getHttpProtocolModuleFormat,
|
||||
'node:'() { return 'builtin'; },
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {URL} parsed
|
||||
|
||||
@@ -179,39 +179,38 @@ function nextHookFactory(chain, meta, { validateArgs, validateOutput }) {
|
||||
* the main module and everything in its dependency graph.
|
||||
*/
|
||||
class ESMLoader {
|
||||
/**
|
||||
* Prior to ESM loading. These are called once before any modules are started.
|
||||
* @private
|
||||
* @property {KeyedHook[]} globalPreloaders Last-in-first-out
|
||||
* list of preload hooks.
|
||||
*/
|
||||
#globalPreloaders = [];
|
||||
#hooks = {
|
||||
/**
|
||||
* Prior to ESM loading. These are called once before any modules are started.
|
||||
* @private
|
||||
* @property {KeyedHook[]} globalPreload Last-in-first-out list of preload hooks.
|
||||
*/
|
||||
globalPreload: [],
|
||||
|
||||
/**
|
||||
* Phase 2 of 2 in ESM loading.
|
||||
* @private
|
||||
* @property {KeyedHook[]} loaders Last-in-first-out
|
||||
* collection of loader hooks.
|
||||
*/
|
||||
#loaders = [
|
||||
{
|
||||
fn: defaultLoad,
|
||||
url: 'node:internal/modules/esm/load',
|
||||
},
|
||||
];
|
||||
/**
|
||||
* Phase 2 of 2 in ESM loading (phase 1 is below).
|
||||
* @private
|
||||
* @property {KeyedHook[]} load Last-in-first-out collection of loader hooks.
|
||||
*/
|
||||
load: [
|
||||
{
|
||||
fn: defaultLoad,
|
||||
url: 'node:internal/modules/esm/load',
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* Phase 1 of 2 in ESM loading.
|
||||
* @private
|
||||
* @property {KeyedHook[]} resolvers Last-in-first-out
|
||||
* collection of resolver hooks.
|
||||
*/
|
||||
#resolvers = [
|
||||
{
|
||||
fn: defaultResolve,
|
||||
url: 'node:internal/modules/esm/resolve',
|
||||
},
|
||||
];
|
||||
/**
|
||||
* Phase 1 of 2 in ESM loading.
|
||||
* @private
|
||||
* @property {KeyedHook[]} resolve Last-in-first-out collection of resolve hooks.
|
||||
*/
|
||||
resolve: [
|
||||
{
|
||||
fn: defaultResolve,
|
||||
url: 'node:internal/modules/esm/resolve',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
#importMetaInitializer = initializeImportMeta;
|
||||
|
||||
@@ -305,13 +304,13 @@ class ESMLoader {
|
||||
);
|
||||
|
||||
if (globalPreload) {
|
||||
acceptedHooks.globalPreloader = globalPreload;
|
||||
acceptedHooks.globalPreload = globalPreload;
|
||||
}
|
||||
if (resolve) {
|
||||
acceptedHooks.resolver = resolve;
|
||||
acceptedHooks.resolve = resolve;
|
||||
}
|
||||
if (load) {
|
||||
acceptedHooks.loader = load;
|
||||
acceptedHooks.load = load;
|
||||
}
|
||||
|
||||
return acceptedHooks;
|
||||
@@ -333,34 +332,34 @@ class ESMLoader {
|
||||
url,
|
||||
} = customLoaders[i];
|
||||
const {
|
||||
globalPreloader,
|
||||
resolver,
|
||||
loader,
|
||||
globalPreload,
|
||||
resolve,
|
||||
load,
|
||||
} = ESMLoader.pluckHooks(exports);
|
||||
|
||||
if (globalPreloader) {
|
||||
if (globalPreload) {
|
||||
ArrayPrototypePush(
|
||||
this.#globalPreloaders,
|
||||
this.#hooks.globalPreload,
|
||||
{
|
||||
fn: globalPreloader,
|
||||
fn: globalPreload,
|
||||
url,
|
||||
},
|
||||
);
|
||||
}
|
||||
if (resolver) {
|
||||
if (resolve) {
|
||||
ArrayPrototypePush(
|
||||
this.#resolvers,
|
||||
this.#hooks.resolve,
|
||||
{
|
||||
fn: resolver,
|
||||
fn: resolve,
|
||||
url,
|
||||
},
|
||||
);
|
||||
}
|
||||
if (loader) {
|
||||
if (load) {
|
||||
ArrayPrototypePush(
|
||||
this.#loaders,
|
||||
this.#hooks.load,
|
||||
{
|
||||
fn: loader,
|
||||
fn: load,
|
||||
url,
|
||||
},
|
||||
);
|
||||
@@ -411,14 +410,14 @@ class ESMLoader {
|
||||
async getModuleJob(specifier, parentURL, importAssertions) {
|
||||
let importAssertionsForResolve;
|
||||
|
||||
// By default, `this.#loaders` contains just the Node default load hook
|
||||
if (this.#loaders.length !== 1) {
|
||||
// By default, `this.#hooks.load` contains just the Node default load hook
|
||||
if (this.#hooks.load.length !== 1) {
|
||||
// We can skip cloning if there are no user-provided loaders because
|
||||
// the Node.js default resolve hook does not use import assertions.
|
||||
importAssertionsForResolve = ObjectAssign(
|
||||
ObjectCreate(null),
|
||||
importAssertions,
|
||||
);
|
||||
importAssertionsForResolve = {
|
||||
__proto__: null,
|
||||
...importAssertions,
|
||||
};
|
||||
}
|
||||
|
||||
const { format, url } =
|
||||
@@ -533,11 +532,11 @@ class ESMLoader {
|
||||
if (!wasArr) { return namespaces[0]; } // We can skip the pairing below
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const namespace = ObjectCreate(null);
|
||||
namespace.url = specifiers[i];
|
||||
namespace.exports = namespaces[i];
|
||||
|
||||
namespaces[i] = namespace;
|
||||
namespaces[i] = {
|
||||
__proto__: null,
|
||||
url: specifiers[i],
|
||||
exports: namespaces[i],
|
||||
};
|
||||
}
|
||||
|
||||
return namespaces;
|
||||
@@ -555,7 +554,7 @@ class ESMLoader {
|
||||
* @returns {{ format: ModuleFormat, source: ModuleSource }}
|
||||
*/
|
||||
async load(url, context = {}) {
|
||||
const chain = this.#loaders;
|
||||
const chain = this.#hooks.load;
|
||||
const meta = {
|
||||
chainFinished: null,
|
||||
context,
|
||||
@@ -684,7 +683,7 @@ class ESMLoader {
|
||||
}
|
||||
|
||||
preload() {
|
||||
for (let i = this.#globalPreloaders.length - 1; i >= 0; i--) {
|
||||
for (let i = this.#hooks.globalPreload.length - 1; i >= 0; i--) {
|
||||
const channel = new MessageChannel();
|
||||
const {
|
||||
port1: insidePreload,
|
||||
@@ -695,19 +694,19 @@ class ESMLoader {
|
||||
insideLoader.unref();
|
||||
|
||||
const {
|
||||
fn: preloader,
|
||||
fn: preload,
|
||||
url: specifier,
|
||||
} = this.#globalPreloaders[i];
|
||||
} = this.#hooks.globalPreload[i];
|
||||
|
||||
const preload = preloader({
|
||||
const preloaded = preload({
|
||||
port: insideLoader,
|
||||
});
|
||||
|
||||
if (preload == null) { return; }
|
||||
if (preloaded == null) { return; }
|
||||
|
||||
const hookErrIdentifier = `${specifier} globalPreload`;
|
||||
|
||||
if (typeof preload !== 'string') { // [2]
|
||||
if (typeof preloaded !== 'string') { // [2]
|
||||
throw new ERR_INVALID_RETURN_VALUE(
|
||||
'a string',
|
||||
hookErrIdentifier,
|
||||
@@ -716,7 +715,7 @@ class ESMLoader {
|
||||
}
|
||||
const { compileFunction } = require('vm');
|
||||
const preloadInit = compileFunction(
|
||||
preload,
|
||||
preloaded,
|
||||
['getBuiltin', 'port', 'setImportMetaCallback'],
|
||||
{
|
||||
filename: '<preload>',
|
||||
@@ -789,7 +788,7 @@ class ESMLoader {
|
||||
async resolve(
|
||||
originalSpecifier,
|
||||
parentURL,
|
||||
importAssertions = ObjectCreate(null)
|
||||
importAssertions = ObjectCreate(null),
|
||||
) {
|
||||
const isMain = parentURL === undefined;
|
||||
|
||||
@@ -804,7 +803,7 @@ class ESMLoader {
|
||||
parentURL,
|
||||
);
|
||||
}
|
||||
const chain = this.#resolvers;
|
||||
const chain = this.#hooks.resolve;
|
||||
const context = {
|
||||
conditions: DEFAULT_CONDITIONS,
|
||||
importAssertions,
|
||||
|
||||
@@ -12,10 +12,10 @@ const { ESMLoader } = esmLoaderModule;
|
||||
const esmLoader = new ESMLoader();
|
||||
|
||||
const originalSpecifier = 'foo/bar';
|
||||
const importAssertions = Object.assign(
|
||||
Object.create(null),
|
||||
{ type: 'json' },
|
||||
);
|
||||
const importAssertions = {
|
||||
__proto__: null,
|
||||
type: 'json',
|
||||
};
|
||||
const parentURL = 'file:///entrypoint.js';
|
||||
const resolvedURL = 'file:///foo/bar.js';
|
||||
const suggestedFormat = 'test';
|
||||
|
||||
Reference in New Issue
Block a user