Skip to content

Commit 0bdf2db

Browse files
GeoffreyBoothjuanarbol
authored andcommitted
esm: rewrite loader hooks test
Rewrite the test that validates that custom loader hooks are called from being a test that depends on internals to one that spawns a child process and checks its output to confirm expected behavior. PR-URL: #46016 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Jacob Smith <jacob@frende.me>
1 parent c1cc1f9 commit 0bdf2db

File tree

2 files changed

+115
-81
lines changed

2 files changed

+115
-81
lines changed
+24-81
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,26 @@
1-
// Flags: --expose-internals
2-
import { mustCall } from '../common/index.mjs';
3-
import esmLoaderModule from 'internal/modules/esm/loader';
4-
import assert from 'assert';
5-
6-
const { ESMLoader } = esmLoaderModule;
7-
8-
/**
9-
* Verify custom hooks are called with appropriate arguments.
10-
*/
11-
{
12-
const esmLoader = new ESMLoader();
13-
14-
const originalSpecifier = 'foo/bar';
15-
const importAssertions = {
16-
__proto__: null,
17-
type: 'json',
18-
};
19-
const parentURL = 'file:///entrypoint.js';
20-
const resolvedURL = 'file:///foo/bar.js';
21-
const suggestedFormat = 'test';
22-
23-
function resolve(specifier, context, defaultResolve) {
24-
assert.strictEqual(specifier, originalSpecifier);
25-
// Ensure `context` has all and only the properties it's supposed to
26-
assert.deepStrictEqual(Object.keys(context), [
27-
'conditions',
28-
'importAssertions',
29-
'parentURL',
30-
]);
31-
assert.ok(Array.isArray(context.conditions));
32-
assert.deepStrictEqual(context.importAssertions, importAssertions);
33-
assert.strictEqual(context.parentURL, parentURL);
34-
assert.strictEqual(typeof defaultResolve, 'function');
35-
36-
return {
37-
format: suggestedFormat,
38-
shortCircuit: true,
39-
url: resolvedURL,
40-
};
41-
}
42-
43-
function load(resolvedURL, context, defaultLoad) {
44-
assert.strictEqual(resolvedURL, resolvedURL);
45-
assert.ok(new URL(resolvedURL));
46-
// Ensure `context` has all and only the properties it's supposed to
47-
assert.deepStrictEqual(Object.keys(context), [
48-
'format',
49-
'importAssertions',
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', () => {
8+
it('are called with all expected arguments', async () => {
9+
const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [
10+
'--no-warnings',
11+
'--experimental-loader',
12+
fixtures.fileURL('/es-module-loaders/hooks-input.mjs'),
13+
fixtures.path('/es-modules/json-modules.mjs'),
5014
]);
51-
assert.strictEqual(context.format, suggestedFormat);
52-
assert.deepStrictEqual(context.importAssertions, importAssertions);
53-
assert.strictEqual(typeof defaultLoad, 'function');
54-
55-
// This doesn't matter (just to avoid errors)
56-
return {
57-
format: 'module',
58-
shortCircuit: true,
59-
source: '',
60-
};
61-
}
62-
63-
const customLoader = [
64-
{
65-
exports: {
66-
// Ensure ESMLoader actually calls the custom hooks
67-
resolve: mustCall(resolve),
68-
load: mustCall(load),
69-
},
70-
url: import.meta.url,
71-
},
72-
];
73-
74-
esmLoader.addCustomLoaders(customLoader);
7515

76-
// Manually trigger hooks (since ESMLoader is not actually running)
77-
const job = await esmLoader.getModuleJob(
78-
originalSpecifier,
79-
parentURL,
80-
importAssertions,
81-
);
82-
await job.modulePromise;
83-
}
16+
assert.strictEqual(stderr, '');
17+
assert.strictEqual(code, 0);
18+
assert.strictEqual(signal, null);
19+
20+
const lines = stdout.split('\n');
21+
assert.match(lines[0], /{"url":"file:\/\/\/.*\/json-modules\.mjs","format":"test","shortCircuit":true}/);
22+
assert.match(lines[1], /{"source":{"type":"Buffer","data":\[.*\]},"format":"module","shortCircuit":true}/);
23+
assert.match(lines[2], /{"url":"file:\/\/\/.*\/experimental\.json","format":"test","shortCircuit":true}/);
24+
assert.match(lines[3], /{"source":{"type":"Buffer","data":\[.*\]},"format":"json","shortCircuit":true}/);
25+
});
26+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// This is expected to be used by test-esm-loader-hooks.mjs via:
2+
// node --loader ./test/fixtures/es-module-loaders/hooks-input.mjs ./test/fixtures/es-modules/json-modules.mjs
3+
4+
import assert from 'assert';
5+
import { readFile } from 'fs/promises';
6+
import { fileURLToPath } from 'url';
7+
8+
9+
let resolveCalls = 0;
10+
let loadCalls = 0;
11+
12+
export async function resolve(specifier, context, next) {
13+
resolveCalls++;
14+
let url;
15+
16+
if (resolveCalls === 1) {
17+
url = new URL(specifier).href;
18+
assert.match(specifier, /json-modules\.mjs$/);
19+
assert.strictEqual(context.parentURL, undefined);
20+
assert.deepStrictEqual(context.importAssertions, {
21+
__proto__: null,
22+
});
23+
} else if (resolveCalls === 2) {
24+
url = new URL(specifier, context.parentURL).href;
25+
assert.match(specifier, /experimental\.json$/);
26+
assert.match(context.parentURL, /json-modules\.mjs$/);
27+
assert.deepStrictEqual(context.importAssertions, {
28+
__proto__: null,
29+
type: 'json',
30+
});
31+
}
32+
33+
// Ensure `context` has all and only the properties it's supposed to
34+
assert.deepStrictEqual(Reflect.ownKeys(context), [
35+
'conditions',
36+
'importAssertions',
37+
'parentURL',
38+
]);
39+
assert.ok(Array.isArray(context.conditions));
40+
assert.strictEqual(typeof next, 'function');
41+
42+
const returnValue = {
43+
url,
44+
format: 'test',
45+
shortCircuit: true,
46+
}
47+
48+
console.log(JSON.stringify(returnValue)); // For the test to validate when it parses stdout
49+
50+
return returnValue;
51+
}
52+
53+
export async function load(url, context, next) {
54+
loadCalls++;
55+
const source = await readFile(fileURLToPath(url));
56+
let format;
57+
58+
if (loadCalls === 1) {
59+
assert.match(url, /json-modules\.mjs$/);
60+
assert.deepStrictEqual(context.importAssertions, {
61+
__proto__: null,
62+
});
63+
format = 'module';
64+
} else if (loadCalls === 2) {
65+
assert.match(url, /experimental\.json$/);
66+
assert.deepStrictEqual(context.importAssertions, {
67+
__proto__: null,
68+
type: 'json',
69+
});
70+
format = 'json';
71+
}
72+
73+
assert.ok(new URL(url));
74+
// Ensure `context` has all and only the properties it's supposed to
75+
assert.deepStrictEqual(Object.keys(context), [
76+
'format',
77+
'importAssertions',
78+
]);
79+
assert.strictEqual(context.format, 'test');
80+
assert.strictEqual(typeof next, 'function');
81+
82+
const returnValue = {
83+
source,
84+
format,
85+
shortCircuit: true,
86+
};
87+
88+
console.log(JSON.stringify(returnValue)); // For the test to validate when it parses stdout
89+
90+
return returnValue;
91+
}

0 commit comments

Comments
 (0)