Skip to content

Commit ddff9d9

Browse files
committed
esm: isolate globalPreload
1 parent 0bce573 commit ddff9d9

File tree

5 files changed

+137
-3
lines changed

5 files changed

+137
-3
lines changed

lib/internal/modules/esm/hooks.js

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

7474
/**
7575
* @typedef {object} ExportedHooks
76+
* @property {Function} initialize Customizations setup hook.
7677
* @property {Function} globalPreload Global preload hook.
7778
* @property {Function} resolve Resolve hook.
7879
* @property {Function} load Load hook.

lib/internal/modules/esm/worker.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ function wrapMessage(status, body) {
7474
}
7575

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

8082
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import { spawnPromisified } from '../common/index.mjs';
2+
import * as fixtures from '../common/fixtures.mjs';
3+
import assert from 'node:assert';
4+
import os from 'node:os';
5+
import { execPath } from 'node:process';
6+
import { describe, it } from 'node:test';
7+
8+
describe('globalPreload hook', () => {
9+
it('should not emit deprecation warning when initialize is supplied', async () => {
10+
const { stderr } = await spawnPromisified(execPath, [
11+
'--experimental-loader',
12+
'data:text/javascript,export function globalPreload(){}export function initialize(){}',
13+
fixtures.path('empty.js'),
14+
]);
15+
16+
assert.doesNotMatch(stderr, /`globalPreload` is an experimental feature/);
17+
});
18+
19+
it('should handle globalPreload returning undefined', async () => {
20+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
21+
'--no-warnings',
22+
'--experimental-loader',
23+
'data:text/javascript,export function globalPreload(){}',
24+
fixtures.path('empty.js'),
25+
]);
26+
27+
assert.strictEqual(stderr, '');
28+
assert.strictEqual(stdout, '');
29+
assert.strictEqual(code, 0);
30+
assert.strictEqual(signal, null);
31+
});
32+
33+
it('should handle loading node:test', async () => {
34+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
35+
'--no-warnings',
36+
'--experimental-loader',
37+
'data:text/javascript,export function globalPreload(){return `getBuiltin("node:test")()`}',
38+
fixtures.path('empty.js'),
39+
]);
40+
41+
assert.strictEqual(stderr, '');
42+
assert.match(stdout, /\n# pass 1\r?\n/);
43+
assert.strictEqual(code, 0);
44+
assert.strictEqual(signal, null);
45+
});
46+
47+
it('should handle loading node:os with node: prefix', async () => {
48+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
49+
'--no-warnings',
50+
'--experimental-loader',
51+
'data:text/javascript,export function globalPreload(){return `console.log(getBuiltin("node:os").arch())`}',
52+
fixtures.path('empty.js'),
53+
]);
54+
55+
assert.strictEqual(stderr, '');
56+
assert.strictEqual(stdout.trim(), os.arch());
57+
assert.strictEqual(code, 0);
58+
assert.strictEqual(signal, null);
59+
});
60+
61+
// `os` is used here because it's simple and not mocked (the builtin module otherwise doesn't matter).
62+
it('should handle loading builtin module without node: prefix', async () => {
63+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
64+
'--no-warnings',
65+
'--experimental-loader',
66+
'data:text/javascript,export function globalPreload(){return `console.log(getBuiltin("os").arch())`}',
67+
fixtures.path('empty.js'),
68+
]);
69+
70+
assert.strictEqual(stderr, '');
71+
assert.strictEqual(stdout.trim(), os.arch());
72+
assert.strictEqual(code, 0);
73+
assert.strictEqual(signal, null);
74+
});
75+
76+
it('should throw when loading node:test without node: prefix', async () => {
77+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
78+
'--no-warnings',
79+
'--experimental-loader',
80+
'data:text/javascript,export function globalPreload(){return `getBuiltin("test")()`}',
81+
fixtures.path('empty.js'),
82+
]);
83+
84+
assert.match(stderr, /ERR_UNKNOWN_BUILTIN_MODULE/);
85+
assert.strictEqual(stdout, '');
86+
assert.strictEqual(code, 1);
87+
assert.strictEqual(signal, null);
88+
});
89+
90+
it('should register globals set from globalPreload', async () => {
91+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
92+
'--no-warnings',
93+
'--experimental-loader',
94+
'data:text/javascript,export function globalPreload(){return "this.myGlobal=4"}',
95+
'--print', 'myGlobal',
96+
]);
97+
98+
assert.strictEqual(stderr, '');
99+
assert.strictEqual(stdout.trim(), '4');
100+
assert.strictEqual(code, 0);
101+
assert.strictEqual(signal, null);
102+
});
103+
104+
it('should log console.log calls returned from globalPreload', async () => {
105+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
106+
'--no-warnings',
107+
'--experimental-loader',
108+
'data:text/javascript,export function globalPreload(){return `console.log("Hello from globalPreload")`}',
109+
fixtures.path('empty.js'),
110+
]);
111+
112+
assert.strictEqual(stderr, '');
113+
assert.strictEqual(stdout.trim(), 'Hello from globalPreload');
114+
assert.strictEqual(code, 0);
115+
assert.strictEqual(signal, null);
116+
});
117+
118+
it('should crash if globalPreload returns code that throws', async () => {
119+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
120+
'--no-warnings',
121+
'--experimental-loader',
122+
'data:text/javascript,export function globalPreload(){return `throw new Error("error from globalPreload")`}',
123+
fixtures.path('empty.js'),
124+
]);
125+
126+
assert.match(stderr, /error from globalPreload/);
127+
assert.strictEqual(stdout, '');
128+
assert.strictEqual(code, 1);
129+
assert.strictEqual(signal, null);
130+
});
131+
});

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ describe('Loader hooks', { concurrency: true }, () => {
423423
});
424424

425425
describe('globalPreload', () => {
426-
it('should emit deprecation warning', async () => {
426+
it('should emit warning', async () => {
427427
const { stderr } = await spawnPromisified(execPath, [
428428
'--experimental-loader',
429429
'data:text/javascript,export function globalPreload(){}',

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)