Skip to content

Commit 3c73118

Browse files
committed
module: initialize hook returns load, resolve
This commit allows the `initialize()` hook to optionally return an object having the `resolve()` and `load()` hooks as properties. This allows state passed into `initialize()` to be shared with the `resolve()` and `load()` hooks either via closure or class instance. In addition to developer ergonomics, supporting this model will make it easier to write tests against a loader module. The existing design forces state to be shared at the module level which puts the burden of invalidating the ESM module cache on anyone hoping to write isolated tests against a loader module. Fixes: #50042
1 parent 609b13e commit 3c73118

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

lib/internal/modules/esm/hooks.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const {
44
ArrayPrototypePush,
55
ArrayPrototypePushApply,
6+
FunctionPrototypeBind,
67
Int32Array,
78
ObjectAssign,
89
ObjectDefineProperty,
@@ -139,7 +140,7 @@ class Hooks {
139140
* to the worker.
140141
* @returns {any | Promise<any>} User data, ignored unless it's a promise, in which case it will be awaited.
141142
*/
142-
addCustomLoader(url, exports, data) {
143+
async addCustomLoader(url, exports, data) {
143144
const {
144145
initialize,
145146
resolve,
@@ -154,7 +155,26 @@ class Hooks {
154155
const next = this.#chains.load[this.#chains.load.length - 1];
155156
ArrayPrototypePush(this.#chains.load, { __proto__: null, fn: load, url, next });
156157
}
157-
return initialize?.(data);
158+
159+
const hooks = await initialize?.(data);
160+
161+
if (hooks?.resolve) {
162+
if (resolve) {
163+
throw new Error('Invariant violation: both a module-level and returned resolve hook found');
164+
}
165+
const next = this.#chains.resolve[this.#chains.resolve.length - 1];
166+
const boundResolve = FunctionPrototypeBind(hooks.resolve, hooks);
167+
ArrayPrototypePush(this.#chains.resolve, { __proto__: null, fn: boundResolve, url, next });
168+
}
169+
170+
if (hooks?.load) {
171+
if (load) {
172+
throw new Error('Invariant violation: both a module-level and returned load hook found');
173+
}
174+
const next = this.#chains.load[this.#chains.load.length - 1];
175+
const boundLoad = FunctionPrototypeBind(hooks.load, hooks);
176+
ArrayPrototypePush(this.#chains.load, { __proto__: null, fn: boundLoad, url, next });
177+
}
158178
}
159179

160180
/**

0 commit comments

Comments
 (0)