Skip to content

Commit 320a8ad

Browse files
GeoffreyBoothdanielleadams
authored andcommitted
esm: misc test refactors
- add test specific to the event loop - move parallel tests into es-module folder - refactor fixture to add braces for if blocks - use 'os' instead of 'fs' as placeholder - spelling PR-URL: #46631 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com>
1 parent dd97b05 commit 320a8ad

9 files changed

+377
-58
lines changed

test/es-module/test-esm-import-meta-resolve.mjs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import { mustCall } from '../common/index.mjs';
33
import assert from 'assert';
44

55
const dirname = import.meta.url.slice(0, import.meta.url.lastIndexOf('/') + 1);
6-
const fixtures = dirname.slice(0, dirname.lastIndexOf('/', dirname.length - 2) +
7-
1) + 'fixtures/';
6+
const fixtures = dirname.slice(0, dirname.lastIndexOf('/', dirname.length - 2) + 1) + 'fixtures/';
87

98
(async () => {
109
assert.strictEqual(await import.meta.resolve('./test-esm-import-meta.mjs'),

test/es-module/test-esm-initialization.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { execPath } from 'node:process';
55
import { describe, it } from 'node:test';
66

77

8-
describe('ESM: ensure initialisation happens only once', { concurrency: true }, () => {
8+
describe('ESM: ensure initialization happens only once', { concurrency: true }, () => {
99
it(async () => {
1010
const { code, stderr, stdout } = await spawnPromisified(execPath, [
1111
'--loader',

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const setupArgs = [
1010
'--input-type=module',
1111
'--eval',
1212
];
13-
const commonInput = 'import fs from "node:fs"; console.log(fs)';
13+
const commonInput = 'import os from "node:os"; console.log(os)';
1414
const commonArgs = [
1515
...setupArgs,
1616
commonInput,
@@ -115,11 +115,11 @@ describe('ESM: loader chaining', { concurrency: true }, () => {
115115
);
116116

117117
assert.match(stdout, /^resolve arg count: 3$/m);
118-
assert.match(stdout, /specifier: 'node:fs'/);
118+
assert.match(stdout, /specifier: 'node:os'/);
119119
assert.match(stdout, /next: \[AsyncFunction: nextResolve\]/);
120120

121121
assert.match(stdout, /^load arg count: 3$/m);
122-
assert.match(stdout, /url: 'node:fs'/);
122+
assert.match(stdout, /url: 'node:os'/);
123123
assert.match(stdout, /next: \[AsyncFunction: nextLoad\]/);
124124
});
125125

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Flags: --experimental-loader ./test/fixtures/es-module-loaders/hooks-custom.mjs
2+
import { mustCall } from '../common/index.mjs';
3+
4+
const done = mustCall();
5+
6+
7+
// Test that the process doesn't exit because of a caught exception thrown as part of dynamic import().
8+
for (let i = 0; i < 10; i++) {
9+
await import('nonexistent/file.mjs').catch(() => {});
10+
}
11+
12+
done();
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
import { spawnPromisified } from '../common/index.mjs';
2+
import * as fixtures from '../common/fixtures.mjs';
3+
import assert from 'node:assert';
4+
import { execPath } from 'node:process';
5+
import { describe, it } from 'node:test';
6+
7+
describe('Loader hooks throwing errors', { concurrency: true }, () => {
8+
it('throws on nonexistent modules', async () => {
9+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
10+
'--no-warnings',
11+
'--experimental-loader',
12+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
13+
'--input-type=module',
14+
'--eval',
15+
'import "nonexistent/file.mjs"',
16+
]);
17+
18+
assert.match(stderr, /ERR_MODULE_NOT_FOUND/);
19+
assert.strictEqual(stdout, '');
20+
assert.strictEqual(code, 1);
21+
assert.strictEqual(signal, null);
22+
});
23+
24+
it('throws on unknown extensions', async () => {
25+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
26+
'--no-warnings',
27+
'--experimental-loader',
28+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
29+
'--input-type=module',
30+
'--eval',
31+
`import '${fixtures.fileURL('/es-modules/file.unknown')}'`,
32+
]);
33+
34+
assert.match(stderr, /ERR_UNKNOWN_FILE_EXTENSION/);
35+
assert.strictEqual(stdout, '');
36+
assert.strictEqual(code, 1);
37+
assert.strictEqual(signal, null);
38+
});
39+
40+
it('throws on invalid return values', async () => {
41+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
42+
'--no-warnings',
43+
'--experimental-loader',
44+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
45+
'--input-type=module',
46+
'--eval',
47+
'import "esmHook/badReturnVal.mjs"',
48+
]);
49+
50+
assert.match(stderr, /ERR_INVALID_RETURN_VALUE/);
51+
assert.strictEqual(stdout, '');
52+
assert.strictEqual(code, 1);
53+
assert.strictEqual(signal, null);
54+
});
55+
56+
it('throws on boolean false', async () => {
57+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
58+
'--no-warnings',
59+
'--experimental-loader',
60+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
61+
'--input-type=module',
62+
'--eval',
63+
'import "esmHook/format.false"',
64+
]);
65+
66+
assert.match(stderr, /ERR_INVALID_RETURN_PROPERTY_VALUE/);
67+
assert.strictEqual(stdout, '');
68+
assert.strictEqual(code, 1);
69+
assert.strictEqual(signal, null);
70+
});
71+
it('throws on boolean true', async () => {
72+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
73+
'--no-warnings',
74+
'--experimental-loader',
75+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
76+
'--input-type=module',
77+
'--eval',
78+
'import "esmHook/format.true"',
79+
]);
80+
81+
assert.match(stderr, /ERR_INVALID_RETURN_PROPERTY_VALUE/);
82+
assert.strictEqual(stdout, '');
83+
assert.strictEqual(code, 1);
84+
assert.strictEqual(signal, null);
85+
});
86+
87+
it('throws on invalid returned object', async () => {
88+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
89+
'--no-warnings',
90+
'--experimental-loader',
91+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
92+
'--input-type=module',
93+
'--eval',
94+
'import "esmHook/badReturnFormatVal.mjs"',
95+
]);
96+
97+
assert.match(stderr, /ERR_INVALID_RETURN_PROPERTY_VALUE/);
98+
assert.strictEqual(stdout, '');
99+
assert.strictEqual(code, 1);
100+
assert.strictEqual(signal, null);
101+
});
102+
103+
it('throws on unsupported format', async () => {
104+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
105+
'--no-warnings',
106+
'--experimental-loader',
107+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
108+
'--input-type=module',
109+
'--eval',
110+
'import "esmHook/unsupportedReturnFormatVal.mjs"',
111+
]);
112+
113+
assert.match(stderr, /ERR_UNKNOWN_MODULE_FORMAT/);
114+
assert.strictEqual(stdout, '');
115+
assert.strictEqual(code, 1);
116+
assert.strictEqual(signal, null);
117+
});
118+
119+
it('throws on invalid format property type', async () => {
120+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
121+
'--no-warnings',
122+
'--experimental-loader',
123+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
124+
'--input-type=module',
125+
'--eval',
126+
'import "esmHook/badReturnSourceVal.mjs"',
127+
]);
128+
129+
assert.match(stderr, /ERR_INVALID_RETURN_PROPERTY_VALUE/);
130+
assert.strictEqual(stdout, '');
131+
assert.strictEqual(code, 1);
132+
assert.strictEqual(signal, null);
133+
});
134+
135+
it('rejects dynamic imports for all of the error cases checked above', async () => {
136+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
137+
'--no-warnings',
138+
'--experimental-loader',
139+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
140+
'--input-type=module',
141+
'--eval',
142+
`import assert from 'node:assert';
143+
await Promise.allSettled([
144+
import('nonexistent/file.mjs'),
145+
import('${fixtures.fileURL('/es-modules/file.unknown')}'),
146+
import('esmHook/badReturnVal.mjs'),
147+
import('esmHook/format.false'),
148+
import('esmHook/format.true'),
149+
import('esmHook/badReturnFormatVal.mjs'),
150+
import('esmHook/unsupportedReturnFormatVal.mjs'),
151+
import('esmHook/badReturnSourceVal.mjs'),
152+
]).then((results) => {
153+
assert.strictEqual(results.every((result) => result.status === 'rejected'), true);
154+
})`,
155+
]);
156+
157+
assert.strictEqual(stderr, '');
158+
assert.strictEqual(stdout, '');
159+
assert.strictEqual(code, 0);
160+
assert.strictEqual(signal, null);
161+
});
162+
});
163+
164+
describe('Loader hooks parsing modules', { concurrency: true }, () => {
165+
it('can parse .js files as ESM', async () => {
166+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
167+
'--no-warnings',
168+
'--experimental-loader',
169+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
170+
'--input-type=module',
171+
'--eval',
172+
`import assert from 'node:assert';
173+
await import('${fixtures.fileURL('/es-module-loaders/js-as-esm.js')}')
174+
.then((parsedModule) => {
175+
assert.strictEqual(typeof parsedModule, 'object');
176+
assert.strictEqual(parsedModule.namedExport, 'named-export');
177+
})`,
178+
]);
179+
180+
assert.strictEqual(stderr, '');
181+
assert.strictEqual(stdout, '');
182+
assert.strictEqual(code, 0);
183+
assert.strictEqual(signal, null);
184+
});
185+
186+
it('can define .ext files as ESM', async () => {
187+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
188+
'--no-warnings',
189+
'--experimental-loader',
190+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
191+
'--input-type=module',
192+
'--eval',
193+
`import assert from 'node:assert';
194+
await import('${fixtures.fileURL('/es-modules/file.ext')}')
195+
.then((parsedModule) => {
196+
assert.strictEqual(typeof parsedModule, 'object');
197+
const { default: defaultExport } = parsedModule;
198+
assert.strictEqual(typeof defaultExport, 'function');
199+
assert.strictEqual(defaultExport.name, 'iAmReal');
200+
assert.strictEqual(defaultExport(), true);
201+
})`,
202+
]);
203+
204+
assert.strictEqual(stderr, '');
205+
assert.strictEqual(stdout, '');
206+
assert.strictEqual(code, 0);
207+
assert.strictEqual(signal, null);
208+
});
209+
210+
it('can predetermine the format in the custom loader resolve hook', async () => {
211+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
212+
'--no-warnings',
213+
'--experimental-loader',
214+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
215+
'--input-type=module',
216+
'--eval',
217+
`import assert from 'node:assert';
218+
await import('esmHook/preknownFormat.pre')
219+
.then((parsedModule) => {
220+
assert.strictEqual(typeof parsedModule, 'object');
221+
assert.strictEqual(parsedModule.default, 'hello world');
222+
})`,
223+
]);
224+
225+
assert.strictEqual(stderr, '');
226+
assert.strictEqual(stdout, '');
227+
assert.strictEqual(code, 0);
228+
assert.strictEqual(signal, null);
229+
});
230+
231+
it('can provide source for a nonexistent file', async () => {
232+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
233+
'--no-warnings',
234+
'--experimental-loader',
235+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
236+
'--input-type=module',
237+
'--eval',
238+
`import assert from 'node:assert';
239+
await import('esmHook/virtual.mjs')
240+
.then((parsedModule) => {
241+
assert.strictEqual(typeof parsedModule, 'object');
242+
assert.strictEqual(typeof parsedModule.default, 'undefined');
243+
assert.strictEqual(parsedModule.message, 'WOOHOO!');
244+
})`,
245+
]);
246+
247+
assert.strictEqual(stderr, '');
248+
assert.strictEqual(stdout, '');
249+
assert.strictEqual(code, 0);
250+
assert.strictEqual(signal, null);
251+
});
252+
253+
it('ensures that loaders have a separate context from userland', async () => {
254+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
255+
'--no-warnings',
256+
'--experimental-loader',
257+
fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'),
258+
'--input-type=module',
259+
'--eval',
260+
`import assert from 'node:assert';
261+
await import('${fixtures.fileURL('/es-modules/stateful.mjs')}')
262+
.then(({ default: count }) => {
263+
assert.strictEqual(count(), 1);
264+
});`,
265+
]);
266+
267+
assert.strictEqual(stderr, '');
268+
assert.strictEqual(stdout, '');
269+
assert.strictEqual(code, 0);
270+
assert.strictEqual(signal, null);
271+
});
272+
273+
it('ensures that user loaders are not bound to the internal loader', async () => {
274+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
275+
'--no-warnings',
276+
'--experimental-loader',
277+
fixtures.fileURL('/es-module-loaders/loader-this-value-inside-hook-functions.mjs'),
278+
'--input-type=module',
279+
'--eval',
280+
';', // Actual test is inside the loader module.
281+
]);
282+
283+
assert.strictEqual(stderr, '');
284+
assert.strictEqual(stdout, '');
285+
assert.strictEqual(code, 0);
286+
assert.strictEqual(signal, null);
287+
});
288+
});

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy