Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,13 @@ by the `node:assert` module.
An attempt was made to register something that is not a function as an
`AsyncHooks` callback.

<a id="ERR_ASYNC_LOADER_REQUEST_NEVER_SETTLED"></a>

### `ERR_ASYNC_LOADER_REQUEST_NEVER_SETTLED`

An operation related to module loading is customized by an asynchronous loader
hook that never settled the promise before the loader thread exits.

<a id="ERR_ASYNC_TYPE"></a>

### `ERR_ASYNC_TYPE`
Expand Down
2 changes: 2 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,8 @@ E('ERR_AMBIGUOUS_ARGUMENT', 'The "%s" argument is ambiguous. %s', TypeError);
E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError);
E('ERR_ASSERTION', '%s', Error);
E('ERR_ASYNC_CALLBACK', '%s must be a function', TypeError);
E('ERR_ASYNC_LOADER_REQUEST_NEVER_SETTLED',
'Async loader request never settled', Error);
E('ERR_ASYNC_TYPE', 'Invalid name for async "type": %s', TypeError);
E('ERR_BROTLI_INVALID_PARAM', '%s is not a valid Brotli parameter', RangeError);
E('ERR_BUFFER_OUT_OF_BOUNDS',
Expand Down
28 changes: 17 additions & 11 deletions lib/internal/modules/esm/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,15 @@ const {
} = globalThis;

const {
ERR_ASYNC_LOADER_REQUEST_NEVER_SETTLED,
ERR_INTERNAL_ASSERTION,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE,
ERR_INVALID_RETURN_PROPERTY_VALUE,
ERR_INVALID_RETURN_VALUE,
ERR_LOADER_CHAIN_INCOMPLETE,
ERR_METHOD_NOT_IMPLEMENTED,
ERR_WORKER_UNSERIALIZABLE_ERROR,
} = require('internal/errors').codes;
const { exitCodes: { kUnsettledTopLevelAwait } } = internalBinding('errors');
const { URLParse } = require('internal/url');
const { canParse: URLCanParse } = internalBinding('url');
const { receiveMessageOnPort } = require('worker_threads');
Expand Down Expand Up @@ -117,15 +116,16 @@ function defineImportAssertionAlias(context) {
* via `ModuleLoader.#setAsyncLoaderHooks()`.
* @typedef {object} AsyncLoaderHooks
* @property {boolean} allowImportMetaResolve Whether to allow the use of `import.meta.resolve`.
* @property {boolean} isForAsyncLoaderHookWorker Whether the instance is running on the loader hook worker thread.
* @property {(url: string, context: object, defaultLoad: Function) => Promise<LoadResult>} load
* Calling the asynchronous `load` hook asynchronously.
* @property {(url: string, context: object, defaultLoad: Function) => LoadResult} loadSync
* @property {(url: string, context: object, defaultLoad: Function) => LoadResult} [loadSync]
* Calling the asynchronous `load` hook synchronously.
* @property {(originalSpecifier: string, parentURL: string,
* importAttributes: Record<string, string>) => Promise<ResolveResult>} resolve
* Calling the asynchronous `resolve` hook asynchronously.
* @property {(originalSpecifier: string, parentURL: string,
* importAttributes: Record<string, string>) => ResolveResult} resolveSync
* importAttributes: Record<string, string>) => ResolveResult} [resolveSync]
* Calling the asynchronous `resolve` hook synchronously.
* @property {(specifier: string, parentURL: string) => any} register Register asynchronous loader hooks
* @property {() => void} waitForLoaderHookInitialization Force loading of hooks.
Expand Down Expand Up @@ -169,6 +169,8 @@ class AsyncLoaderHooksOnLoaderHookWorker {

allowImportMetaResolve = false;

isForAsyncLoaderHookWorker = true;

/**
* Import and register custom/user-defined module loader hook(s).
* @param {string} urlOrSpecifier
Expand Down Expand Up @@ -350,10 +352,6 @@ class AsyncLoaderHooksOnLoaderHookWorker {
};
}

resolveSync(_originalSpecifier, _parentURL, _importAttributes) {
throw new ERR_METHOD_NOT_IMPLEMENTED('resolveSync()');
}

/**
* Provide source that is understood by one of Node's translators.
*
Expand Down Expand Up @@ -560,7 +558,10 @@ class AsyncLoaderHookWorker {
debug('wait for signal from worker');
AtomicsWait(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 0);
const response = this.#worker.receiveMessageSync();
if (response == null || response.message.status === 'exit') { return; }
if (response == null) { return; }
if (response.message.status === 'exit') {
process.exit(response.message.body);
}

// ! This line catches initialization errors in the worker thread.
this.#unwrapMessage(response);
Expand Down Expand Up @@ -647,10 +648,13 @@ class AsyncLoaderHookWorker {
this.#workerNotificationLastId = AtomicsLoad(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION);

response = this.#worker.receiveMessageSync();
debug('got sync message from worker', { method, args, response });
} while (response == null);
debug('got sync response from worker', { method, args });

if (response.message.status === 'never-settle') {
process.exit(kUnsettledTopLevelAwait);
const error = new ERR_ASYNC_LOADER_REQUEST_NEVER_SETTLED();
error.details = { method, args };
throw error;
} else if (response.message.status === 'exit') {
process.exit(response.message.body);
}
Expand Down Expand Up @@ -819,6 +823,8 @@ class AsyncLoaderHooksProxiedToLoaderHookWorker {

allowImportMetaResolve = true;

isForAsyncLoaderHookWorker = false;

/**
* Instantiate a module loader that uses user-provided custom loader hooks.
*/
Expand Down
3 changes: 2 additions & 1 deletion lib/internal/modules/esm/initialize_import_meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ function createImportMetaResolve(defaultParentURL, loader, allowParentURL) {
}

try {
({ url } = loader.resolveSync(specifier, parentURL));
const request = { specifier, __proto__: null };
({ url } = loader.resolveSync(parentURL, request));
return url;
} catch (error) {
switch (error?.code) {
Expand Down
Loading
Loading