Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 705e623

Browse filesBrowse files
esm: remove globalPreload hook (superseded by initialize)
PR-URL: #49144 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent ce30b4e commit 705e623
Copy full SHA for 705e623

File tree

Expand file treeCollapse file tree

9 files changed

+31
-429
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

9 files changed

+31
-429
lines changed
Open diff view settings
Collapse file

‎doc/api/module.md‎

Copy file name to clipboardExpand all lines: doc/api/module.md
+3-75Lines changed: 3 additions & 75 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ import('node:fs').then((esmFS) => {
149149
<!-- YAML
150150
added: v8.8.0
151151
changes:
152+
- version: REPLACEME
153+
pr-url: https://github.com/nodejs/node/pull/49144
154+
description: Removed `globalPreload`.
152155
- version: v20.6.0
153156
pr-url: https://github.com/nodejs/node/pull/48842
154157
description: Added `initialize` hook to replace `globalPreload`.
@@ -674,79 +677,6 @@ export async function load(url, context, nextLoad) {
674677
In a more advanced scenario, this can also be used to transform an unsupported
675678
source to a supported one (see [Examples](#examples) below).
676679
677-
#### `globalPreload()`
678-
679-
<!-- YAML
680-
changes:
681-
- version:
682-
- v18.6.0
683-
- v16.17.0
684-
pr-url: https://github.com/nodejs/node/pull/42623
685-
description: Add support for chaining globalPreload hooks.
686-
-->
687-
688-
> Stability: 1.0 - Early development
689-
690-
> **Warning:** This hook will be removed in a future version. Use
691-
> [`initialize`][] instead. When a hooks module has an `initialize` export,
692-
> `globalPreload` will be ignored.
693-
694-
* `context` {Object} Information to assist the preload code
695-
* `port` {MessagePort}
696-
* Returns: {string} Code to run before application startup
697-
698-
Sometimes it might be necessary to run some code inside of the same global
699-
scope that the application runs in. This hook allows the return of a string
700-
that is run as a sloppy-mode script on startup.
701-
702-
Similar to how CommonJS wrappers work, the code runs in an implicit function
703-
scope. The only argument is a `require`-like function that can be used to load
704-
builtins like "fs": `getBuiltin(request: string)`.
705-
706-
If the code needs more advanced `require` features, it has to construct
707-
its own `require` using `module.createRequire()`.
708-
709-
```mjs
710-
export function globalPreload(context) {
711-
return `\
712-
globalThis.someInjectedProperty = 42;
713-
console.log('I just set some globals!');
714-
715-
const { createRequire } = getBuiltin('module');
716-
const { cwd } = getBuiltin('process');
717-
718-
const require = createRequire(cwd() + '/<preload>');
719-
// [...]
720-
`;
721-
}
722-
```
723-
724-
Another argument is provided to the preload code: `port`. This is available as a
725-
parameter to the hook and inside of the source text returned by the hook. This
726-
functionality has been moved to the `initialize` hook.
727-
728-
Care must be taken in order to properly call [`port.ref()`][] and
729-
[`port.unref()`][] to prevent a process from being in a state where it won't
730-
close normally.
731-
732-
```mjs
733-
/**
734-
* This example has the application context send a message to the hook
735-
* and sends the message back to the application context
736-
*/
737-
export function globalPreload({ port }) {
738-
port.onmessage = (evt) => {
739-
port.postMessage(evt.data);
740-
};
741-
return `\
742-
port.postMessage('console.log("I went to the hook and back");');
743-
port.onmessage = (evt) => {
744-
eval(evt.data);
745-
};
746-
`;
747-
}
748-
```
749-
750680
### Examples
751681
752682
The various module customization hooks can be used together to accomplish
@@ -1105,8 +1035,6 @@ returned object contains the following keys:
11051035
[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
11061036
[`initialize`]: #initialize
11071037
[`module`]: modules.md#the-module-object
1108-
[`port.ref()`]: worker_threads.md#portref
1109-
[`port.unref()`]: worker_threads.md#portunref
11101038
[`register`]: #moduleregisterspecifier-parenturl-options
11111039
[`string`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
11121040
[`util.TextDecoder`]: util.md#class-utiltextdecoder
Collapse file

‎lib/internal/modules/esm/hooks.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/hooks.js
+12-126Lines changed: 12 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,13 @@
33
const {
44
ArrayPrototypePush,
55
ArrayPrototypePushApply,
6-
FunctionPrototypeCall,
76
Int32Array,
87
ObjectAssign,
98
ObjectDefineProperty,
109
ObjectSetPrototypeOf,
1110
Promise,
1211
SafeSet,
1312
StringPrototypeSlice,
14-
StringPrototypeStartsWith,
1513
StringPrototypeToUpperCase,
1614
globalThis,
1715
} = primordials;
@@ -33,7 +31,6 @@ const {
3331
ERR_INVALID_RETURN_VALUE,
3432
ERR_LOADER_CHAIN_INCOMPLETE,
3533
ERR_METHOD_NOT_IMPLEMENTED,
36-
ERR_UNKNOWN_BUILTIN_MODULE,
3734
ERR_WORKER_UNSERIALIZABLE_ERROR,
3835
} = require('internal/errors').codes;
3936
const { exitCodes: { kUnfinishedTopLevelAwait } } = internalBinding('errors');
@@ -49,7 +46,6 @@ const {
4946
validateString,
5047
} = require('internal/validators');
5148
const {
52-
emitExperimentalWarning,
5349
kEmptyObject,
5450
} = require('internal/util');
5551

@@ -73,8 +69,6 @@ let importMetaInitializer;
7369

7470
/**
7571
* @typedef {object} ExportedHooks
76-
* @property {Function} initialize Customizations setup hook.
77-
* @property {Function} globalPreload Global preload hook.
7872
* @property {Function} resolve Resolve hook.
7973
* @property {Function} load Load hook.
8074
*/
@@ -89,13 +83,6 @@ let importMetaInitializer;
8983

9084
class Hooks {
9185
#chains = {
92-
/**
93-
* Prior to ESM loading. These are called once before any modules are started.
94-
* @private
95-
* @property {KeyedHook[]} globalPreload Last-in-first-out list of preload hooks.
96-
*/
97-
globalPreload: [],
98-
9986
/**
10087
* Phase 1 of 2 in ESM loading.
10188
* The output of the `resolve` chain of hooks is passed into the `load` chain of hooks.
@@ -146,7 +133,6 @@ class Hooks {
146133

147134
/**
148135
* Collect custom/user-defined module loader hook(s).
149-
* After all hooks have been collected, the global preload hook(s) must be initialized.
150136
* @param {string} url Custom loader specifier
151137
* @param {Record<string, unknown>} exports
152138
* @param {any} [data] Arbitrary data to be passed from the custom loader (user-land)
@@ -155,18 +141,11 @@ class Hooks {
155141
*/
156142
addCustomLoader(url, exports, data) {
157143
const {
158-
globalPreload,
159144
initialize,
160145
resolve,
161146
load,
162147
} = pluckHooks(exports);
163148

164-
if (globalPreload && !initialize) {
165-
emitExperimentalWarning(
166-
'`globalPreload` is planned for removal in favor of `initialize`. `globalPreload`',
167-
);
168-
ArrayPrototypePush(this.#chains.globalPreload, { __proto__: null, fn: globalPreload, url });
169-
}
170149
if (resolve) {
171150
const next = this.#chains.resolve[this.#chains.resolve.length - 1];
172151
ArrayPrototypePush(this.#chains.resolve, { __proto__: null, fn: resolve, url, next });
@@ -178,49 +157,6 @@ class Hooks {
178157
return initialize?.(data);
179158
}
180159

181-
/**
182-
* Initialize `globalPreload` hooks.
183-
*/
184-
initializeGlobalPreload() {
185-
const preloadScripts = [];
186-
for (let i = this.#chains.globalPreload.length - 1; i >= 0; i--) {
187-
const { MessageChannel } = require('internal/worker/io');
188-
const channel = new MessageChannel();
189-
const {
190-
port1: insidePreload,
191-
port2: insideLoader,
192-
} = channel;
193-
194-
insidePreload.unref();
195-
insideLoader.unref();
196-
197-
const {
198-
fn: preload,
199-
url: specifier,
200-
} = this.#chains.globalPreload[i];
201-
202-
const preloaded = preload({
203-
port: insideLoader,
204-
});
205-
206-
if (preloaded == null) { continue; }
207-
208-
if (typeof preloaded !== 'string') { // [2]
209-
throw new ERR_INVALID_RETURN_VALUE(
210-
'a string',
211-
`${specifier} globalPreload`,
212-
preload,
213-
);
214-
}
215-
216-
ArrayPrototypePush(preloadScripts, {
217-
code: preloaded,
218-
port: insidePreload,
219-
});
220-
}
221-
return preloadScripts;
222-
}
223-
224160
/**
225161
* Resolve the location of the module.
226162
*
@@ -559,8 +495,9 @@ class HooksProxy {
559495
AtomicsWait(this.#lock, WORKER_TO_MAIN_THREAD_NOTIFICATION, 0);
560496
const response = this.#worker.receiveMessageSync();
561497
if (response == null || response.message.status === 'exit') { return; }
562-
const { preloadScripts } = this.#unwrapMessage(response);
563-
this.#executePreloadScripts(preloadScripts);
498+
499+
// ! This line catches initialization errors in the worker thread.
500+
this.#unwrapMessage(response);
564501
}
565502

566503
this.#isReady = true;
@@ -677,66 +614,12 @@ class HooksProxy {
677614
importMetaInitialize(meta, context, loader) {
678615
this.#importMetaInitializer(meta, context, loader);
679616
}
680-
681-
#executePreloadScripts(preloadScripts) {
682-
for (let i = 0; i < preloadScripts.length; i++) {
683-
const { code, port } = preloadScripts[i];
684-
const { compileFunction } = require('vm');
685-
const preloadInit = compileFunction(
686-
code,
687-
['getBuiltin', 'port', 'setImportMetaCallback'],
688-
{
689-
filename: '<preload>',
690-
},
691-
);
692-
let finished = false;
693-
let replacedImportMetaInitializer = false;
694-
let next = this.#importMetaInitializer;
695-
const { BuiltinModule } = require('internal/bootstrap/realm');
696-
// Calls the compiled preload source text gotten from the hook
697-
// Since the parameters are named we use positional parameters
698-
// see compileFunction above to cross reference the names
699-
try {
700-
FunctionPrototypeCall(
701-
preloadInit,
702-
globalThis,
703-
// Param getBuiltin
704-
(builtinName) => {
705-
if (StringPrototypeStartsWith(builtinName, 'node:')) {
706-
builtinName = StringPrototypeSlice(builtinName, 5);
707-
} else if (!BuiltinModule.canBeRequiredWithoutScheme(builtinName)) {
708-
throw new ERR_UNKNOWN_BUILTIN_MODULE(builtinName);
709-
}
710-
if (BuiltinModule.canBeRequiredByUsers(builtinName)) {
711-
return require(builtinName);
712-
}
713-
throw new ERR_UNKNOWN_BUILTIN_MODULE(builtinName);
714-
},
715-
// Param port
716-
port,
717-
// setImportMetaCallback
718-
(fn) => {
719-
if (finished || typeof fn !== 'function') {
720-
throw new ERR_INVALID_ARG_TYPE('fn', fn);
721-
}
722-
replacedImportMetaInitializer = true;
723-
const parent = next;
724-
next = (meta, context) => {
725-
return fn(meta, context, parent);
726-
};
727-
},
728-
);
729-
} finally {
730-
finished = true;
731-
if (replacedImportMetaInitializer) {
732-
this.#importMetaInitializer = next;
733-
}
734-
}
735-
}
736-
}
737617
}
738618
ObjectSetPrototypeOf(HooksProxy.prototype, null);
739619

620+
// TODO(JakobJingleheimer): Remove this when loaders go "stable".
621+
let globalPreloadWarningWasEmitted = false;
622+
740623
/**
741624
* A utility function to pluck the hooks from a user-defined loader.
742625
* @param {import('./loader.js).ModuleExports} exports
@@ -750,9 +633,6 @@ function pluckHooks({
750633
}) {
751634
const acceptedHooks = { __proto__: null };
752635

753-
if (globalPreload) {
754-
acceptedHooks.globalPreload = globalPreload;
755-
}
756636
if (resolve) {
757637
acceptedHooks.resolve = resolve;
758638
}
@@ -762,6 +642,12 @@ function pluckHooks({
762642

763643
if (initialize) {
764644
acceptedHooks.initialize = initialize;
645+
} else if (globalPreload && !globalPreloadWarningWasEmitted) {
646+
process.emitWarning(
647+
'`globalPreload` has been removed; use `initialize` instead.',
648+
'UnsupportedWarning',
649+
);
650+
globalPreloadWarningWasEmitted = true;
765651
}
766652

767653
return acceptedHooks;
Collapse file

‎lib/internal/modules/esm/utils.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/utils.js
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,7 @@ async function initializeHooks() {
145145
);
146146
}
147147

148-
const preloadScripts = hooks.initializeGlobalPreload();
149-
150-
return { __proto__: null, hooks, preloadScripts };
148+
return hooks;
151149
}
152150

153151
module.exports = {
Collapse file

‎lib/internal/modules/esm/worker.js‎

Copy file name to clipboardExpand all lines: lib/internal/modules/esm/worker.js
+4-5Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ function wrapMessage(status, body) {
7474
}
7575

7676
async function customizedModuleWorker(lock, syncCommPort, errorHandler) {
77-
let hooks, preloadScripts, initializationError;
77+
let hooks;
78+
let initializationError;
7879
let hasInitializationError = false;
7980

8081
{
@@ -91,9 +92,7 @@ async function customizedModuleWorker(lock, syncCommPort, errorHandler) {
9192

9293

9394
try {
94-
const initResult = await initializeHooks();
95-
hooks = initResult.hooks;
96-
preloadScripts = initResult.preloadScripts;
95+
hooks = await initializeHooks();
9796
} catch (exception) {
9897
// If there was an error while parsing and executing a user loader, for example if because a
9998
// loader contained a syntax error, then we need to send the error to the main thread so it can
@@ -107,7 +106,7 @@ async function customizedModuleWorker(lock, syncCommPort, errorHandler) {
107106
if (hasInitializationError) {
108107
syncCommPort.postMessage(wrapMessage('error', initializationError));
109108
} else {
110-
syncCommPort.postMessage(wrapMessage('success', { preloadScripts }), preloadScripts.map(({ port }) => port));
109+
syncCommPort.postMessage(wrapMessage('success'));
111110
}
112111

113112
// We're ready, so unlock the main thread.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.