diff --git a/doc/api/errors.md b/doc/api/errors.md
index 3e338a4e8f8cd6..5a8637a0ecc8b0 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -1233,23 +1233,6 @@ provided.
Encoding provided to `TextDecoder()` API was not one of the
[WHATWG Supported Encodings][].
-
-
-### `ERR_ESM_LOADER_REGISTRATION_UNAVAILABLE`
-
-
-
-Programmatically registering custom ESM loaders
-currently requires at least one custom loader to have been
-registered via the `--experimental-loader` flag. A no-op
-loader registered via CLI is sufficient
-(for example: `--experimental-loader data:text/javascript,`;
-do not omit the necessary trailing comma).
-A future version of Node.js will support the programmatic
-registration of loaders without needing to also use the flag.
-
### `ERR_EVAL_ESM_CANNOT_PRINT`
diff --git a/doc/api/n-api.md b/doc/api/n-api.md
index 873c8bdce4a492..10f19ee2f8cc65 100644
--- a/doc/api/n-api.md
+++ b/doc/api/n-api.md
@@ -245,106 +245,54 @@ from version 3 with some additions. This means that it is not necessary
to recompile for new versions of Node.js which are
listed as supporting a later version.
+This table may not be up to date in older streams, the most up to date
+information is in the latest API documentation in:
+[Node-API version matrix](https://nodejs.org/docs/latest/api/n-api.html#node-api-version-matrix)
+
- |
- 4 |
- 5 |
- 6 |
- 7 |
- 8 |
+ 7 |
+ v10.23.0+, v12.19.0+, v14.12.0+, 15.0.0 and all later versions |
- | v10.x |
- v10.16.0 |
- v10.17.0 |
- v10.20.0 |
- v10.23.0 |
- |
+ 6 |
+ v10.20.0+, v12.17.0+, 14.0.0 and all later versions |
- | v11.x |
- v11.8.0 |
- |
- |
- |
- |
+ 5 |
+ v10.17.0+, v12.11.0+, 13.0.0 and all later versions |
- | v12.x |
- v12.0.0 |
- v12.11.0 |
- v12.17.0 |
- v12.19.0 |
- v12.22.0 |
+ 4 |
+ v10.16.0+, v11.8.0+, 12.0.0 and all later versions |
-
- | v13.x |
- v13.0.0 |
- v13.0.0 |
- |
- |
- |
-
- | v14.x |
- v14.0.0 |
- v14.0.0 |
- v14.0.0 |
- v14.12.0 |
- v14.17.0 |
+
+ | 3 |
+ v6.14.2*, 8.11.2+, v9.11.0+*, 10.0.0 and all later versions |
- | v15.x |
- v15.0.0 |
- v15.0.0 |
- v15.0.0 |
- v15.0.0 |
- v15.12.0 |
+ 2 |
+ v8.10.0+*, v9.3.0+*, 10.0.0 and all later versions |
- | v16.x |
- v16.0.0 |
- v16.0.0 |
- v16.0.0 |
- v16.0.0 |
- v16.0.0 |
+ 1 |
+ v8.6.0+**, v9.0.0+*, 10.0.0 and all later versions |
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index a7120564c468fb..2206994e9277ee 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -1036,11 +1036,6 @@ E('ERR_ENCODING_INVALID_ENCODED_DATA', function(encoding, ret) {
}, TypeError);
E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported',
RangeError);
-E('ERR_ESM_LOADER_REGISTRATION_UNAVAILABLE', 'Programmatically registering custom ESM loaders ' +
- 'currently requires at least one custom loader to have been registered via the --experimental-loader ' +
- 'flag. A no-op loader registered via CLI is sufficient (for example: `--experimental-loader ' +
- '"data:text/javascript,"` with the necessary trailing comma). A future version of Node.js ' +
- 'will remove this requirement.', Error);
E('ERR_EVAL_ESM_CANNOT_PRINT', '--print cannot be used with ESM input', Error);
E('ERR_EVENT_RECURSION', 'The event "%s" is already being dispatched', Error);
E('ERR_FALSY_VALUE_REJECTION', function(reason) {
diff --git a/lib/internal/modules/esm/hooks.js b/lib/internal/modules/esm/hooks.js
index fa34e4b39a5950..cea2337ff15539 100644
--- a/lib/internal/modules/esm/hooks.js
+++ b/lib/internal/modules/esm/hooks.js
@@ -31,6 +31,7 @@ const {
ERR_INVALID_RETURN_PROPERTY_VALUE,
ERR_INVALID_RETURN_VALUE,
ERR_LOADER_CHAIN_INCOMPLETE,
+ ERR_METHOD_NOT_IMPLEMENTED,
ERR_UNKNOWN_BUILTIN_MODULE,
ERR_WORKER_UNSERIALIZABLE_ERROR,
} = require('internal/errors').codes;
@@ -65,7 +66,7 @@ const {
let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {
debug = fn;
});
-
+let importMetaInitializer;
/**
* @typedef {object} ExportedHooks
@@ -82,7 +83,6 @@ let debug = require('internal/util/debuglog').debuglog('esm', (fn) => {
// [2] `validate...()`s throw the wrong error
-
class Hooks {
#chains = {
/**
@@ -121,21 +121,22 @@ class Hooks {
// Cache URLs we've already validated to avoid repeated validation
#validatedUrls = new SafeSet();
+ allowImportMetaResolve = false;
+
/**
* Import and register custom/user-defined module loader hook(s).
* @param {string} urlOrSpecifier
* @param {string} parentURL
+ * @param {any} data
*/
- async register(urlOrSpecifier, parentURL) {
+ async register(urlOrSpecifier, parentURL, data) {
const moduleLoader = require('internal/process/esm_loader').esmLoader;
-
const keyedExports = await moduleLoader.import(
urlOrSpecifier,
parentURL,
kEmptyObject,
);
-
- this.addCustomLoader(urlOrSpecifier, keyedExports);
+ return await this.addCustomLoader(urlOrSpecifier, keyedExports, data);
}
/**
@@ -143,22 +144,29 @@ class Hooks {
* After all hooks have been collected, the global preload hook(s) must be initialized.
* @param {string} url Custom loader specifier
* @param {Record