mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
test: refactor ESM tests to improve performance
PR-URL: https://github.com/nodejs/node/pull/43784 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
parent
e5add6659d
commit
447635b440
56 changed files with 1386 additions and 1438 deletions
|
@ -336,7 +336,7 @@ class ESMLoader {
|
|||
* A list of exports from user-defined loaders (as returned by
|
||||
* ESMLoader.import()).
|
||||
*/
|
||||
async addCustomLoaders(
|
||||
addCustomLoaders(
|
||||
customLoaders = [],
|
||||
) {
|
||||
for (let i = 0; i < customLoaders.length; i++) {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
const process = global.process; // Some tests tamper with the process global.
|
||||
|
||||
const assert = require('assert');
|
||||
const { exec, execSync, spawnSync } = require('child_process');
|
||||
const { exec, execSync, spawn, spawnSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
// Do not require 'os' until needed so that test-os-checked-function can
|
||||
// monkey patch it. If 'os' is required here, that test will fail.
|
||||
|
@ -842,6 +842,36 @@ function requireNoPackageJSONAbove(dir = __dirname) {
|
|||
}
|
||||
}
|
||||
|
||||
function spawnPromisified(...args) {
|
||||
let stderr = '';
|
||||
let stdout = '';
|
||||
|
||||
const child = spawn(...args);
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => { stderr += data; });
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', (data) => { stdout += data; });
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
child.on('close', (code, signal) => {
|
||||
resolve({
|
||||
code,
|
||||
signal,
|
||||
stderr,
|
||||
stdout,
|
||||
});
|
||||
});
|
||||
child.on('error', (code, signal) => {
|
||||
reject({
|
||||
code,
|
||||
signal,
|
||||
stderr,
|
||||
stdout,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const common = {
|
||||
allowGlobals,
|
||||
buildType,
|
||||
|
@ -891,6 +921,7 @@ const common = {
|
|||
skipIfEslintMissing,
|
||||
skipIfInspectorDisabled,
|
||||
skipIfWorker,
|
||||
spawnPromisified,
|
||||
|
||||
get enoughTestMem() {
|
||||
return require('os').totalmem() > 0x70000000; /* 1.75 Gb */
|
||||
|
|
|
@ -23,53 +23,7 @@ const {
|
|||
hasCrypto,
|
||||
hasIPv6,
|
||||
childShouldThrowAndAbort,
|
||||
createZeroFilledFile,
|
||||
platformTimeout,
|
||||
allowGlobals,
|
||||
mustCall,
|
||||
mustCallAtLeast,
|
||||
mustSucceed,
|
||||
hasMultiLocalhost,
|
||||
skipIfDumbTerminal,
|
||||
skipIfEslintMissing,
|
||||
canCreateSymLink,
|
||||
getCallSite,
|
||||
mustNotCall,
|
||||
mustNotMutateObjectDeep,
|
||||
printSkipMessage,
|
||||
skip,
|
||||
nodeProcessAborted,
|
||||
isAlive,
|
||||
expectWarning,
|
||||
expectsError,
|
||||
skipIfInspectorDisabled,
|
||||
skipIf32Bits,
|
||||
getArrayBufferViews,
|
||||
getBufferSources,
|
||||
getTTYfd,
|
||||
runWithInvalidFD
|
||||
} = common;
|
||||
|
||||
export {
|
||||
isMainThread,
|
||||
isWindows,
|
||||
isAIX,
|
||||
isIBMi,
|
||||
isLinuxPPCBE,
|
||||
isSunOS,
|
||||
isDumbTerminal,
|
||||
isFreeBSD,
|
||||
isOpenBSD,
|
||||
isLinux,
|
||||
isOSX,
|
||||
enoughTestMem,
|
||||
buildType,
|
||||
localIPv6Hosts,
|
||||
opensslCli,
|
||||
PIPE,
|
||||
hasCrypto,
|
||||
hasIPv6,
|
||||
childShouldThrowAndAbort,
|
||||
checkoutEOL,
|
||||
createZeroFilledFile,
|
||||
platformTimeout,
|
||||
allowGlobals,
|
||||
|
@ -95,5 +49,55 @@ export {
|
|||
getBufferSources,
|
||||
getTTYfd,
|
||||
runWithInvalidFD,
|
||||
createRequire
|
||||
spawnPromisified,
|
||||
} = common;
|
||||
|
||||
export {
|
||||
isMainThread,
|
||||
isWindows,
|
||||
isAIX,
|
||||
isIBMi,
|
||||
isLinuxPPCBE,
|
||||
isSunOS,
|
||||
isDumbTerminal,
|
||||
isFreeBSD,
|
||||
isOpenBSD,
|
||||
isLinux,
|
||||
isOSX,
|
||||
enoughTestMem,
|
||||
buildType,
|
||||
localIPv6Hosts,
|
||||
opensslCli,
|
||||
PIPE,
|
||||
hasCrypto,
|
||||
hasIPv6,
|
||||
childShouldThrowAndAbort,
|
||||
checkoutEOL,
|
||||
createZeroFilledFile,
|
||||
platformTimeout,
|
||||
allowGlobals,
|
||||
mustCall,
|
||||
mustCallAtLeast,
|
||||
mustSucceed,
|
||||
hasMultiLocalhost,
|
||||
skipIfDumbTerminal,
|
||||
skipIfEslintMissing,
|
||||
canCreateSymLink,
|
||||
getCallSite,
|
||||
mustNotCall,
|
||||
mustNotMutateObjectDeep,
|
||||
printSkipMessage,
|
||||
skip,
|
||||
nodeProcessAborted,
|
||||
isAlive,
|
||||
expectWarning,
|
||||
expectsError,
|
||||
skipIfInspectorDisabled,
|
||||
skipIf32Bits,
|
||||
getArrayBufferViews,
|
||||
getBufferSources,
|
||||
getTTYfd,
|
||||
runWithInvalidFD,
|
||||
createRequire,
|
||||
spawnPromisified,
|
||||
};
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { spawn } = require('child_process');
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const { spawnPromisified } = require('../common');
|
||||
const fixtures = require('../common/fixtures.js');
|
||||
const assert = require('node:assert');
|
||||
const path = require('node:path');
|
||||
const { execPath } = require('node:process');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
|
||||
const requiringCjsAsEsm = path.resolve(fixtures.path('/es-modules/cjs-esm.js'));
|
||||
const requiringEsm = path.resolve(fixtures.path('/es-modules/cjs-esm-esm.js'));
|
||||
|
@ -12,53 +14,55 @@ const pjson = path.resolve(
|
|||
fixtures.path('/es-modules/package-type-module/package.json')
|
||||
);
|
||||
|
||||
{
|
||||
const required = path.resolve(
|
||||
fixtures.path('/es-modules/package-type-module/cjs.js')
|
||||
);
|
||||
const basename = 'cjs.js';
|
||||
const child = spawn(process.execPath, [requiringCjsAsEsm]);
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', common.mustCall((code, signal) => {
|
||||
|
||||
describe('CJS ↔︎ ESM interop warnings', { concurrency: true }, () => {
|
||||
|
||||
it(async () => {
|
||||
const required = path.resolve(
|
||||
fixtures.path('/es-modules/package-type-module/cjs.js')
|
||||
);
|
||||
const basename = 'cjs.js';
|
||||
const { code, signal, stderr } = await spawnPromisified(execPath, [requiringCjsAsEsm]);
|
||||
|
||||
assert.ok(
|
||||
stderr.replaceAll('\r', '').includes(
|
||||
`Error [ERR_REQUIRE_ESM]: require() of ES Module ${required} from ${requiringCjsAsEsm} not supported.\n`
|
||||
)
|
||||
);
|
||||
assert.ok(
|
||||
stderr.replaceAll('\r', '').includes(
|
||||
`Instead rename ${basename} to end in .cjs, change the requiring ` +
|
||||
'code to use dynamic import() which is available in all CommonJS ' +
|
||||
`modules, or change "type": "module" to "type": "commonjs" in ${pjson} to ` +
|
||||
'treat all .js files as CommonJS (using .mjs for all ES modules ' +
|
||||
'instead).\n'
|
||||
)
|
||||
);
|
||||
|
||||
assert.strictEqual(code, 1);
|
||||
assert.strictEqual(signal, null);
|
||||
|
||||
assert.ok(stderr.replaceAll('\r', '').includes(
|
||||
`Error [ERR_REQUIRE_ESM]: require() of ES Module ${required} from ${
|
||||
requiringCjsAsEsm} not supported.\n`));
|
||||
assert.ok(stderr.replaceAll('\r', '').includes(
|
||||
`Instead rename ${basename} to end in .cjs, change the requiring ` +
|
||||
'code to use dynamic import() which is available in all CommonJS ' +
|
||||
`modules, or change "type": "module" to "type": "commonjs" in ${pjson} to ` +
|
||||
'treat all .js files as CommonJS (using .mjs for all ES modules ' +
|
||||
'instead).\n'));
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
const required = path.resolve(
|
||||
fixtures.path('/es-modules/package-type-module/esm.js')
|
||||
);
|
||||
const basename = 'esm.js';
|
||||
const child = spawn(process.execPath, [requiringEsm]);
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', common.mustCall((code, signal) => {
|
||||
|
||||
it(async () => {
|
||||
const required = path.resolve(
|
||||
fixtures.path('/es-modules/package-type-module/esm.js')
|
||||
);
|
||||
const basename = 'esm.js';
|
||||
const { code, signal, stderr } = await spawnPromisified(execPath, [requiringEsm]);
|
||||
|
||||
assert.ok(
|
||||
stderr.replace(/\r/g, '').includes(
|
||||
`Error [ERR_REQUIRE_ESM]: require() of ES Module ${required} from ${requiringEsm} not supported.\n`
|
||||
)
|
||||
);
|
||||
assert.ok(
|
||||
stderr.replace(/\r/g, '').includes(
|
||||
`Instead change the require of ${basename} in ${requiringEsm} to` +
|
||||
' a dynamic import() which is available in all CommonJS modules.\n'
|
||||
)
|
||||
);
|
||||
|
||||
assert.strictEqual(code, 1);
|
||||
assert.strictEqual(signal, null);
|
||||
|
||||
assert.ok(stderr.replace(/\r/g, '').includes(
|
||||
`Error [ERR_REQUIRE_ESM]: require() of ES Module ${required} from ${
|
||||
requiringEsm} not supported.\n`));
|
||||
assert.ok(stderr.replace(/\r/g, '').includes(
|
||||
`Instead change the require of ${basename} in ${requiringEsm} to` +
|
||||
' a dynamic import() which is available in all CommonJS modules.\n'));
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { spawn } = require('child_process');
|
||||
const assert = require('assert');
|
||||
const { spawnPromisified } = require('../common');
|
||||
const fixtures = require('../common/fixtures.js');
|
||||
const assert = require('node:assert');
|
||||
const { execPath } = require('node:process');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
|
||||
const entry = fixtures.path('/es-modules/builtin-imports-case.mjs');
|
||||
|
||||
const child = spawn(process.execPath, [entry]);
|
||||
child.stderr.setEncoding('utf8');
|
||||
let stdout = '';
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', (data) => {
|
||||
stdout += data;
|
||||
describe('ESM: importing builtins & CJS', () => {
|
||||
it('should work', async () => {
|
||||
const { code, signal, stdout } = await spawnPromisified(execPath, [entry]);
|
||||
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.strictEqual(stdout, 'ok\n');
|
||||
});
|
||||
});
|
||||
child.on('close', common.mustCall((code, signal) => {
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.strictEqual(stdout, 'ok\n');
|
||||
}));
|
||||
|
|
|
@ -1,35 +1,29 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { spawn } = require('child_process');
|
||||
const assert = require('assert');
|
||||
const { spawnPromisified } = require('../common');
|
||||
const fixtures = require('../common/fixtures.js');
|
||||
const assert = require('node:assert');
|
||||
const { execPath } = require('node:process');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
const entry = fixtures.path('/es-modules/cjs-exports.mjs');
|
||||
|
||||
let child = spawn(process.execPath, [entry]);
|
||||
child.stderr.setEncoding('utf8');
|
||||
let stdout = '';
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', (data) => {
|
||||
stdout += data;
|
||||
describe('ESM: importing CJS', { concurrency: true }, () => {
|
||||
it('should support valid CJS exports', async () => {
|
||||
const validEntry = fixtures.path('/es-modules/cjs-exports.mjs');
|
||||
const { code, signal, stdout } = await spawnPromisified(execPath, [validEntry]);
|
||||
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.strictEqual(stdout, 'ok\n');
|
||||
});
|
||||
|
||||
it('should eror on invalid CJS exports', async () => {
|
||||
const invalidEntry = fixtures.path('/es-modules/cjs-exports-invalid.mjs');
|
||||
const { code, signal, stderr } = await spawnPromisified(execPath, [invalidEntry]);
|
||||
|
||||
assert.strictEqual(code, 1);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.ok(stderr.includes('Warning: To load an ES module'));
|
||||
assert.ok(stderr.includes('Unexpected token \'export\''));
|
||||
});
|
||||
});
|
||||
child.on('close', common.mustCall((code, signal) => {
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.strictEqual(stdout, 'ok\n');
|
||||
}));
|
||||
|
||||
const entryInvalid = fixtures.path('/es-modules/cjs-exports-invalid.mjs');
|
||||
child = spawn(process.execPath, [entryInvalid]);
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', common.mustCall((code, signal) => {
|
||||
assert.strictEqual(code, 1);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.ok(stderr.includes('Warning: To load an ES module'));
|
||||
assert.ok(stderr.includes('Unexpected token \'export\''));
|
||||
}));
|
||||
|
|
|
@ -1,163 +1,96 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import assert from 'assert';
|
||||
import fixtures from '../common/fixtures.js';
|
||||
import { spawn } from 'child_process';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import assert from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
const Export1 = fixtures.path('/es-modules/es-note-unexpected-export-1.cjs');
|
||||
const Export2 = fixtures.path('/es-modules/es-note-unexpected-export-2.cjs');
|
||||
const Import1 = fixtures.path('/es-modules/es-note-unexpected-import-1.cjs');
|
||||
const Import2 = fixtures.path('/es-modules/es-note-promiserej-import-2.cjs');
|
||||
const Import3 = fixtures.path('/es-modules/es-note-unexpected-import-3.cjs');
|
||||
const Import4 = fixtures.path('/es-modules/es-note-unexpected-import-4.cjs');
|
||||
const Import5 = fixtures.path('/es-modules/es-note-unexpected-import-5.cjs');
|
||||
const Error1 = fixtures.path('/es-modules/es-note-error-1.mjs');
|
||||
const Error2 = fixtures.path('/es-modules/es-note-error-2.mjs');
|
||||
const Error3 = fixtures.path('/es-modules/es-note-error-3.mjs');
|
||||
const Error4 = fixtures.path('/es-modules/es-note-error-4.mjs');
|
||||
|
||||
// Expect note to be included in the error output
|
||||
const expectedNote = 'To load an ES module, ' +
|
||||
'set "type": "module" in the package.json ' +
|
||||
'or use the .mjs extension.';
|
||||
|
||||
const expectedCode = 1;
|
||||
const mustIncludeMessage = {
|
||||
getMessage: () => (stderr) => `${expectedNote} not found in ${stderr}`,
|
||||
includeNote: true,
|
||||
};
|
||||
const mustNotIncludeMessage = {
|
||||
getMessage: () => (stderr) => `${expectedNote} must not be included in ${stderr}`,
|
||||
includeNote: false,
|
||||
};
|
||||
|
||||
const pExport1 = spawn(process.execPath, [Export1]);
|
||||
let pExport1Stderr = '';
|
||||
pExport1.stderr.setEncoding('utf8');
|
||||
pExport1.stderr.on('data', (data) => {
|
||||
pExport1Stderr += data;
|
||||
describe('ESM: Errors for unexpected exports', { concurrency: true }, () => {
|
||||
for (
|
||||
const { errorNeedle, filePath, getMessage, includeNote }
|
||||
of [
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-unexpected-export-1.cjs'),
|
||||
...mustIncludeMessage,
|
||||
},
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-unexpected-import-1.cjs'),
|
||||
...mustIncludeMessage,
|
||||
},
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-promiserej-import-2.cjs'),
|
||||
...mustNotIncludeMessage,
|
||||
},
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-unexpected-import-3.cjs'),
|
||||
...mustIncludeMessage,
|
||||
},
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-unexpected-import-4.cjs'),
|
||||
...mustIncludeMessage,
|
||||
},
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-unexpected-import-5.cjs'),
|
||||
...mustNotIncludeMessage,
|
||||
},
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-error-1.mjs'),
|
||||
...mustNotIncludeMessage,
|
||||
errorNeedle: /Error: some error/,
|
||||
},
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-error-2.mjs'),
|
||||
...mustNotIncludeMessage,
|
||||
errorNeedle: /string/,
|
||||
},
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-error-3.mjs'),
|
||||
...mustNotIncludeMessage,
|
||||
errorNeedle: /null/,
|
||||
},
|
||||
{
|
||||
// name: '',
|
||||
filePath: fixtures.path('/es-modules/es-note-error-4.mjs'),
|
||||
...mustNotIncludeMessage,
|
||||
errorNeedle: /undefined/,
|
||||
},
|
||||
]
|
||||
) {
|
||||
it(`should ${includeNote ? '' : 'NOT'} include note`, async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [filePath]);
|
||||
|
||||
assert.strictEqual(code, 1);
|
||||
|
||||
if (errorNeedle != null) assert.match(stderr, errorNeedle);
|
||||
|
||||
const shouldIncludeNote = stderr.includes(expectedNote);
|
||||
assert.ok(
|
||||
includeNote ? shouldIncludeNote : !shouldIncludeNote,
|
||||
`${filePath} ${getMessage(stderr)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
pExport1.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(pExport1Stderr.includes(expectedNote),
|
||||
`${expectedNote} not found in ${pExport1Stderr}`);
|
||||
}));
|
||||
|
||||
|
||||
const pExport2 = spawn(process.execPath, [Export2]);
|
||||
let pExport2Stderr = '';
|
||||
pExport2.stderr.setEncoding('utf8');
|
||||
pExport2.stderr.on('data', (data) => {
|
||||
pExport2Stderr += data;
|
||||
});
|
||||
pExport2.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(pExport2Stderr.includes(expectedNote),
|
||||
`${expectedNote} not found in ${pExport2Stderr}`);
|
||||
}));
|
||||
|
||||
const pImport1 = spawn(process.execPath, [Import1]);
|
||||
let pImport1Stderr = '';
|
||||
pImport1.stderr.setEncoding('utf8');
|
||||
pImport1.stderr.on('data', (data) => {
|
||||
pImport1Stderr += data;
|
||||
});
|
||||
pImport1.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(pImport1Stderr.includes(expectedNote),
|
||||
`${expectedNote} not found in ${pExport1Stderr}`);
|
||||
}));
|
||||
|
||||
// Note this test shouldn't include the note
|
||||
const pImport2 = spawn(process.execPath, [Import2]);
|
||||
let pImport2Stderr = '';
|
||||
pImport2.stderr.setEncoding('utf8');
|
||||
pImport2.stderr.on('data', (data) => {
|
||||
pImport2Stderr += data;
|
||||
});
|
||||
pImport2.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(!pImport2Stderr.includes(expectedNote),
|
||||
`${expectedNote} must not be included in ${pImport2Stderr}`);
|
||||
}));
|
||||
|
||||
const pImport3 = spawn(process.execPath, [Import3]);
|
||||
let pImport3Stderr = '';
|
||||
pImport3.stderr.setEncoding('utf8');
|
||||
pImport3.stderr.on('data', (data) => {
|
||||
pImport3Stderr += data;
|
||||
});
|
||||
pImport3.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(pImport3Stderr.includes(expectedNote),
|
||||
`${expectedNote} not found in ${pImport3Stderr}`);
|
||||
}));
|
||||
|
||||
|
||||
const pImport4 = spawn(process.execPath, [Import4]);
|
||||
let pImport4Stderr = '';
|
||||
pImport4.stderr.setEncoding('utf8');
|
||||
pImport4.stderr.on('data', (data) => {
|
||||
pImport4Stderr += data;
|
||||
});
|
||||
pImport4.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(pImport4Stderr.includes(expectedNote),
|
||||
`${expectedNote} not found in ${pImport4Stderr}`);
|
||||
}));
|
||||
|
||||
// Must exit non-zero and show note
|
||||
const pImport5 = spawn(process.execPath, [Import5]);
|
||||
let pImport5Stderr = '';
|
||||
pImport5.stderr.setEncoding('utf8');
|
||||
pImport5.stderr.on('data', (data) => {
|
||||
pImport5Stderr += data;
|
||||
});
|
||||
pImport5.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(!pImport5Stderr.includes(expectedNote),
|
||||
`${expectedNote} must not be included in ${pImport5Stderr}`);
|
||||
}));
|
||||
|
||||
const pError1 = spawn(process.execPath, [Error1]);
|
||||
let pError1Stderr = '';
|
||||
pError1.stderr.setEncoding('utf8');
|
||||
pError1.stderr.on('data', (data) => {
|
||||
pError1Stderr += data;
|
||||
});
|
||||
pError1.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(pError1Stderr.includes('Error: some error'));
|
||||
assert.ok(!pError1Stderr.includes(expectedNote),
|
||||
`${expectedNote} must not be included in ${pError1Stderr}`);
|
||||
}));
|
||||
|
||||
const pError2 = spawn(process.execPath, [Error2]);
|
||||
let pError2Stderr = '';
|
||||
pError2.stderr.setEncoding('utf8');
|
||||
pError2.stderr.on('data', (data) => {
|
||||
pError2Stderr += data;
|
||||
});
|
||||
pError2.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(pError2Stderr.includes('string'));
|
||||
assert.ok(!pError2Stderr.includes(expectedNote),
|
||||
`${expectedNote} must not be included in ${pError2Stderr}`);
|
||||
}));
|
||||
|
||||
const pError3 = spawn(process.execPath, [Error3]);
|
||||
let pError3Stderr = '';
|
||||
pError3.stderr.setEncoding('utf8');
|
||||
pError3.stderr.on('data', (data) => {
|
||||
pError3Stderr += data;
|
||||
});
|
||||
pError3.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(pError3Stderr.includes('null'));
|
||||
assert.ok(!pError3Stderr.includes(expectedNote),
|
||||
`${expectedNote} must not be included in ${pError3Stderr}`);
|
||||
}));
|
||||
|
||||
const pError4 = spawn(process.execPath, [Error4]);
|
||||
let pError4Stderr = '';
|
||||
pError4.stderr.setEncoding('utf8');
|
||||
pError4.stderr.on('data', (data) => {
|
||||
pError4Stderr += data;
|
||||
});
|
||||
pError4.on('close', mustCall((code) => {
|
||||
assert.strictEqual(code, expectedCode);
|
||||
assert.ok(pError4Stderr.includes('undefined'));
|
||||
assert.ok(!pError4Stderr.includes(expectedNote),
|
||||
`${expectedNote} must not be included in ${pError4Stderr}`);
|
||||
}));
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { spawn } = require('child_process');
|
||||
const assert = require('assert');
|
||||
const { spawnPromisified } = require('../common');
|
||||
const fixtures = require('../common/fixtures.js');
|
||||
const assert = require('node:assert');
|
||||
const { execPath } = require('node:process');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
const entry = fixtures.path('/es-modules/cjs.js');
|
||||
|
||||
const child = spawn(process.execPath, [entry]);
|
||||
child.stderr.setEncoding('utf8');
|
||||
let stdout = '';
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', (data) => {
|
||||
stdout += data;
|
||||
describe('ESM: importing CJS', () => {
|
||||
it('should work', async () => {
|
||||
const { code, signal, stdout } = await spawnPromisified(execPath, [
|
||||
fixtures.path('/es-modules/cjs.js'),
|
||||
]);
|
||||
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.strictEqual(stdout, 'executed\n');
|
||||
});
|
||||
});
|
||||
child.on('close', common.mustCall((code, signal) => {
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.strictEqual(stdout, 'executed\n');
|
||||
}));
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const { spawn } = require('child_process');
|
||||
|
||||
const native = fixtures.path('es-module-url/native.mjs');
|
||||
const child = spawn(process.execPath, [native]);
|
||||
child.on('exit', (code) => {
|
||||
assert.strictEqual(code, 1);
|
||||
const { spawnPromisified } = require('../common');
|
||||
const fixtures = require('../common/fixtures.js');
|
||||
const assert = require('node:assert');
|
||||
const { execPath } = require('node:process');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
|
||||
describe('ESM: importing an encoded path', () => {
|
||||
it('should throw', async () => {
|
||||
const { code } = await spawnPromisified(execPath, [
|
||||
fixtures.path('es-module-url/native.mjs'),
|
||||
]);
|
||||
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,55 +1,48 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import { fileURL } from '../common/fixtures.mjs';
|
||||
import { doesNotMatch, match, strictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { doesNotMatch, match, strictEqual } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
// Verify no warnings are printed when no experimental features are enabled or used
|
||||
{
|
||||
const input = `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`;
|
||||
const child = spawn(execPath, [
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
input,
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => { stderr += data; });
|
||||
child.on('close', mustCall((code, signal) => {
|
||||
strictEqual(code, 0);
|
||||
strictEqual(signal, null);
|
||||
describe('ESM: warn for obsolete hooks provided', { concurrency: true }, () => {
|
||||
it('should not print warnings when no experimental features are enabled or used', async () => {
|
||||
const { code, signal, stderr } = await spawnPromisified(execPath, [
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
`import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`,
|
||||
]);
|
||||
|
||||
doesNotMatch(
|
||||
stderr,
|
||||
/ExperimentalWarning/,
|
||||
new Error('No experimental warning(s) should be emitted when no experimental feature is enabled')
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
// Verify experimental warning is printed when experimental feature is enabled
|
||||
for (
|
||||
const [experiment, arg] of [
|
||||
[/Custom ESM Loaders/, `--experimental-loader=${fileURL('es-module-loaders', 'hooks-custom.mjs')}`],
|
||||
[/Network Imports/, '--experimental-network-imports'],
|
||||
[/specifier resolution/, '--experimental-specifier-resolution=node'],
|
||||
]
|
||||
) {
|
||||
const input = `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`;
|
||||
const child = spawn(execPath, [
|
||||
arg,
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
input,
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => { stderr += data; });
|
||||
child.on('close', mustCall((code, signal) => {
|
||||
strictEqual(code, 0);
|
||||
strictEqual(signal, null);
|
||||
match(stderr, /ExperimentalWarning/);
|
||||
match(stderr, experiment);
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
describe('experimental warnings for enabled experimental feature', () => {
|
||||
for (
|
||||
const [experiment, arg] of [
|
||||
[/Custom ESM Loaders/, `--experimental-loader=${fileURL('es-module-loaders', 'hooks-custom.mjs')}`],
|
||||
[/Network Imports/, '--experimental-network-imports'],
|
||||
[/specifier resolution/, '--experimental-specifier-resolution=node'],
|
||||
]
|
||||
) {
|
||||
it(`should print for ${experiment.toString().replaceAll('/', '')}`, async () => {
|
||||
const { code, signal, stderr } = await spawnPromisified(execPath, [
|
||||
arg,
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
`import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`,
|
||||
]);
|
||||
|
||||
match(stderr, /ExperimentalWarning/);
|
||||
match(stderr, experiment);
|
||||
strictEqual(code, 0);
|
||||
strictEqual(signal, null);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,39 +1,48 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { path } from '../common/fixtures.mjs';
|
||||
import { match, notStrictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import assert from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
const importStatement =
|
||||
'import { foo, notfound } from \'./module-named-exports.mjs\';';
|
||||
|
||||
const importStatement = 'import { foo, notfound } from \'./module-named-exports.mjs\';';
|
||||
const importStatementMultiline = `import {
|
||||
foo,
|
||||
notfound
|
||||
} from './module-named-exports.mjs';
|
||||
`;
|
||||
|
||||
[importStatement, importStatementMultiline].forEach((input) => {
|
||||
const child = spawn(execPath, [
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
input,
|
||||
], {
|
||||
cwd: path('es-module-loaders'),
|
||||
});
|
||||
describe('ESM: nonexistent exports', { concurrency: true }, () => {
|
||||
for (
|
||||
const { name, input }
|
||||
of [
|
||||
{
|
||||
input: importStatement,
|
||||
name: 'single-line import',
|
||||
},
|
||||
{
|
||||
input: importStatementMultiline,
|
||||
name: 'multi-line import',
|
||||
},
|
||||
]
|
||||
) {
|
||||
it(`should throw for nonexistent exports via ${name}`, async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
input,
|
||||
], {
|
||||
cwd: fixtures.path('es-module-loaders'),
|
||||
});
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
assert.notStrictEqual(code, 0);
|
||||
|
||||
// SyntaxError: The requested module './module-named-exports.mjs'
|
||||
// does not provide an export named 'notfound'
|
||||
match(stderr, /SyntaxError:/);
|
||||
// The quotes ensure that the path starts with ./ and not ../
|
||||
match(stderr, /'\.\/module-named-exports\.mjs'/);
|
||||
match(stderr, /notfound/);
|
||||
}));
|
||||
// SyntaxError: The requested module './module-named-exports.mjs'
|
||||
// does not provide an export named 'notfound'
|
||||
assert.match(stderr, /SyntaxError:/);
|
||||
// The quotes ensure that the path starts with ./ and not ../
|
||||
assert.match(stderr, /'\.\/module-named-exports\.mjs'/);
|
||||
assert.match(stderr, /notfound/);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,24 +1,22 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { path } from '../common/fixtures.mjs';
|
||||
import { match, notStrictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import assert from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
const child = spawn(execPath, [
|
||||
path('es-modules', 'import-json-named-export.mjs'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
describe('ESM: named JSON exports', { concurrency: true }, () => {
|
||||
it('should throw, citing named import', async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
fixtures.path('es-modules', 'import-json-named-export.mjs'),
|
||||
]);
|
||||
|
||||
// SyntaxError: The requested module '../experimental.json'
|
||||
// does not provide an export named 'ofLife'
|
||||
assert.match(stderr, /SyntaxError:/);
|
||||
assert.match(stderr, /'\.\.\/experimental\.json'/);
|
||||
assert.match(stderr, /'ofLife'/);
|
||||
|
||||
assert.notStrictEqual(code, 0);
|
||||
});
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
|
||||
// SyntaxError: The requested module '../experimental.json'
|
||||
// does not provide an export named 'ofLife'
|
||||
match(stderr, /SyntaxError:/);
|
||||
match(stderr, /'\.\.\/experimental\.json'/);
|
||||
match(stderr, /'ofLife'/);
|
||||
}));
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
import '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import assert from 'node:assert';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
|
||||
{ // Verify unadulterated source is loaded when there are no loaders
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
describe('ESM: ensure initialisation happens only once', { concurrency: true }, () => {
|
||||
it(async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--no-warnings',
|
||||
fixtures.path('es-modules', 'runmain.mjs'),
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
]);
|
||||
|
||||
// Length minus 1 because the first match is the needle.
|
||||
const resolveHookRunCount = (stdout.match(/resolve passthru/g)?.length ?? 0) - 1;
|
||||
// Length minus 1 because the first match is the needle.
|
||||
const resolveHookRunCount = (stdout.match(/resolve passthru/g)?.length ?? 0) - 1;
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
/**
|
||||
* resolveHookRunCount = 2:
|
||||
* 1. fixtures/…/runmain.mjs
|
||||
* 2. node:module (imported by fixtures/…/runmain.mjs)
|
||||
*/
|
||||
assert.strictEqual(resolveHookRunCount, 2);
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
/**
|
||||
* resolveHookRunCount = 2:
|
||||
* 1. fixtures/…/runmain.mjs
|
||||
* 2. node:module (imported by fixtures/…/runmain.mjs)
|
||||
*/
|
||||
assert.strictEqual(resolveHookRunCount, 2);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
'use strict';
|
||||
require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const assert = require('assert');
|
||||
const { spawnSync } = require('child_process');
|
||||
const fixture = fixtures.path('/es-modules/import-invalid-ext.mjs');
|
||||
const child = spawnSync(process.execPath, [fixture]);
|
||||
const errMsg = 'TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension';
|
||||
|
||||
assert.strictEqual(child.status, 1);
|
||||
assert.strictEqual(child.signal, null);
|
||||
assert.strictEqual(child.stdout.toString().trim(), '');
|
||||
assert.ok(child.stderr.toString().includes(errMsg));
|
|
@ -1,27 +1,28 @@
|
|||
'use strict';
|
||||
|
||||
const { mustCall, checkoutEOL } = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { spawn } = require('child_process');
|
||||
const { strictEqual, ok } = require('assert');
|
||||
const { checkoutEOL, spawnPromisified } = require('../common');
|
||||
const fixtures = require('../common/fixtures.js');
|
||||
const assert = require('node:assert');
|
||||
const { execPath } = require('node:process');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
const entry = fixtures.path('/es-modules/import-invalid-pjson.mjs');
|
||||
const invalidJson = fixtures.path('/node_modules/invalid-pjson/package.json');
|
||||
|
||||
const child = spawn(process.execPath, [entry]);
|
||||
child.stderr.setEncoding('utf8');
|
||||
let stderr = '';
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
describe('ESM: Package.json', { concurrency: true }, () => {
|
||||
it('should throw on invalid pson', async () => {
|
||||
const entry = fixtures.path('/es-modules/import-invalid-pjson.mjs');
|
||||
const invalidJson = fixtures.path('/node_modules/invalid-pjson/package.json');
|
||||
|
||||
const { code, signal, stderr } = await spawnPromisified(execPath, [entry]);
|
||||
|
||||
assert.ok(
|
||||
stderr.includes(
|
||||
`[ERR_INVALID_PACKAGE_CONFIG]: Invalid package config ${invalidJson} ` +
|
||||
`while importing "invalid-pjson" from ${entry}. ` +
|
||||
`Unexpected token } in JSON at position ${12 + checkoutEOL.length * 2}`
|
||||
),
|
||||
stderr
|
||||
);
|
||||
assert.strictEqual(code, 1);
|
||||
assert.strictEqual(signal, null);
|
||||
});
|
||||
});
|
||||
child.on('close', mustCall((code, signal) => {
|
||||
strictEqual(code, 1);
|
||||
strictEqual(signal, null);
|
||||
ok(
|
||||
stderr.includes(
|
||||
`[ERR_INVALID_PACKAGE_CONFIG]: Invalid package config ${invalidJson} ` +
|
||||
`while importing "invalid-pjson" from ${entry}. ` +
|
||||
`Unexpected token } in JSON at position ${12 + checkoutEOL.length * 2}`
|
||||
),
|
||||
stderr);
|
||||
}));
|
||||
|
|
|
@ -1,27 +1,25 @@
|
|||
import '../common/index.mjs';
|
||||
import { path } from '../common/fixtures.mjs';
|
||||
import { strictEqual, ok } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import assert from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import secret from '../fixtures/experimental.json' assert { type: 'json' };
|
||||
|
||||
strictEqual(secret.ofLife, 42);
|
||||
|
||||
// Test warning message
|
||||
const child = spawn(process.execPath, [
|
||||
path('/es-modules/json-modules.mjs'),
|
||||
]);
|
||||
describe('ESM: importing JSON', () => {
|
||||
it('should load JSON', () => {
|
||||
assert.strictEqual(secret.ofLife, 42);
|
||||
});
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', (code, signal) => {
|
||||
strictEqual(code, 0);
|
||||
strictEqual(signal, null);
|
||||
ok(stderr.toString().includes(
|
||||
'ExperimentalWarning: Importing JSON modules is an experimental feature. ' +
|
||||
'This feature could change at any time'
|
||||
));
|
||||
it('should print an experimental warning', async () => {
|
||||
const { code, signal, stderr } = await spawnPromisified(execPath, [
|
||||
fixtures.path('/es-modules/json-modules.mjs'),
|
||||
]);
|
||||
|
||||
assert.match(stderr, /ExperimentalWarning/);
|
||||
assert.match(stderr, /JSON modules/);
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(signal, null);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import '../common/index.mjs';
|
||||
import fixtures from '../common/fixtures.js';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import assert from 'node:assert';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
|
||||
const setupArgs = [
|
||||
'--no-warnings',
|
||||
|
@ -14,420 +16,420 @@ const commonArgs = [
|
|||
commonInput,
|
||||
];
|
||||
|
||||
{ // Verify unadulterated source is loaded when there are no loaders
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
...setupArgs,
|
||||
'import fs from "node:fs"; console.log(typeof fs?.constants?.F_OK )',
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
describe('ESM: loader chaining', { concurrency: true }, () => {
|
||||
it('should load unadulterated source when there are no loaders', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
...setupArgs,
|
||||
'import fs from "node:fs"; console.log(typeof fs?.constants?.F_OK )',
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /number/); // node:fs is an object
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /number/); // node:fs is an object
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
{ // Verify loaded source is properly different when only load changes something
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
it('should load properly different source when only load changes something', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /load passthru/);
|
||||
assert.match(stdout, /resolve passthru/);
|
||||
assert.match(stdout, /foo/);
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /load passthru/);
|
||||
assert.match(stdout, /resolve passthru/);
|
||||
assert.match(stdout, /foo/);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
{ // Verify multiple changes from hooks result in proper output
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-foo.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
it('should result in proper output from multiple changes in resolve hooks', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-foo.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /resolve 42/); // It did go thru resolve-42
|
||||
assert.match(stdout, /foo/); // LIFO, so resolve-foo won
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /resolve 42/); // It did go thru resolve-42
|
||||
assert.match(stdout, /foo/); // LIFO, so resolve-foo won
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
{ // Verify modifying context within resolve chain is respected
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-receiving-modified-context.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passing-modified-context.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
it('should respect modified context within resolve chain', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-receiving-modified-context.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passing-modified-context.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /bar/);
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /bar/);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
{ // Verify multiple changes from hooks result in proper output
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-foo.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
it('should result in proper output from multiple changes in resolve hooks', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-foo.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /resolve foo/); // It did go thru resolve-foo
|
||||
assert.match(stdout, /42/); // LIFO, so resolve-42 won
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /resolve foo/); // It did go thru resolve-foo
|
||||
assert.match(stdout, /42/); // LIFO, so resolve-42 won
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
{ // Verify multiple calls to next within same loader receive correct "next" fn
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-foo.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-multiple-next-calls.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
it('should provide the correct "next" fn when multiple calls to next within same loader', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-foo.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-multiple-next-calls.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
const countFoos = stdout.match(/resolve foo/g)?.length;
|
||||
const countFoos = stdout.match(/resolve foo/g)?.length;
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(countFoos, 2);
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(countFoos, 2);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
{ // Verify next<HookName> function's `name` is correct
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
it('should use the correct `name` for next<HookName>\'s function', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /next<HookName>: nextResolve/);
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /next<HookName>: nextResolve/);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
{ // Verify error thrown for incomplete resolve chain, citing errant loader & hook
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
it('should throw for incomplete resolve chain, citing errant loader & hook', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.match(stdout, /resolve passthru/);
|
||||
assert.match(stderr, /ERR_LOADER_CHAIN_INCOMPLETE/);
|
||||
assert.match(stderr, /loader-resolve-incomplete\.mjs/);
|
||||
assert.match(stderr, /'resolve'/);
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
assert.match(stdout, /resolve passthru/);
|
||||
assert.match(stderr, /ERR_LOADER_CHAIN_INCOMPLETE/);
|
||||
assert.match(stderr, /loader-resolve-incomplete\.mjs/);
|
||||
assert.match(stderr, /'resolve'/);
|
||||
assert.strictEqual(status, 1);
|
||||
}
|
||||
it('should NOT throw when nested resolve hook signaled a short circuit', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-next-modified.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify error NOT thrown when nested resolve hook signaled a short circuit
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-next-modified.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(stdout.trim(), 'foo');
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(stdout.trim(), 'foo');
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
it('should NOT throw when nested load hook signaled a short circuit', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-next-modified.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify error NOT thrown when nested load hook signaled a short circuit
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-next-modified.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /421/);
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.match(stdout, /421/);
|
||||
assert.strictEqual(status, 0);
|
||||
}
|
||||
it('should throw when the resolve chain is broken', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify resolve chain does break and throws appropriately
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.doesNotMatch(stdout, /resolve passthru/);
|
||||
assert.match(stderr, /ERR_LOADER_CHAIN_INCOMPLETE/);
|
||||
assert.match(stderr, /loader-resolve-incomplete\.mjs/);
|
||||
assert.match(stderr, /'resolve'/);
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
assert.doesNotMatch(stdout, /resolve passthru/);
|
||||
assert.match(stderr, /ERR_LOADER_CHAIN_INCOMPLETE/);
|
||||
assert.match(stderr, /loader-resolve-incomplete\.mjs/);
|
||||
assert.match(stderr, /'resolve'/);
|
||||
assert.strictEqual(status, 1);
|
||||
}
|
||||
it('should throw for incomplete load chain, citing errant loader & hook', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-incomplete.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify error thrown for incomplete load chain, citing errant loader & hook
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-incomplete.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.match(stdout, /load passthru/);
|
||||
assert.match(stderr, /ERR_LOADER_CHAIN_INCOMPLETE/);
|
||||
assert.match(stderr, /loader-load-incomplete\.mjs/);
|
||||
assert.match(stderr, /'load'/);
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
assert.match(stdout, /load passthru/);
|
||||
assert.match(stderr, /ERR_LOADER_CHAIN_INCOMPLETE/);
|
||||
assert.match(stderr, /loader-load-incomplete\.mjs/);
|
||||
assert.match(stderr, /'load'/);
|
||||
assert.strictEqual(status, 1);
|
||||
}
|
||||
it('should throw when the load chain is broken', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-incomplete.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify load chain does break and throws appropriately
|
||||
const { status, stderr, stdout } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-incomplete.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.doesNotMatch(stdout, /load passthru/);
|
||||
assert.match(stderr, /ERR_LOADER_CHAIN_INCOMPLETE/);
|
||||
assert.match(stderr, /loader-load-incomplete\.mjs/);
|
||||
assert.match(stderr, /'load'/);
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
assert.doesNotMatch(stdout, /load passthru/);
|
||||
assert.match(stderr, /ERR_LOADER_CHAIN_INCOMPLETE/);
|
||||
assert.match(stderr, /loader-load-incomplete\.mjs/);
|
||||
assert.match(stderr, /'load'/);
|
||||
assert.strictEqual(status, 1);
|
||||
}
|
||||
it('should throw when invalid `specifier` argument passed to `nextResolve`', async () => {
|
||||
const { code, stderr } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-bad-next-specifier.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify error thrown when invalid `specifier` argument passed to `nextResolve`
|
||||
const { status, stderr } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-bad-next-specifier.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.strictEqual(code, 1);
|
||||
assert.match(stderr, /ERR_INVALID_ARG_TYPE/);
|
||||
assert.match(stderr, /loader-resolve-bad-next-specifier\.mjs/);
|
||||
assert.match(stderr, /'resolve' hook's nextResolve\(\) specifier/);
|
||||
});
|
||||
|
||||
assert.strictEqual(status, 1);
|
||||
assert.match(stderr, /ERR_INVALID_ARG_TYPE/);
|
||||
assert.match(stderr, /loader-resolve-bad-next-specifier\.mjs/);
|
||||
assert.match(stderr, /'resolve' hook's nextResolve\(\) specifier/);
|
||||
}
|
||||
it('should throw when resolve hook is invalid', async () => {
|
||||
const { code, stderr } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-null-return.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify error thrown when resolve hook is invalid
|
||||
const { status, stderr } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-null-return.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.strictEqual(code, 1);
|
||||
assert.match(stderr, /ERR_INVALID_RETURN_VALUE/);
|
||||
assert.match(stderr, /loader-resolve-null-return\.mjs/);
|
||||
assert.match(stderr, /'resolve' hook's nextResolve\(\)/);
|
||||
assert.match(stderr, /an object/);
|
||||
assert.match(stderr, /got null/);
|
||||
});
|
||||
|
||||
assert.strictEqual(status, 1);
|
||||
assert.match(stderr, /ERR_INVALID_RETURN_VALUE/);
|
||||
assert.match(stderr, /loader-resolve-null-return\.mjs/);
|
||||
assert.match(stderr, /'resolve' hook's nextResolve\(\)/);
|
||||
assert.match(stderr, /an object/);
|
||||
assert.match(stderr, /got null/);
|
||||
}
|
||||
it('should throw when invalid `context` argument passed to `nextResolve`', async () => {
|
||||
const { code, stderr } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-bad-next-context.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify error thrown when invalid `context` argument passed to `nextResolve`
|
||||
const { status, stderr } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-resolve-bad-next-context.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.match(stderr, /ERR_INVALID_ARG_TYPE/);
|
||||
assert.match(stderr, /loader-resolve-bad-next-context\.mjs/);
|
||||
assert.match(stderr, /'resolve' hook's nextResolve\(\) context/);
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
assert.match(stderr, /ERR_INVALID_ARG_TYPE/);
|
||||
assert.match(stderr, /loader-resolve-bad-next-context\.mjs/);
|
||||
assert.match(stderr, /'resolve' hook's nextResolve\(\) context/);
|
||||
assert.strictEqual(status, 1);
|
||||
}
|
||||
it('should throw when load hook is invalid', async () => {
|
||||
const { code, stderr } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-null-return.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify error thrown when load hook is invalid
|
||||
const { status, stderr } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-null-return.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.strictEqual(code, 1);
|
||||
assert.match(stderr, /ERR_INVALID_RETURN_VALUE/);
|
||||
assert.match(stderr, /loader-load-null-return\.mjs/);
|
||||
assert.match(stderr, /'load' hook's nextLoad\(\)/);
|
||||
assert.match(stderr, /an object/);
|
||||
assert.match(stderr, /got null/);
|
||||
});
|
||||
|
||||
assert.strictEqual(status, 1);
|
||||
assert.match(stderr, /ERR_INVALID_RETURN_VALUE/);
|
||||
assert.match(stderr, /loader-load-null-return\.mjs/);
|
||||
assert.match(stderr, /'load' hook's nextLoad\(\)/);
|
||||
assert.match(stderr, /an object/);
|
||||
assert.match(stderr, /got null/);
|
||||
}
|
||||
it('should throw when invalid `url` argument passed to `nextLoad`', async () => {
|
||||
const { code, stderr } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-bad-next-url.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify error thrown when invalid `url` argument passed to `nextLoad`
|
||||
const { status, stderr } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-bad-next-url.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.match(stderr, /ERR_INVALID_ARG_TYPE/);
|
||||
assert.match(stderr, /loader-load-bad-next-url\.mjs/);
|
||||
assert.match(stderr, /'load' hook's nextLoad\(\) url/);
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
assert.match(stderr, /ERR_INVALID_ARG_TYPE/);
|
||||
assert.match(stderr, /loader-load-bad-next-url\.mjs/);
|
||||
assert.match(stderr, /'load' hook's nextLoad\(\) url/);
|
||||
assert.strictEqual(status, 1);
|
||||
}
|
||||
it('should throw when invalid `url` argument passed to `nextLoad`', async () => {
|
||||
const { code, stderr } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-impersonating-next-url.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
{ // Verify error thrown when invalid `url` argument passed to `nextLoad`
|
||||
const { status, stderr } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-impersonating-next-url.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.match(stderr, /ERR_INVALID_ARG_VALUE/);
|
||||
assert.match(stderr, /loader-load-impersonating-next-url\.mjs/);
|
||||
assert.match(stderr, /'load' hook's nextLoad\(\) url/);
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
assert.match(stderr, /ERR_INVALID_ARG_VALUE/);
|
||||
assert.match(stderr, /loader-load-impersonating-next-url\.mjs/);
|
||||
assert.match(stderr, /'load' hook's nextLoad\(\) url/);
|
||||
assert.strictEqual(status, 1);
|
||||
}
|
||||
|
||||
{ // Verify error thrown when invalid `context` argument passed to `nextLoad`
|
||||
const { status, stderr } = spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-bad-next-context.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
|
||||
assert.match(stderr, /ERR_INVALID_ARG_TYPE/);
|
||||
assert.match(stderr, /loader-load-bad-next-context\.mjs/);
|
||||
assert.match(stderr, /'load' hook's nextLoad\(\) context/);
|
||||
assert.strictEqual(status, 1);
|
||||
}
|
||||
it('should throw when invalid `context` argument passed to `nextLoad`', async () => {
|
||||
const { code, stderr } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'),
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'loader-load-bad-next-context.mjs'),
|
||||
...commonArgs,
|
||||
],
|
||||
{ encoding: 'utf8' },
|
||||
);
|
||||
assert.match(stderr, /ERR_INVALID_ARG_TYPE/);
|
||||
assert.match(stderr, /loader-load-bad-next-context\.mjs/);
|
||||
assert.match(stderr, /'load' hook's nextLoad\(\) context/);
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import fixtures from '../common/fixtures.js';
|
||||
import { strictEqual } from 'node:assert';
|
||||
import { spawn } from 'node:child_process';
|
||||
import assert from 'node:assert';
|
||||
import http from 'node:http';
|
||||
import path from 'node:path';
|
||||
import { execPath } from 'node:process';
|
||||
import { promisify } from 'node:util';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
|
||||
const files = {
|
||||
|
@ -40,33 +41,31 @@ const {
|
|||
port,
|
||||
} = server.address();
|
||||
|
||||
{ // Verify nested HTTP imports work
|
||||
const child = spawn( // ! `spawn` MUST be used (vs `spawnSync`) to avoid blocking the event loop
|
||||
process.execPath,
|
||||
[
|
||||
'--no-warnings',
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'http-loader.mjs'),
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
`import * as main from 'http://${host}:${port}/main.mjs'; console.log(main)`,
|
||||
]
|
||||
);
|
||||
/**
|
||||
* ! If more cases are added to this test, they cannot (yet) be concurrent because there is no
|
||||
* ! `afterAll` teardown in which to close the server.
|
||||
*/
|
||||
|
||||
let stderr = '';
|
||||
let stdout = '';
|
||||
describe('ESM: http import via loader', { concurrency: false }, () => {
|
||||
it('should work', async () => {
|
||||
// ! MUST NOT use spawnSync to avoid blocking the event loop
|
||||
const { code, signal, stderr, stdout } = await spawnPromisified(
|
||||
execPath,
|
||||
[
|
||||
'--no-warnings',
|
||||
'--loader',
|
||||
fixtures.fileURL('es-module-loaders', 'http-loader.mjs'),
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
`import * as main from 'http://${host}:${port}/main.mjs'; console.log(main)`,
|
||||
]
|
||||
);
|
||||
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => stderr += data);
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', (data) => stdout += data);
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(stdout, '[Module: null prototype] { sum: [Function: sum] }\n');
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(signal, null);
|
||||
|
||||
child.on('close', mustCall((code, signal) => {
|
||||
strictEqual(stderr, '');
|
||||
strictEqual(stdout, '[Module: null prototype] { sum: [Function: sum] }\n');
|
||||
strictEqual(code, 0);
|
||||
strictEqual(signal, null);
|
||||
|
||||
server.close();
|
||||
}));
|
||||
}
|
||||
server.close(); // ! This MUST come after the final test, but inside the async `it` function
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,27 +1,24 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { path } from '../common/fixtures.mjs';
|
||||
import { match, ok, notStrictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import assert from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
const child = spawn(execPath, [
|
||||
'--experimental-loader',
|
||||
'i-dont-exist',
|
||||
path('print-error-message.js'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
describe('ESM: nonexistent loader', () => {
|
||||
it('should throw', async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
'--experimental-loader',
|
||||
'i-dont-exist',
|
||||
fixtures.path('print-error-message.js'),
|
||||
]);
|
||||
|
||||
assert.notStrictEqual(code, 0);
|
||||
|
||||
// Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'i-dont-exist' imported from
|
||||
assert.match(stderr, /ERR_MODULE_NOT_FOUND/);
|
||||
assert.match(stderr, /'i-dont-exist'/);
|
||||
|
||||
assert.ok(!stderr.includes('Bad command or file name'));
|
||||
});
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
|
||||
// Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'i-dont-exist'
|
||||
// imported from
|
||||
match(stderr, /ERR_MODULE_NOT_FOUND/);
|
||||
match(stderr, /'i-dont-exist'/);
|
||||
|
||||
ok(!stderr.includes('Bad command or file name'));
|
||||
}));
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import { fileURL, path } from '../common/fixtures.mjs';
|
||||
import { match, notStrictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { match, notStrictEqual } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
const child = spawn(execPath, [
|
||||
'--no-warnings',
|
||||
'--throw-deprecation',
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'hooks-obsolete.mjs').href,
|
||||
path('print-error-message.js'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
describe('ESM: deprecation warnings for obsolete hooks', { concurrency: true }, () => {
|
||||
it(async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
'--throw-deprecation',
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'hooks-obsolete.mjs').href,
|
||||
path('print-error-message.js'),
|
||||
]);
|
||||
|
||||
// DeprecationWarning: Obsolete loader hook(s) supplied and will be ignored:
|
||||
// dynamicInstantiate, getFormat, getSource, transformSource
|
||||
match(stderr, /DeprecationWarning:/);
|
||||
match(stderr, /dynamicInstantiate/);
|
||||
match(stderr, /getFormat/);
|
||||
match(stderr, /getSource/);
|
||||
match(stderr, /transformSource/);
|
||||
|
||||
notStrictEqual(code, 0);
|
||||
});
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
|
||||
// DeprecationWarning: Obsolete loader hook(s) supplied and will be ignored:
|
||||
// dynamicInstantiate, getFormat, getSource, transformSource
|
||||
match(stderr, /DeprecationWarning:/);
|
||||
match(stderr, /dynamicInstantiate/);
|
||||
match(stderr, /getFormat/);
|
||||
match(stderr, /getSource/);
|
||||
match(stderr, /transformSource/);
|
||||
}));
|
||||
|
|
|
@ -1,65 +1,43 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import { fileURL, path } from '../common/fixtures.mjs';
|
||||
import { match, ok, notStrictEqual, strictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
{
|
||||
const child = spawn(execPath, [
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'thenable-load-hook.mjs').href,
|
||||
path('es-modules', 'test-esm-ok.mjs'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
describe('ESM: thenable loader hooks', { concurrency: true }, () => {
|
||||
it('should behave as a normal promise resolution', async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'thenable-load-hook.mjs').href,
|
||||
path('es-modules', 'test-esm-ok.mjs'),
|
||||
]);
|
||||
|
||||
strictEqual(code, 0);
|
||||
ok(!stderr.includes('must not call'));
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
const child = spawn(execPath, [
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'thenable-load-hook-rejected.mjs').href,
|
||||
path('es-modules', 'test-esm-ok.mjs'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
|
||||
it('should crash the node process rejection with an error', async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'thenable-load-hook-rejected.mjs').href,
|
||||
path('es-modules', 'test-esm-ok.mjs'),
|
||||
]);
|
||||
|
||||
notStrictEqual(code, 0);
|
||||
match(stderr, /\sError: must crash the process\r?\n/);
|
||||
|
||||
ok(!stderr.includes('must not call'));
|
||||
}));
|
||||
}
|
||||
|
||||
{
|
||||
const child = spawn(execPath, [
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'thenable-load-hook-rejected-no-arguments.mjs').href,
|
||||
path('es-modules', 'test-esm-ok.mjs'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
|
||||
it('should just reject without an error (but NOT crash the node process)', async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'thenable-load-hook-rejected-no-arguments.mjs').href,
|
||||
path('es-modules', 'test-esm-ok.mjs'),
|
||||
]);
|
||||
|
||||
notStrictEqual(code, 0);
|
||||
|
||||
match(stderr, /\sundefined\r?\n/);
|
||||
|
||||
ok(!stderr.includes('must not call'));
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,24 +1,20 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import { fileURL, path } from '../common/fixtures.mjs';
|
||||
import { match, ok, notStrictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { match, ok, notStrictEqual } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
const child = spawn(execPath, [
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'syntax-error.mjs').href,
|
||||
path('print-error-message.js'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
describe('ESM: loader with syntax error', { concurrency: true }, () => {
|
||||
it('should crash the node process', async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
'--experimental-loader',
|
||||
fileURL('es-module-loaders', 'syntax-error.mjs').href,
|
||||
path('print-error-message.js'),
|
||||
]);
|
||||
|
||||
match(stderr, /SyntaxError:/);
|
||||
ok(!stderr.includes('Bad command or file name'));
|
||||
notStrictEqual(code, 0);
|
||||
});
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
|
||||
match(stderr, /SyntaxError:/);
|
||||
|
||||
ok(!stderr.includes('Bad command or file name'));
|
||||
}));
|
||||
|
|
|
@ -1,35 +1,34 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import { fixturesDir } from '../common/fixtures.mjs';
|
||||
import { match, notStrictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { match, notStrictEqual } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
[
|
||||
{
|
||||
input: 'import "./print-error-message"',
|
||||
// Did you mean to import ../print-error-message.js?
|
||||
expected: / \.\.\/print-error-message\.js\?/,
|
||||
},
|
||||
{
|
||||
input: 'import obj from "some_module/obj"',
|
||||
expected: / some_module\/obj\.js\?/,
|
||||
},
|
||||
].forEach(({ input, expected }) => {
|
||||
const child = spawn(execPath, [
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
input,
|
||||
], {
|
||||
cwd: fixturesDir,
|
||||
});
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
describe('ESM: module not found hint', { concurrency: true }, () => {
|
||||
for (
|
||||
const { input, expected }
|
||||
of [
|
||||
{
|
||||
input: 'import "./print-error-message"',
|
||||
// Did you mean to import ../print-error-message.js?
|
||||
expected: / \.\.\/print-error-message\.js\?/,
|
||||
},
|
||||
{
|
||||
input: 'import obj from "some_module/obj"',
|
||||
expected: / some_module\/obj\.js\?/,
|
||||
},
|
||||
]
|
||||
) it('should cite a variant form', async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
input,
|
||||
], {
|
||||
cwd: fixturesDir,
|
||||
});
|
||||
|
||||
match(stderr, expected);
|
||||
}));
|
||||
notStrictEqual(code, 0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,23 +1,20 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import { fileURL } from '../common/fixtures.mjs';
|
||||
import { match, strictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { match, strictEqual } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
// Verify non-js extensions fail for ESM
|
||||
const child = spawn(execPath, [
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
`import ${JSON.stringify(fileURL('es-modules', 'file.unknown'))}`,
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
describe('ESM: non-js extensions fail', { concurrency: true }, () => {
|
||||
it(async () => {
|
||||
const { code, stderr, signal } = await spawnPromisified(execPath, [
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
`import ${JSON.stringify(fileURL('es-modules', 'file.unknown'))}`,
|
||||
]);
|
||||
|
||||
match(stderr, /ERR_UNKNOWN_FILE_EXTENSION/);
|
||||
strictEqual(code, 1);
|
||||
strictEqual(signal, null);
|
||||
});
|
||||
});
|
||||
child.on('close', mustCall((code, signal) => {
|
||||
strictEqual(code, 1);
|
||||
strictEqual(signal, null);
|
||||
match(stderr, /ERR_UNKNOWN_FILE_EXTENSION/);
|
||||
}));
|
||||
|
|
|
@ -1,25 +1,19 @@
|
|||
import '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import { path } from '../common/fixtures.mjs';
|
||||
import { strictEqual, ok } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { strictEqual } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
const child = spawn(process.execPath, [
|
||||
'--experimental-import-meta-resolve',
|
||||
path('/es-modules/import-resolve-exports.mjs'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', (code, signal) => {
|
||||
strictEqual(code, 0);
|
||||
strictEqual(signal, null);
|
||||
ok(!stderr.toString().includes(
|
||||
'ExperimentalWarning: The ESM module loader is experimental'
|
||||
));
|
||||
ok(!stderr.toString().includes(
|
||||
'ExperimentalWarning: Conditional exports'
|
||||
));
|
||||
describe('ESM: experiemental warning for import.meta.resolve', { concurrency: true }, () => {
|
||||
it('should not warn when caught', async () => {
|
||||
const { code, signal, stderr } = await spawnPromisified(execPath, [
|
||||
'--experimental-import-meta-resolve',
|
||||
path('es-modules/import-resolve-exports.mjs'),
|
||||
]);
|
||||
|
||||
strictEqual(stderr, '');
|
||||
strictEqual(code, 0);
|
||||
strictEqual(signal, null);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -39,15 +39,15 @@ function doTest(flags, done) {
|
|||
// dictates that it'll resolve relative imports in the main file relative to
|
||||
// the symlink, and not relative to the symlink target; the file structure set
|
||||
// up above requires this to not crash when loading ./submodule_link.js
|
||||
spawn(process.execPath,
|
||||
flags.concat([
|
||||
'--preserve-symlinks',
|
||||
'--preserve-symlinks-main', entry_link_absolute_path,
|
||||
]),
|
||||
{ stdio: 'inherit' }).on('exit', (code) => {
|
||||
assert.strictEqual(code, 0);
|
||||
done();
|
||||
});
|
||||
spawn(process.execPath, [
|
||||
'--preserve-symlinks',
|
||||
'--preserve-symlinks-main',
|
||||
entry_link_absolute_path,
|
||||
], { stdio: 'inherit' })
|
||||
.on('exit', (code) => {
|
||||
assert.strictEqual(code, 0);
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
// First test the commonjs module loader
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
'use strict';
|
||||
|
||||
const { mustCall } = require('../common');
|
||||
const assert = require('assert');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { spawn } = require('child_process');
|
||||
const assert = require('node:assert');
|
||||
const { spawn } = require('node:child_process');
|
||||
const { execPath } = require('node:process');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
const child = spawn(process.execPath, [
|
||||
'--interactive',
|
||||
], {
|
||||
cwd: fixtures.path('es-modules', 'pkgimports'),
|
||||
|
||||
describe('ESM: REPL runs', { concurrency: true }, () => {
|
||||
it((context, done) => {
|
||||
const child = spawn(execPath, [
|
||||
'--interactive',
|
||||
], {
|
||||
cwd: fixtures.path('es-modules', 'pkgimports'),
|
||||
});
|
||||
|
||||
child.stdin.end(
|
||||
'try{require("#test");await import("#test")}catch{process.exit(-1)}'
|
||||
);
|
||||
|
||||
child.on('exit', mustCall((code) => {
|
||||
assert.strictEqual(code, 0);
|
||||
done();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
child.stdin.end(
|
||||
'try{require("#test");await import("#test")}catch{process.exit(-1)}'
|
||||
);
|
||||
|
||||
child.on('exit', mustCall((code) => {
|
||||
assert.strictEqual(code, 0);
|
||||
}));
|
||||
|
|
|
@ -1,62 +1,79 @@
|
|||
// Flags: --experimental-specifier-resolution=node
|
||||
import { mustNotCall } from '../common/index.mjs';
|
||||
import assert from 'assert';
|
||||
import path from 'path';
|
||||
import { spawn } from 'child_process';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import { match, strictEqual } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
// commonJS index.js
|
||||
import commonjs from '../fixtures/es-module-specifiers/package-type-commonjs';
|
||||
// esm index.js
|
||||
import module from '../fixtures/es-module-specifiers/package-type-module';
|
||||
// Notice the trailing slash
|
||||
import success, { explicit, implicit, implicitModule, getImplicitCommonjs }
|
||||
from '../fixtures/es-module-specifiers/';
|
||||
|
||||
assert.strictEqual(commonjs, 'commonjs');
|
||||
assert.strictEqual(module, 'module');
|
||||
assert.strictEqual(success, 'success');
|
||||
assert.strictEqual(explicit, 'esm');
|
||||
assert.strictEqual(implicit, 'cjs');
|
||||
assert.strictEqual(implicitModule, 'cjs');
|
||||
describe('ESM: specifier-resolution=node', { concurrency: true }, () => {
|
||||
it(async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
'--experimental-specifier-resolution=node',
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
[
|
||||
'import { strictEqual } from "node:assert";',
|
||||
// commonJS index.js
|
||||
`import commonjs from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-commonjs'))};`,
|
||||
// esm index.js
|
||||
`import module from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-module'))};`,
|
||||
// Notice the trailing slash
|
||||
`import success, { explicit, implicit, implicitModule } from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/'))};`,
|
||||
'strictEqual(commonjs, "commonjs");',
|
||||
'strictEqual(module, "module");',
|
||||
'strictEqual(success, "success");',
|
||||
'strictEqual(explicit, "esm");',
|
||||
'strictEqual(implicit, "cjs");',
|
||||
'strictEqual(implicitModule, "cjs");',
|
||||
].join('\n'),
|
||||
]);
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
await import('../fixtures/es-module-specifiers/do-not-exist.js');
|
||||
} catch (e) {
|
||||
// Files that do not exist should throw
|
||||
assert.strictEqual(e.name, 'Error');
|
||||
}
|
||||
try {
|
||||
await getImplicitCommonjs();
|
||||
} catch (e) {
|
||||
// Legacy loader cannot resolve .mjs automatically from main
|
||||
assert.strictEqual(e.name, 'Error');
|
||||
}
|
||||
}
|
||||
strictEqual(stderr, '');
|
||||
strictEqual(stdout, '');
|
||||
strictEqual(code, 0);
|
||||
});
|
||||
|
||||
main().catch(mustNotCall);
|
||||
it('should throw when the file doesn\'t exist', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
fixtures.path('es-module-specifiers/do-not-exist.js'),
|
||||
]);
|
||||
|
||||
// Test path from command line arguments
|
||||
[
|
||||
'package-type-commonjs',
|
||||
'package-type-module',
|
||||
'/',
|
||||
'/index',
|
||||
].forEach((item) => {
|
||||
const modulePath = path.join(
|
||||
fileURLToPath(import.meta.url),
|
||||
'../../fixtures/es-module-specifiers',
|
||||
item,
|
||||
);
|
||||
[
|
||||
'--experimental-specifier-resolution',
|
||||
'--es-module-specifier-resolution',
|
||||
].forEach((option) => {
|
||||
spawn(process.execPath,
|
||||
[`${option}=node`, modulePath],
|
||||
{ stdio: 'inherit' }).on('exit', (code) => {
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
match(stderr, /Cannot find module/);
|
||||
strictEqual(stdout, '');
|
||||
strictEqual(code, 1);
|
||||
});
|
||||
|
||||
it('should throw when the omitted file extension is .mjs (legacy loader doesn\'t support it)', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
'--experimental-specifier-resolution=node',
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
`import whatever from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/implicit-main-type-commonjs'))};`,
|
||||
]);
|
||||
|
||||
match(stderr, /ERR_MODULE_NOT_FOUND/);
|
||||
strictEqual(stdout, '');
|
||||
strictEqual(code, 1);
|
||||
});
|
||||
|
||||
for (
|
||||
const item of [
|
||||
'package-type-commonjs',
|
||||
'package-type-module',
|
||||
'/',
|
||||
'/index',
|
||||
]
|
||||
) it('should ', async () => {
|
||||
const { code } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
'--experimental-specifier-resolution=node',
|
||||
'--es-module-specifier-resolution=node',
|
||||
fixtures.path('es-module-specifiers', item),
|
||||
]);
|
||||
|
||||
strictEqual(code, 0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import { path } from '../common/fixtures.mjs';
|
||||
import { match, notStrictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { match, notStrictEqual } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
const child = spawn(execPath, [
|
||||
path('es-module-loaders', 'syntax-error.mjs'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
describe('ESM: importing a module with syntax error(s)', { concurrency: true }, () => {
|
||||
it('should throw', async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
path('es-module-loaders', 'syntax-error.mjs'),
|
||||
]);
|
||||
match(stderr, /SyntaxError:/);
|
||||
notStrictEqual(code, 0);
|
||||
});
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
match(stderr, /SyntaxError:/);
|
||||
}));
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import '../common/index.mjs';
|
||||
import assert from 'assert';
|
||||
import child_process from 'child_process';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import fixtures from '../common/fixtures.js';
|
||||
import assert from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
|
||||
const commonArgs = [
|
||||
'--no-warnings',
|
||||
|
@ -9,102 +11,117 @@ const commonArgs = [
|
|||
'--eval',
|
||||
];
|
||||
|
||||
{
|
||||
// Unresolved TLA promise, --eval
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
[...commonArgs, 'await new Promise(() => {})'],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout, stderr], [13, '', '']);
|
||||
}
|
||||
describe('ESM: unsettled and rejected promises', { concurrency: true }, () => {
|
||||
it('should exit for an unsettled TLA promise via --eval', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
...commonArgs,
|
||||
'await new Promise(() => {})',
|
||||
]);
|
||||
|
||||
{
|
||||
// Rejected TLA promise, --eval
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
[...commonArgs, 'await Promise.reject(new Error("Xyz"))'],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout], [1, '']);
|
||||
assert.match(stderr, /Error: Xyz/);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 13);
|
||||
});
|
||||
|
||||
{
|
||||
// Unresolved TLA promise with explicit exit code, --eval
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
it('should throw for a rejected TLA promise via --eval', async () => {
|
||||
// Rejected TLA promise, --eval
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
...commonArgs,
|
||||
'await Promise.reject(new Error("Xyz"))',
|
||||
]);
|
||||
|
||||
assert.match(stderr, /Error: Xyz/);
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
it('should exit for an unsettled TLA promise and respect explicit exit code via --eval', async () => {
|
||||
// Rejected TLA promise, --eval
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
...commonArgs,
|
||||
'process.exitCode = 42;await new Promise(() => {})',
|
||||
],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout, stderr], [42, '', '']);
|
||||
}
|
||||
]);
|
||||
|
||||
{
|
||||
// Rejected TLA promise with explicit exit code, --eval
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
[
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 42);
|
||||
});
|
||||
|
||||
it('should throw for a rejected TLA promise and ignore explicit exit code via --eval', async () => {
|
||||
// Rejected TLA promise, --eval
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
...commonArgs,
|
||||
'process.exitCode = 42;await Promise.reject(new Error("Xyz"))',
|
||||
],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout], [1, '']);
|
||||
assert.match(stderr, /Error: Xyz/);
|
||||
}
|
||||
]);
|
||||
|
||||
{
|
||||
// Unresolved TLA promise, module file
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
['--no-warnings', fixtures.path('es-modules/tla/unresolved.mjs')],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout, stderr], [13, '', '']);
|
||||
}
|
||||
assert.match(stderr, /Error: Xyz/);
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
{
|
||||
// Rejected TLA promise, module file
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
['--no-warnings', fixtures.path('es-modules/tla/rejected.mjs')],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout], [1, '']);
|
||||
assert.match(stderr, /Error: Xyz/);
|
||||
}
|
||||
it('should exit for an unsettled TLA promise via stdin', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
fixtures.path('es-modules/tla/unresolved.mjs'),
|
||||
]);
|
||||
|
||||
{
|
||||
// Unresolved TLA promise, module file
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
['--no-warnings', fixtures.path('es-modules/tla/unresolved-withexitcode.mjs')],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout, stderr], [42, '', '']);
|
||||
}
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 13);
|
||||
});
|
||||
|
||||
{
|
||||
// Rejected TLA promise, module file
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
['--no-warnings', fixtures.path('es-modules/tla/rejected-withexitcode.mjs')],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout], [1, '']);
|
||||
assert.match(stderr, /Error: Xyz/);
|
||||
}
|
||||
it('should throw for a rejected TLA promise via stdin', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
fixtures.path('es-modules/tla/rejected.mjs'),
|
||||
]);
|
||||
|
||||
{
|
||||
// Calling process.exit() in .mjs should return status 0
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
['--no-warnings', fixtures.path('es-modules/tla/process-exit.mjs')],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout, stderr], [0, '', '']);
|
||||
}
|
||||
assert.match(stderr, /Error: Xyz/);
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
{
|
||||
// Calling process.exit() in worker thread shouldn't influence main thread
|
||||
const { status, stdout, stderr } = child_process.spawnSync(
|
||||
process.execPath,
|
||||
['--no-warnings', fixtures.path('es-modules/tla/unresolved-with-worker-process-exit.mjs')],
|
||||
{ encoding: 'utf8' });
|
||||
assert.deepStrictEqual([status, stdout, stderr], [13, '', '']);
|
||||
}
|
||||
it('should exit for an unsettled TLA promise and respect explicit exit code via stdin', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
fixtures.path('es-modules/tla/unresolved-withexitcode.mjs'),
|
||||
]);
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 42);
|
||||
});
|
||||
|
||||
it('should throw for a rejected TLA promise and ignore explicit exit code via stdin', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
fixtures.path('es-modules/tla/rejected-withexitcode.mjs'),
|
||||
]);
|
||||
|
||||
assert.match(stderr, /Error: Xyz/);
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 1);
|
||||
});
|
||||
|
||||
it('should exit successfully when calling `process.exit()` in `.mjs` file', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
fixtures.path('es-modules/tla/process-exit.mjs'),
|
||||
]);
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 0);
|
||||
});
|
||||
|
||||
it('should be unaffected by `process.exit()` in worker thread', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
fixtures.path('es-modules/tla/unresolved-with-worker-process-exit.mjs'),
|
||||
]);
|
||||
|
||||
assert.strictEqual(stderr, '');
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.strictEqual(code, 13);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,40 +1,36 @@
|
|||
'use strict';
|
||||
|
||||
const common = require('../common');
|
||||
const fixtures = require('../common/fixtures');
|
||||
const { spawn } = require('child_process');
|
||||
const assert = require('assert');
|
||||
const { spawnPromisified } = require('../common');
|
||||
const fixtures = require('../common/fixtures.js');
|
||||
const assert = require('node:assert');
|
||||
const { execPath } = require('node:process');
|
||||
const { describe, it } = require('node:test');
|
||||
|
||||
|
||||
// In a "type": "module" package scope, files with unknown extensions or no
|
||||
// extensions should throw; both when used as a main entry point and also when
|
||||
// referenced via `import`.
|
||||
describe('ESM: extensionless and unknown specifiers', { concurrency: true }, () => {
|
||||
for (
|
||||
const fixturePath of [
|
||||
'/es-modules/package-type-module/noext-esm',
|
||||
'/es-modules/package-type-module/imports-noext.mjs',
|
||||
'/es-modules/package-type-module/extension.unknown',
|
||||
'/es-modules/package-type-module/imports-unknownext.mjs',
|
||||
]
|
||||
) {
|
||||
it('should throw', async () => {
|
||||
const entry = fixtures.path(fixturePath);
|
||||
const { code, signal, stderr, stdout } = await spawnPromisified(execPath, [entry]);
|
||||
|
||||
[
|
||||
'/es-modules/package-type-module/noext-esm',
|
||||
'/es-modules/package-type-module/imports-noext.mjs',
|
||||
'/es-modules/package-type-module/extension.unknown',
|
||||
'/es-modules/package-type-module/imports-unknownext.mjs',
|
||||
].forEach((fixturePath) => {
|
||||
const entry = fixtures.path(fixturePath);
|
||||
const child = spawn(process.execPath, [entry]);
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stdout.setEncoding('utf8');
|
||||
child.stdout.on('data', (data) => {
|
||||
stdout += data;
|
||||
});
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', common.mustCall((code, signal) => {
|
||||
assert.strictEqual(code, 1);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.ok(stderr.includes('ERR_UNKNOWN_FILE_EXTENSION'));
|
||||
if (fixturePath.includes('noext')) {
|
||||
// Check for explanation to users
|
||||
assert.ok(stderr.includes('extensionless'));
|
||||
}
|
||||
}));
|
||||
assert.strictEqual(code, 1);
|
||||
assert.strictEqual(signal, null);
|
||||
assert.strictEqual(stdout, '');
|
||||
assert.ok(stderr.includes('ERR_UNKNOWN_FILE_EXTENSION'));
|
||||
if (fixturePath.includes('noext')) {
|
||||
// Check for explanation to users
|
||||
assert.ok(stderr.includes('extensionless'));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,37 +1,43 @@
|
|||
// Flags: --experimental-wasm-modules
|
||||
import '../common/index.mjs';
|
||||
import { path } from '../common/fixtures.mjs';
|
||||
import { add, addImported } from '../fixtures/es-modules/simple.wasm';
|
||||
import { state } from '../fixtures/es-modules/wasm-dep.mjs';
|
||||
import { strictEqual, ok } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { spawnPromisified } from '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import { strictEqual, match } from 'node:assert';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
strictEqual(state, 'WASM Start Executed');
|
||||
|
||||
strictEqual(add(10, 20), 30);
|
||||
describe('ESM: WASM modules', { concurrency: true }, () => {
|
||||
it('should load exports', async () => {
|
||||
const { code, stderr, stdout } = await spawnPromisified(execPath, [
|
||||
'--no-warnings',
|
||||
'--experimental-wasm-modules',
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
[
|
||||
'import { strictEqual, match } from "node:assert";',
|
||||
`import { add, addImported } from ${JSON.stringify(fixtures.fileURL('es-modules/simple.wasm'))};`,
|
||||
`import { state } from ${JSON.stringify(fixtures.fileURL('es-modules/wasm-dep.mjs'))};`,
|
||||
'strictEqual(state, "WASM Start Executed");',
|
||||
'strictEqual(add(10, 20), 30);',
|
||||
'strictEqual(addImported(0), 42);',
|
||||
'strictEqual(state, "WASM JS Function Executed");',
|
||||
'strictEqual(addImported(1), 43);',
|
||||
].join('\n'),
|
||||
]);
|
||||
|
||||
strictEqual(addImported(0), 42);
|
||||
strictEqual(stderr, '');
|
||||
strictEqual(stdout, '');
|
||||
strictEqual(code, 0);
|
||||
});
|
||||
|
||||
strictEqual(state, 'WASM JS Function Executed');
|
||||
it('should emit experimental warning', async () => {
|
||||
const { code, signal, stderr } = await spawnPromisified(execPath, [
|
||||
'--experimental-wasm-modules',
|
||||
fixtures.path('es-modules/wasm-modules.mjs'),
|
||||
]);
|
||||
|
||||
strictEqual(addImported(1), 43);
|
||||
|
||||
// Test warning message
|
||||
const child = spawn(process.execPath, [
|
||||
'--experimental-wasm-modules',
|
||||
path('/es-modules/wasm-modules.mjs'),
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', (code, signal) => {
|
||||
strictEqual(code, 0);
|
||||
strictEqual(signal, null);
|
||||
ok(stderr.toString().includes(
|
||||
'ExperimentalWarning: Importing WebAssembly modules is ' +
|
||||
'an experimental feature. This feature could change at any time'
|
||||
));
|
||||
strictEqual(code, 0);
|
||||
strictEqual(signal, null);
|
||||
match(stderr, /ExperimentalWarning/);
|
||||
match(stderr, /WebAssembly/);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
import { mustCall } from '../common/index.mjs';
|
||||
import { match, notStrictEqual } from 'assert';
|
||||
import { spawn } from 'child_process';
|
||||
import { execPath } from 'process';
|
||||
import { mustCall, spawnPromisified } from '../common/index.mjs';
|
||||
import { ok, match, notStrictEqual } from 'node:assert';
|
||||
import { spawn as spawnAsync } from 'node:child_process';
|
||||
import { execPath } from 'node:process';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
{
|
||||
const child = spawn(execPath, [
|
||||
'--experimental-network-imports',
|
||||
'--input-type=module',
|
||||
'-e',
|
||||
'import "http://example.com"',
|
||||
]);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
describe('ESM: http import via CLI', { concurrency: true }, () => {
|
||||
const disallowedSpecifier = 'http://example.com';
|
||||
|
||||
it('should throw disallowed error for insecure protocol', async () => {
|
||||
const { code, stderr } = await spawnPromisified(execPath, [
|
||||
'--experimental-network-imports',
|
||||
'--input-type=module',
|
||||
'--eval',
|
||||
`import ${JSON.stringify(disallowedSpecifier)}`,
|
||||
]);
|
||||
|
||||
notStrictEqual(code, 0);
|
||||
|
||||
// [ERR_NETWORK_IMPORT_DISALLOWED]: import of 'http://example.com/' by
|
||||
// …/[eval1] is not supported: http can only be used to load local
|
||||
// resources (use https instead).
|
||||
match(stderr, /[ERR_NETWORK_IMPORT_DISALLOWED]/);
|
||||
}));
|
||||
}
|
||||
{
|
||||
const child = spawn(execPath, [
|
||||
'--experimental-network-imports',
|
||||
'--input-type=module',
|
||||
]);
|
||||
child.stdin.end('import "http://example.com"');
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => {
|
||||
stderr += data;
|
||||
match(stderr, /ERR_NETWORK_IMPORT_DISALLOWED/);
|
||||
ok(stderr.includes(disallowedSpecifier));
|
||||
});
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
|
||||
// [ERR_NETWORK_IMPORT_DISALLOWED]: import of 'http://example.com/' by
|
||||
// …/[stdin] is not supported: http can only be used to load local
|
||||
// resources (use https instead).
|
||||
match(stderr, /[ERR_NETWORK_IMPORT_DISALLOWED]/);
|
||||
}));
|
||||
}
|
||||
it('should throw disallowed error for insecure protocol in REPL', () => {
|
||||
const child = spawnAsync(execPath, [
|
||||
'--experimental-network-imports',
|
||||
'--input-type=module',
|
||||
]);
|
||||
child.stdin.end(`import ${JSON.stringify(disallowedSpecifier)}`);
|
||||
|
||||
let stderr = '';
|
||||
child.stderr.setEncoding('utf8');
|
||||
child.stderr.on('data', (data) => stderr += data);
|
||||
child.on('close', mustCall((code, _signal) => {
|
||||
notStrictEqual(code, 0);
|
||||
|
||||
// [ERR_NETWORK_IMPORT_DISALLOWED]: import of 'http://example.com/' by
|
||||
// …/[stdin] is not supported: http can only be used to load local
|
||||
// resources (use https instead).
|
||||
match(stderr, /\[ERR_NETWORK_IMPORT_DISALLOWED\]/);
|
||||
ok(stderr.includes(disallowedSpecifier));
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,14 +4,14 @@ const JSON_URL_PATTERN = /\.json(\?[^#]*)?(#.*)?$/;
|
|||
export function resolve(url, context, next) {
|
||||
// Mutation from resolve hook should be discarded.
|
||||
context.importAssertions.type = 'whatever';
|
||||
return next(url, context);
|
||||
return next(url);
|
||||
}
|
||||
|
||||
export function load(url, context, next) {
|
||||
if (context.importAssertions.type == null &&
|
||||
if (context.importAssertions.type == null &&
|
||||
(DATA_URL_PATTERN.test(url) || JSON_URL_PATTERN.test(url))) {
|
||||
const { importAssertions } = context;
|
||||
importAssertions.type = 'json';
|
||||
}
|
||||
return next(url, context);
|
||||
return next(url);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ export function load(url, context, next) {
|
|||
format: 'module',
|
||||
};
|
||||
}
|
||||
return next(url, context);
|
||||
return next(url);
|
||||
}
|
||||
|
||||
function generateBuiltinModule(builtinName) {
|
||||
|
|
|
@ -8,7 +8,7 @@ const JS_EXTENSIONS = new Set(['.js', '.mjs']);
|
|||
const baseURL = new URL('file://');
|
||||
baseURL.pathname = process.cwd() + '/';
|
||||
|
||||
export function resolve(specifier, { parentURL = baseURL }, defaultResolve) {
|
||||
export function resolve(specifier, { parentURL = baseURL }, next) {
|
||||
if (builtinModules.includes(specifier)) {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
|
@ -17,7 +17,7 @@ export function resolve(specifier, { parentURL = baseURL }, defaultResolve) {
|
|||
}
|
||||
if (/^\.{1,2}[/]/.test(specifier) !== true && !specifier.startsWith('file:')) {
|
||||
// For node_modules support:
|
||||
// return defaultResolve(specifier, {parentURL}, defaultResolve);
|
||||
// return next(specifier);
|
||||
throw new Error(
|
||||
`imports must be URLs or begin with './', or '../'; '${specifier}' does not`);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ let importedCJS = 0;
|
|||
global.getModuleTypeStats = () => { return {importedESM, importedCJS} };
|
||||
|
||||
export async function load(url, context, next) {
|
||||
return next(url, context, next);
|
||||
return next(url);
|
||||
}
|
||||
|
||||
export async function resolve(specifier, context, next) {
|
||||
|
|
|
@ -56,10 +56,10 @@ export function load(url, context, next) {
|
|||
source: `export const message = 'Woohoo!'.toUpperCase();`,
|
||||
};
|
||||
|
||||
return next(url, context, next);
|
||||
return next(url);
|
||||
}
|
||||
|
||||
export function resolve(specifier, context, next) {
|
||||
export function resolve(specifier, { importAssertions }, next) {
|
||||
let format = '';
|
||||
|
||||
if (specifier === 'esmHook/format.false') format = false;
|
||||
|
@ -70,8 +70,8 @@ export function resolve(specifier, context, next) {
|
|||
format,
|
||||
shortCircuit: true,
|
||||
url: pathToFileURL(specifier).href,
|
||||
importAssertions: context.importAssertions,
|
||||
importAssertions,
|
||||
};
|
||||
|
||||
return next(specifier, context, next);
|
||||
return next(specifier);
|
||||
}
|
||||
|
|
|
@ -4,19 +4,19 @@ export function getSource() {}
|
|||
export function transformSource() {}
|
||||
|
||||
|
||||
export function resolve(specifier, context, next) {
|
||||
if (specifier === 'whatever') return {
|
||||
url: specifier,
|
||||
};
|
||||
|
||||
return next(specifier);
|
||||
}
|
||||
|
||||
export function load(url, context, next) {
|
||||
if (url === 'whatever') return {
|
||||
format: 'module',
|
||||
source: '',
|
||||
};
|
||||
|
||||
return next(url, context, next);
|
||||
}
|
||||
|
||||
export function resolve(specifier, context, next) {
|
||||
if (specifier === 'whatever') return {
|
||||
url: specifier,
|
||||
};
|
||||
|
||||
return next(specifier, context, next);
|
||||
return next(url);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export function resolve(specifier, context, nextResolve) {
|
|||
};
|
||||
}
|
||||
|
||||
return nextResolve(specifier, context);
|
||||
return nextResolve(specifier);
|
||||
}
|
||||
|
||||
export function load(url, context, nextLoad) {
|
||||
|
@ -36,5 +36,5 @@ export function load(url, context, nextLoad) {
|
|||
});
|
||||
}
|
||||
|
||||
return nextLoad(url, context);
|
||||
return nextLoad(url);
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
export async function getFormat(url, context, defaultGetFormat) {
|
||||
try {
|
||||
if (new URL(url).pathname.endsWith('.unknown')) {
|
||||
return {
|
||||
format: 'module'
|
||||
};
|
||||
}
|
||||
} catch {}
|
||||
return defaultGetFormat(url, context, defaultGetFormat);
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
export async function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
export async function resolve(specifier, { parentURL, importAssertions }, next) {
|
||||
if (parentURL && specifier === '../fixtures/es-modules/test-esm-ok.mjs') {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
url: 'file:///asdf',
|
||||
};
|
||||
}
|
||||
return defaultResolve(specifier, {parentURL, importAssertions}, defaultResolve);
|
||||
return next(specifier);
|
||||
}
|
||||
|
||||
export async function load(url, context, next) {
|
||||
|
@ -16,5 +16,5 @@ export async function load(url, context, next) {
|
|||
source: '',
|
||||
}
|
||||
}
|
||||
return next(url, context, next);
|
||||
return next(url);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export async function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
export async function resolve(specifier, { parentURL, importAssertions }, next) {
|
||||
if (parentURL && specifier === '../fixtures/es-modules/test-esm-ok.mjs') {
|
||||
return {
|
||||
shortCircuit: true,
|
||||
|
@ -6,5 +6,5 @@ export async function resolve(specifier, { parentURL, importAssertions }, defaul
|
|||
importAssertions,
|
||||
};
|
||||
}
|
||||
return defaultResolve(specifier, {parentURL, importAssertions}, defaultResolve);
|
||||
return next(specifier);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export async function load(url, context, next) {
|
||||
return next([], context);
|
||||
return next([]);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export async function load(url, context, next) {
|
||||
return next('not/a/url', context);
|
||||
return next('not/a/url');
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ export async function load(url, context, next) {
|
|||
const {
|
||||
format,
|
||||
source,
|
||||
} = await next(url, context);
|
||||
} = await next(url);
|
||||
|
||||
return {
|
||||
format,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export async function load(url, context, next) {
|
||||
console.log('load passthru'); // This log is deliberate
|
||||
return next(url, context);
|
||||
return next(url);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export async function resolve(specifier, context, next) {
|
||||
return next([], context);
|
||||
return next([]);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export async function resolve(specifier, context, next) {
|
||||
console.log('resolve foo'); // This log is deliberate
|
||||
return next('file:///foo.mjs', context);
|
||||
return next('file:///foo.mjs');
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export async function resolve(specifier, context, next) {
|
||||
const { url: first } = await next(specifier, context);
|
||||
const { url: second } = await next(specifier, context);
|
||||
const { url: first } = await next(specifier);
|
||||
const { url: second } = await next(specifier);
|
||||
|
||||
return {
|
||||
format: 'module',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export async function resolve(specifier, context, next) {
|
||||
console.log('resolve passthru'); // This log is deliberate
|
||||
return next(specifier, context);
|
||||
return next(specifier);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { createRequire } from '../../common/index.mjs';
|
|||
const require = createRequire(import.meta.url);
|
||||
const dep = require('./loader-dep.js');
|
||||
|
||||
export function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
export function resolve(specifier, context, next) {
|
||||
assert.strictEqual(dep.format, 'module');
|
||||
return defaultResolve(specifier, { parentURL, importAssertions }, defaultResolve);
|
||||
return next(specifier);
|
||||
}
|
||||
|
|
|
@ -3,5 +3,5 @@ export function resolve(specifier, context, next) {
|
|||
url: 'node:unknown-builtin-module'
|
||||
};
|
||||
|
||||
return next(specifier, context, next);
|
||||
return next(specifier);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
export function resolve(specifier, { parentURL }, defaultResolve) {
|
||||
export function resolve(specifier, context, next) {
|
||||
if (specifier === 'test') {
|
||||
return {
|
||||
url: 'file://'
|
||||
};
|
||||
}
|
||||
return defaultResolve(specifier, {parentURL}, defaultResolve);
|
||||
return next(specifier);
|
||||
}
|
||||
|
||||
export function getFormat(url, context, defaultGetFormat) {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import assert from 'assert';
|
||||
import assert from 'node:assert';
|
||||
|
||||
// a loader that asserts that the defaultResolve will throw "not found"
|
||||
// (skipping the top-level main of course)
|
||||
let mainLoad = true;
|
||||
export async function resolve(specifier, { parentURL, importAssertions }, defaultResolve) {
|
||||
export async function resolve(specifier, { importAssertions }, next) {
|
||||
if (mainLoad) {
|
||||
mainLoad = false;
|
||||
return defaultResolve(specifier, {parentURL, importAssertions}, defaultResolve);
|
||||
return next(specifier);
|
||||
}
|
||||
try {
|
||||
await defaultResolve(specifier, {parentURL, importAssertions}, defaultResolve);
|
||||
await next(specifier);
|
||||
}
|
||||
catch (e) {
|
||||
assert.strictEqual(e.code, 'ERR_MODULE_NOT_FOUND');
|
||||
|
|
|
@ -28,7 +28,7 @@ export function resolve(specifier, context, next) {
|
|||
url: specifier,
|
||||
};
|
||||
}
|
||||
return next(specifier, context);
|
||||
return next(specifier);
|
||||
}
|
||||
|
||||
export function load(href, context, next) {
|
||||
|
@ -39,5 +39,5 @@ export function load(href, context, next) {
|
|||
source: SOURCES[href],
|
||||
};
|
||||
}
|
||||
return next(href, context);
|
||||
return next(href);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue