Skip to content

Commit abdde28

Browse files
esm: remove globalPreload hook (superseded by initialize)
1 parent b5da2f4 commit abdde28

File tree

8 files changed

+10
-405
lines changed

8 files changed

+10
-405
lines changed

lib/internal/modules/esm/hooks.js

+6-61
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ let importMetaInitializer;
7373

7474
/**
7575
* @typedef {object} ExportedHooks
76-
* @property {Function} globalPreload Global preload hook.
76+
* @property {Function} initialize Customizations setup hook.
7777
* @property {Function} resolve Resolve hook.
7878
* @property {Function} load Load hook.
7979
*/
@@ -88,13 +88,6 @@ let importMetaInitializer;
8888

8989
class Hooks {
9090
#chains = {
91-
/**
92-
* Prior to ESM loading. These are called once before any modules are started.
93-
* @private
94-
* @property {KeyedHook[]} globalPreload Last-in-first-out list of preload hooks.
95-
*/
96-
globalPreload: [],
97-
9891
/**
9992
* Phase 1 of 2 in ESM loading.
10093
* The output of the `resolve` chain of hooks is passed into the `load` chain of hooks.
@@ -154,18 +147,11 @@ class Hooks {
154147
*/
155148
addCustomLoader(url, exports, data) {
156149
const {
157-
globalPreload,
158150
initialize,
159151
resolve,
160152
load,
161153
} = pluckHooks(exports);
162154

163-
if (globalPreload && !initialize) {
164-
emitExperimentalWarning(
165-
'`globalPreload` is planned for removal in favor of `initialize`. `globalPreload`',
166-
);
167-
ArrayPrototypePush(this.#chains.globalPreload, { __proto__: null, fn: globalPreload, url });
168-
}
169155
if (resolve) {
170156
const next = this.#chains.resolve[this.#chains.resolve.length - 1];
171157
ArrayPrototypePush(this.#chains.resolve, { __proto__: null, fn: resolve, url, next });
@@ -177,49 +163,6 @@ class Hooks {
177163
return initialize?.(data);
178164
}
179165

180-
/**
181-
* Initialize `globalPreload` hooks.
182-
*/
183-
initializeGlobalPreload() {
184-
const preloadScripts = [];
185-
for (let i = this.#chains.globalPreload.length - 1; i >= 0; i--) {
186-
const { MessageChannel } = require('internal/worker/io');
187-
const channel = new MessageChannel();
188-
const {
189-
port1: insidePreload,
190-
port2: insideLoader,
191-
} = channel;
192-
193-
insidePreload.unref();
194-
insideLoader.unref();
195-
196-
const {
197-
fn: preload,
198-
url: specifier,
199-
} = this.#chains.globalPreload[i];
200-
201-
const preloaded = preload({
202-
port: insideLoader,
203-
});
204-
205-
if (preloaded == null) { continue; }
206-
207-
if (typeof preloaded !== 'string') { // [2]
208-
throw new ERR_INVALID_RETURN_VALUE(
209-
'a string',
210-
`${specifier} globalPreload`,
211-
preload,
212-
);
213-
}
214-
215-
ArrayPrototypePush(preloadScripts, {
216-
code: preloaded,
217-
port: insidePreload,
218-
});
219-
}
220-
return preloadScripts;
221-
}
222-
223166
/**
224167
* Resolve the location of the module.
225168
*
@@ -749,9 +692,6 @@ function pluckHooks({
749692
}) {
750693
const acceptedHooks = { __proto__: null };
751694

752-
if (globalPreload) {
753-
acceptedHooks.globalPreload = globalPreload;
754-
}
755695
if (resolve) {
756696
acceptedHooks.resolve = resolve;
757697
}
@@ -761,6 +701,11 @@ function pluckHooks({
761701

762702
if (initialize) {
763703
acceptedHooks.initialize = initialize;
704+
} else if (globalPreload) { // TODO(JakobJingleheimer): Remove this when loaders go "stable".
705+
process.emitWarning(
706+
'`globalPreload` has been removed; use `initialize` instead.',
707+
'DeprecationWarning',
708+
);
764709
}
765710

766711
return acceptedHooks;

lib/internal/modules/esm/utils.js

+1-3
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 { __proto__: null, hooks };
151149
}
152150

153151
module.exports = {

test/es-module/test-esm-loader-hooks.mjs

+1-138
Original file line numberDiff line numberDiff line change
@@ -419,143 +419,6 @@ describe('Loader hooks', { concurrency: true }, () => {
419419
});
420420
});
421421

422-
describe('globalPreload', () => {
423-
it('should emit deprecation warning', async () => {
424-
const { stderr } = await spawnPromisified(execPath, [
425-
'--experimental-loader',
426-
'data:text/javascript,export function globalPreload(){}',
427-
'--experimental-loader',
428-
'data:text/javascript,export function globalPreload(){return""}',
429-
fixtures.path('empty.js'),
430-
]);
431-
432-
assert.strictEqual(stderr.match(/`globalPreload` is an experimental feature/g).length, 1);
433-
});
434-
435-
it('should not emit deprecation warning when initialize is supplied', async () => {
436-
const { stderr } = await spawnPromisified(execPath, [
437-
'--experimental-loader',
438-
'data:text/javascript,export function globalPreload(){}export function initialize(){}',
439-
fixtures.path('empty.js'),
440-
]);
441-
442-
assert.doesNotMatch(stderr, /`globalPreload` is an experimental feature/);
443-
});
444-
445-
it('should handle globalPreload returning undefined', async () => {
446-
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
447-
'--no-warnings',
448-
'--experimental-loader',
449-
'data:text/javascript,export function globalPreload(){}',
450-
fixtures.path('empty.js'),
451-
]);
452-
453-
assert.strictEqual(stderr, '');
454-
assert.strictEqual(stdout, '');
455-
assert.strictEqual(code, 0);
456-
assert.strictEqual(signal, null);
457-
});
458-
459-
it('should handle loading node:test', async () => {
460-
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
461-
'--no-warnings',
462-
'--experimental-loader',
463-
'data:text/javascript,export function globalPreload(){return `getBuiltin("node:test")()`}',
464-
fixtures.path('empty.js'),
465-
]);
466-
467-
assert.strictEqual(stderr, '');
468-
assert.match(stdout, /\n# pass 1\r?\n/);
469-
assert.strictEqual(code, 0);
470-
assert.strictEqual(signal, null);
471-
});
472-
473-
it('should handle loading node:os with node: prefix', async () => {
474-
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
475-
'--no-warnings',
476-
'--experimental-loader',
477-
'data:text/javascript,export function globalPreload(){return `console.log(getBuiltin("node:os").arch())`}',
478-
fixtures.path('empty.js'),
479-
]);
480-
481-
assert.strictEqual(stderr, '');
482-
assert.strictEqual(stdout.trim(), os.arch());
483-
assert.strictEqual(code, 0);
484-
assert.strictEqual(signal, null);
485-
});
486-
487-
// `os` is used here because it's simple and not mocked (the builtin module otherwise doesn't matter).
488-
it('should handle loading builtin module without node: prefix', async () => {
489-
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
490-
'--no-warnings',
491-
'--experimental-loader',
492-
'data:text/javascript,export function globalPreload(){return `console.log(getBuiltin("os").arch())`}',
493-
fixtures.path('empty.js'),
494-
]);
495-
496-
assert.strictEqual(stderr, '');
497-
assert.strictEqual(stdout.trim(), os.arch());
498-
assert.strictEqual(code, 0);
499-
assert.strictEqual(signal, null);
500-
});
501-
502-
it('should throw when loading node:test without node: prefix', async () => {
503-
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
504-
'--no-warnings',
505-
'--experimental-loader',
506-
'data:text/javascript,export function globalPreload(){return `getBuiltin("test")()`}',
507-
fixtures.path('empty.js'),
508-
]);
509-
510-
assert.match(stderr, /ERR_UNKNOWN_BUILTIN_MODULE/);
511-
assert.strictEqual(stdout, '');
512-
assert.strictEqual(code, 1);
513-
assert.strictEqual(signal, null);
514-
});
515-
516-
it('should register globals set from globalPreload', async () => {
517-
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
518-
'--no-warnings',
519-
'--experimental-loader',
520-
'data:text/javascript,export function globalPreload(){return "this.myGlobal=4"}',
521-
'--print', 'myGlobal',
522-
]);
523-
524-
assert.strictEqual(stderr, '');
525-
assert.strictEqual(stdout.trim(), '4');
526-
assert.strictEqual(code, 0);
527-
assert.strictEqual(signal, null);
528-
});
529-
530-
it('should log console.log calls returned from globalPreload', async () => {
531-
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
532-
'--no-warnings',
533-
'--experimental-loader',
534-
'data:text/javascript,export function globalPreload(){return `console.log("Hello from globalPreload")`}',
535-
fixtures.path('empty.js'),
536-
]);
537-
538-
assert.strictEqual(stderr, '');
539-
assert.strictEqual(stdout.trim(), 'Hello from globalPreload');
540-
assert.strictEqual(code, 0);
541-
assert.strictEqual(signal, null);
542-
});
543-
544-
it('should crash if globalPreload returns code that throws', async () => {
545-
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
546-
'--no-warnings',
547-
'--experimental-loader',
548-
'data:text/javascript,export function globalPreload(){return `throw new Error("error from globalPreload")`}',
549-
fixtures.path('empty.js'),
550-
]);
551-
552-
assert.match(stderr, /error from globalPreload/);
553-
assert.strictEqual(stdout, '');
554-
assert.strictEqual(code, 1);
555-
assert.strictEqual(signal, null);
556-
});
557-
});
558-
559422
it('should be fine to call `process.removeAllListeners("beforeExit")` from the main thread', async () => {
560423
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
561424
'--no-warnings',
@@ -625,7 +488,7 @@ describe('Loader hooks', { concurrency: true }, () => {
625488
assert.strictEqual(signal, null);
626489
});
627490

628-
it('should have `register` work with cjs', async () => {
491+
it('should `register` from cjs', async () => {
629492
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
630493
'--no-warnings',
631494
'--input-type=commonjs',

test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs

+1-12
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,6 @@ import { readFileSync } from 'node:fs';
33

44
const GET_BUILTIN = `$__get_builtin_hole_${Date.now()}`;
55

6-
export function globalPreload() {
7-
return `Object.defineProperty(globalThis, ${JSON.stringify(GET_BUILTIN)}, {
8-
value: (builtinName) => {
9-
return getBuiltin(builtinName);
10-
},
11-
enumerable: false,
12-
configurable: false,
13-
});
14-
`;
15-
}
16-
176
export async function resolve(specifier, context, next) {
187
const def = await next(specifier, context);
198

@@ -56,7 +45,7 @@ const $builtinInstance = ${GET_BUILTIN}(${JSON.stringify(builtinName)});
5645
module.exports = $builtinInstance;
5746
module.exports.__fromLoader = true;
5847
59-
// We need this for CJS-module-lexer can parse the exported names.
48+
// We need this for CJS-module-lexer can parse the exported names.
6049
${
6150
builtinExports
6251
.map(name => `exports.${name} = $builtinInstance.${name};`)

test/fixtures/es-module-loaders/hook-resolve-type.mjs

-24
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,6 @@
11
let importedESM = 0;
22
let importedCJS = 0;
33

4-
export function globalPreload({ port }) {
5-
port.on('message', (int32) => {
6-
port.postMessage({ importedESM, importedCJS });
7-
Atomics.store(int32, 0, 1);
8-
Atomics.notify(int32, 0);
9-
});
10-
port.unref();
11-
return `
12-
const { receiveMessageOnPort } = getBuiltin('worker_threads');
13-
global.getModuleTypeStats = async function getModuleTypeStats() {
14-
const sab = new SharedArrayBuffer(4);
15-
const int32 = new Int32Array(sab);
16-
port.postMessage(int32);
17-
// Artificial timeout to keep the event loop alive.
18-
// https://bugs.chromium.org/p/v8/issues/detail?id=13238
19-
// TODO(targos) Remove when V8 issue is resolved.
20-
const timeout = setTimeout(() => { throw new Error('timeout'); }, 1_000);
21-
await Atomics.waitAsync(int32, 0, 0).value;
22-
clearTimeout(timeout);
23-
return receiveMessageOnPort(port).message;
24-
};
25-
`;
26-
}
27-
284
export async function load(url, context, next) {
295
return next(url);
306
}

test/fixtures/es-module-loaders/loader-side-effect.mjs

-32
This file was deleted.

test/fixtures/es-module-loaders/loader-this-value-inside-hook-functions.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export function load(url, _, next) {
88
return next(url);
99
}
1010

11-
export function globalPreload() {
11+
export function initialize() {
1212
if (this != null) throw new Error('hook function must not be bound to ESMLoader instance');
1313
return "";
1414
}

0 commit comments

Comments
 (0)