Skip to content

Commit

Permalink
esm: refactor DefaultModuleLoader
Browse files Browse the repository at this point in the history
  • Loading branch information
izaakschroeder committed Jun 30, 2023
1 parent 951da52 commit 409484a
Show file tree
Hide file tree
Showing 10 changed files with 278 additions and 157 deletions.
60 changes: 60 additions & 0 deletions lib/internal/modules/esm/conditions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const { getOptionValue } = require('internal/options');
const assert = require('internal/assert');

const {
ERR_INVALID_ARG_VALUE,
} = require('internal/errors').codes;

const {
ArrayIsArray,
SafeSet,
ObjectFreeze,
} = primordials;

let defaultConditions;
function getDefaultConditions() {
assert(defaultConditions !== undefined);
return defaultConditions;
}

let defaultConditionsSet;
function getDefaultConditionsSet() {
assert(defaultConditionsSet !== undefined);
return defaultConditionsSet;
}

// This function is called during pre-execution, before any user code is run.
function initializeDefaultConditions() {
const userConditions = getOptionValue('--conditions');
const noAddons = getOptionValue('--no-addons');
const addonConditions = noAddons ? [] : ['node-addons'];

defaultConditions = ObjectFreeze([
'node',
'import',
...addonConditions,
...userConditions,
]);
defaultConditionsSet = new SafeSet(defaultConditions);
}

/**
* @param {string[]} [conditions]
* @returns {Set<string>}
*/
function getConditionsSet(conditions) {
if (conditions !== undefined && conditions !== getDefaultConditions()) {
if (!ArrayIsArray(conditions)) {
throw new ERR_INVALID_ARG_VALUE('conditions', conditions,
'expected an array');
}
return new SafeSet(conditions);
}
return getDefaultConditionsSet();
}

module.exports = {
initializeDefaultConditions,
getDefaultConditions,
getConditionsSet,
};
59 changes: 46 additions & 13 deletions lib/internal/modules/esm/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,8 @@ const {
defaultResolve,
throwIfInvalidParentURL,
} = require('internal/modules/esm/resolve');
const {
getDefaultConditions,
loaderWorkerId,
} = require('internal/modules/esm/utils');
const {loaderWorkerId} = require('internal/modules/esm/utils');
const {getDefaultConditions} = require('internal/modules/esm/conditions');
const { deserializeError } = require('internal/error_serdes');
const {
SHARED_MEMORY_BYTE_LENGTH,
Expand All @@ -81,8 +79,8 @@ let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {
// [2] `validate...()`s throw the wrong error


class Hooks {
#chains = {
function getDefaultChains() {
return {
/**
* Prior to ESM loading. These are called once before any modules are started.
* @private
Expand Down Expand Up @@ -115,27 +113,42 @@ class Hooks {
},
],
};
}

class Hooks {
#chains;

// Cache URLs we've already validated to avoid repeated validation
#validatedUrls = new SafeSet();
#validatedUrls;

constructor(chains = getDefaultChains(), validatedUrls = new SafeSet()) {
this.#chains = chains;
this.#validatedUrls = validatedUrls;
}

/**
* Import and register custom/user-defined module loader hook(s).
* @param {string} urlOrSpecifier
* @param {string} parentURL
*/
async register(urlOrSpecifier, parentURL) {
const moduleLoader = require('internal/process/esm_loader').esmLoader;

const keyedExports = await moduleLoader.import(
const esmLoader = require('internal/process/esm_loader').esmLoader;
const keyedExports = await esmLoader.import(
urlOrSpecifier,
parentURL,
kEmptyObject,
);

this.addCustomLoader(urlOrSpecifier, keyedExports);
}

getChains() {
return this.#chains;
}

getValidatedUrls() {
return this.#validatedUrls;
}

/**
* Collect custom/user-defined module loader hook(s).
* After all hooks have been collected, the global preload hook(s) must be initialized.
Expand Down Expand Up @@ -221,15 +234,16 @@ class Hooks {
parentURL,
importAssertions = { __proto__: null },
) {
const chain = this.#chains.resolve;
throwIfInvalidParentURL(parentURL);

const chain = this.#chains.resolve;
const context = {
conditions: getDefaultConditions(),
importAssertions,
parentURL,
};
const meta = {
hooks: this,
chainFinished: null,
context,
hookErrIdentifier: '',
Expand Down Expand Up @@ -346,6 +360,7 @@ class Hooks {
async load(url, context = {}) {
const chain = this.#chains.load;
const meta = {
hooks: this,
chainFinished: null,
context,
hookErrIdentifier: '',
Expand Down Expand Up @@ -749,7 +764,25 @@ function nextHookFactory(chain, meta, { validateArgs, validateOutput }) {
ObjectAssign(meta.context, context);
}

const output = await hook(arg0, meta.context, nextNextHook);
const esmLoader = require('internal/process/esm_loader').esmLoader;

const chains = meta.hooks.getChains();
const load = chain === chains.load ? chains.load.slice(0, generatedHookIndex) : chains.load;
const resolve = chain === chains.resolve ? chains.resolve.slice(0, generatedHookIndex) : chains.resolve;
let output;
if (load.length > 0 && resolve.length > 0) {
const nextChains = {
load,
resolve,
globalPreload: chains.globalPreload,
}
const delegate = new Hooks(nextChains, meta.hooks.getValidatedUrls());
output = await esmLoader.withDelegate(delegate, async () => {
return await hook(arg0, meta.context, nextNextHook);
});
} else {
output = await hook(arg0, meta.context, nextNextHook);
}

validateOutput(outputErrIdentifier, output);

Expand Down
Loading

0 comments on commit 409484a

Please sign in to comment.