Skip to content

Commit 249f8d2

Browse files
committed
module: add preImport loader hook
1 parent f209aee commit 249f8d2

File tree

7 files changed

+164
-162
lines changed

7 files changed

+164
-162
lines changed

doc/api/esm.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,54 @@ A hook that returns without calling `next<hookName>()` _and_ without returning
734734
`shortCircuit: true` also triggers an exception. These errors are to help
735735
prevent unintentional breaks in the chain.
736736
737+
#### `preImport(specifier, context)`
738+
739+
<!-- YAML
740+
changes:
741+
- version: REPLACEME
742+
pr-url: REPLACEME
743+
description: Add support for preImport hook
744+
-->
745+
746+
> The loaders API is being redesigned. This hook may disappear or its
747+
> signature may change. Do not rely on the API described below.
748+
749+
* `specifier` {string}
750+
* `context` {Object}
751+
* `conditions` {string\[]} Resolution conditions of the current environment,
752+
as defined for the `package.json` imports and exports fields
753+
* `dynamic` {boolean} Whether this import is a dynamic `import()` (if *false*,
754+
that means it is a host top-level import).
755+
* `importAssertions` {Object}
756+
* `parentURL` {string|undefined} The module importing this one, or undefined
757+
if this is the Node.js entry point
758+
759+
The `preImport` hook allows for tracking and asynchronous setup work for every
760+
top-level import operation. It has no return value, although it can return
761+
a promise to to delay the module pipeline operations. No further hooks will
762+
be called on that module graph until this hook resolves successfully if present.
763+
764+
The `preImport` hook is called for each top-level import operation by the module
765+
loader, both for the host-called imports (ie for the main entry) and for dynamic
766+
`import()` imports. These are distinguished by the `dynamic` context.
767+
768+
All `preImport` hooks for all loaders are run asynchronously in parallel, and
769+
block any further load operations (ie resolve and load) for the module graph
770+
being imported until they all complete successfully.
771+
772+
Multiple import calls to the same import specifier will re-call the hook
773+
multiple times. The first error thrown by the `preImport` hooks will be directly
774+
returned to the specific import operation as the load failure.
775+
776+
```js
777+
export async function preImport(specifier, context) {
778+
if (context.topLevel)
779+
console.log(`Top-level load of ${specifier}`);
780+
else
781+
console.log(`Dynamic import of ${specifier} in ${context.parentURL}`);
782+
}
783+
```
784+
737785
#### `resolve(specifier, context, nextResolve)`
738786
739787
<!-- YAML
@@ -758,7 +806,8 @@ changes:
758806
759807
* `specifier` {string}
760808
* `context` {Object}
761-
* `conditions` {string\[]} Export conditions of the relevant `package.json`
809+
* `conditions` {string\[]} Resolution conditions of the current environment,
810+
as defined for the `package.json` imports and exports fields
762811
* `importAssertions` {Object}
763812
* `parentURL` {string|undefined} The module importing this one, or undefined
764813
if this is the Node.js entry point
@@ -851,7 +900,8 @@ changes:
851900
852901
* `url` {string} The URL returned by the `resolve` chain
853902
* `context` {Object}
854-
* `conditions` {string\[]} Export conditions of the relevant `package.json`
903+
* `conditions` {string\[]} Resolution conditions of the current environment,
904+
as defined for the `package.json` imports and exports fields
855905
* `format` {string|null|undefined} The format optionally supplied by the
856906
`resolve` hook chain
857907
* `importAssertions` {Object}

lib/internal/modules/cjs/loader.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,8 +1036,9 @@ function wrapSafe(filename, content, cjsModuleInstance) {
10361036
displayErrors: true,
10371037
importModuleDynamically: async (specifier, _, importAssertions) => {
10381038
const loader = asyncESM.esmLoader;
1039-
return loader.import(specifier, normalizeReferrerURL(filename),
1040-
importAssertions);
1039+
return loader.import(specifier,
1040+
normalizeReferrerURL(filename),
1041+
importAssertions, true);
10411042
},
10421043
});
10431044
}
@@ -1052,8 +1053,9 @@ function wrapSafe(filename, content, cjsModuleInstance) {
10521053
filename,
10531054
importModuleDynamically(specifier, _, importAssertions) {
10541055
const loader = asyncESM.esmLoader;
1055-
return loader.import(specifier, normalizeReferrerURL(filename),
1056-
importAssertions);
1056+
return loader.import(specifier,
1057+
normalizeReferrerURL(filename),
1058+
importAssertions, true);
10571059
},
10581060
});
10591061
} catch (err) {

0 commit comments

Comments
 (0)