diff --git a/lib/internal/modules/esm/hooks.js b/lib/internal/modules/esm/hooks.js index cb2bc456dbb8f1..b4e9906e8c3bc2 100644 --- a/lib/internal/modules/esm/hooks.js +++ b/lib/internal/modules/esm/hooks.js @@ -6,6 +6,7 @@ const { AtomicsLoad, AtomicsWait, AtomicsWaitAsync, + FunctionPrototypeBind, Int32Array, ObjectAssign, ObjectDefineProperty, @@ -162,7 +163,7 @@ class Hooks { * to the worker. * @returns {any | Promise} User data, ignored unless it's a promise, in which case it will be awaited. */ - addCustomLoader(url, exports, data) { + async addCustomLoader(url, exports, data) { const { initialize, resolve, @@ -177,7 +178,30 @@ class Hooks { const next = this.#chains.load[this.#chains.load.length - 1]; ArrayPrototypePush(this.#chains.load, { __proto__: null, fn: load, url, next }); } - return initialize?.(data); + + const hooks = await initialize?.(data); + + if (hooks?.resolve) { + if (resolve) { + throw new ERR_INTERNAL_ASSERTION( + `ESM custom loader '${url}' exposed a 'resolve' hook and returned an object with a 'resolve' hook.`, + ); + } + const next = this.#chains.resolve[this.#chains.resolve.length - 1]; + const boundResolve = FunctionPrototypeBind(hooks.resolve, hooks); + ArrayPrototypePush(this.#chains.resolve, { __proto__: null, fn: boundResolve, url, next }); + } + + if (hooks?.load) { + if (load) { + throw new ERR_INTERNAL_ASSERTION( + `ESM custom loader '${url}' exposed a 'load' hook and returned an object with a 'load' hook.`, + ); + } + const next = this.#chains.load[this.#chains.load.length - 1]; + const boundLoad = FunctionPrototypeBind(hooks.load, hooks); + ArrayPrototypePush(this.#chains.load, { __proto__: null, fn: boundLoad, url, next }); + } } /**