From 03d1f1d12ad698f4c2d9173ca9c31f844bdd96de Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Sun, 10 Jul 2022 21:18:33 +0200 Subject: [PATCH 01/14] esm: tidy tests --- test/common/index.mjs | 2 + test/es-module/helper.spawnAsPromised.mjs | 32 + test/es-module/test-cjs-esm-warn.js | 64 -- test/es-module/test-cjs-esm-warn.mjs | 65 ++ test/es-module/test-esm-cjs-builtins.js | 21 - test/es-module/test-esm-cjs-builtins.mjs | 15 + test/es-module/test-esm-cjs-exports.js | 35 - test/es-module/test-esm-cjs-exports.mjs | 24 + .../test-esm-cjs-load-error-note.mjs | 231 ++--- test/es-module/test-esm-cjs-main.js | 21 - test/es-module/test-esm-cjs-main.mjs | 14 + .../es-module/test-esm-encoded-path-native.js | 11 - .../test-esm-encoded-path-native.mjs | 12 + .../test-esm-experimental-warnings.mjs | 52 +- test/es-module/test-esm-export-not-found.mjs | 52 +- .../test-esm-import-json-named-export.mjs | 36 +- test/es-module/test-esm-invalid-pjson.js | 27 - test/es-module/test-esm-invalid-pjson.mjs | 24 + test/es-module/test-esm-json.mjs | 40 +- test/es-module/test-esm-loader-chaining.mjs | 843 +++++++++--------- .../test-esm-loader-http-imports.mjs | 50 +- test/es-module/test-esm-loader-not-found.mjs | 36 +- .../assertionless-json-import.mjs | 6 +- .../builtin-named-exports-loader.mjs | 2 +- .../es-module-loaders/example-loader.mjs | 4 +- .../es-module-loaders/hook-resolve-type.mjs | 2 +- .../es-module-loaders/hooks-custom.mjs | 8 +- .../es-module-loaders/hooks-obsolete.mjs | 18 +- .../es-module-loaders/http-loader.mjs | 4 +- .../es-module-loaders/loader-get-format.mjs | 10 - .../loader-invalid-format.mjs | 6 +- .../es-module-loaders/loader-invalid-url.mjs | 4 +- .../loader-load-bad-next-url.mjs | 2 +- .../loader-load-impersonating-next-url.mjs | 2 +- .../loader-load-next-modified.mjs | 2 +- .../loader-load-passthru.mjs | 2 +- .../loader-resolve-bad-next-specifier.mjs | 2 +- .../es-module-loaders/loader-resolve-foo.mjs | 2 +- .../loader-resolve-multiple-next-calls.mjs | 4 +- .../loader-resolve-passthru.mjs | 2 +- .../es-module-loaders/loader-shared-dep.mjs | 4 +- .../loader-unknown-builtin-module.mjs | 2 +- .../missing-dynamic-instantiate-hook.mjs | 4 +- .../not-found-assert-loader.mjs | 8 +- .../es-module-loaders/string-sources.mjs | 4 +- 45 files changed, 852 insertions(+), 959 deletions(-) create mode 100644 test/es-module/helper.spawnAsPromised.mjs delete mode 100644 test/es-module/test-cjs-esm-warn.js create mode 100644 test/es-module/test-cjs-esm-warn.mjs delete mode 100644 test/es-module/test-esm-cjs-builtins.js create mode 100644 test/es-module/test-esm-cjs-builtins.mjs delete mode 100644 test/es-module/test-esm-cjs-exports.js create mode 100644 test/es-module/test-esm-cjs-exports.mjs delete mode 100644 test/es-module/test-esm-cjs-main.js create mode 100644 test/es-module/test-esm-cjs-main.mjs delete mode 100644 test/es-module/test-esm-encoded-path-native.js create mode 100644 test/es-module/test-esm-encoded-path-native.mjs delete mode 100644 test/es-module/test-esm-invalid-pjson.js create mode 100644 test/es-module/test-esm-invalid-pjson.mjs delete mode 100644 test/fixtures/es-module-loaders/loader-get-format.mjs diff --git a/test/common/index.mjs b/test/common/index.mjs index a3a34ae7f04435..772d81135c7ef9 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -23,6 +23,7 @@ const { hasCrypto, hasIPv6, childShouldThrowAndAbort, + checkoutEOL, createZeroFilledFile, platformTimeout, allowGlobals, @@ -70,6 +71,7 @@ export { hasCrypto, hasIPv6, childShouldThrowAndAbort, + checkoutEOL, createZeroFilledFile, platformTimeout, allowGlobals, diff --git a/test/es-module/helper.spawnAsPromised.mjs b/test/es-module/helper.spawnAsPromised.mjs new file mode 100644 index 00000000000000..f2b1e87d0e468c --- /dev/null +++ b/test/es-module/helper.spawnAsPromised.mjs @@ -0,0 +1,32 @@ +import cp from 'node:child_process'; + + +export default function spawn(...args) { + let stderr = ''; + let stdout = ''; + + const child = cp.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, + }); + }); + }); +} diff --git a/test/es-module/test-cjs-esm-warn.js b/test/es-module/test-cjs-esm-warn.js deleted file mode 100644 index d7eeb65b152a4a..00000000000000 --- a/test/es-module/test-cjs-esm-warn.js +++ /dev/null @@ -1,64 +0,0 @@ -'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 requiringCjsAsEsm = path.resolve(fixtures.path('/es-modules/cjs-esm.js')); -const requiringEsm = path.resolve(fixtures.path('/es-modules/cjs-esm-esm.js')); -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) => { - 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) => { - 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')); - })); -} diff --git a/test/es-module/test-cjs-esm-warn.mjs b/test/es-module/test-cjs-esm-warn.mjs new file mode 100644 index 00000000000000..e3772b24d8f8af --- /dev/null +++ b/test/es-module/test-cjs-esm-warn.mjs @@ -0,0 +1,65 @@ +import { mustCall } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import path from 'node:path'; +import { execPath } from 'node:process'; + +import spawn from './helper.spawnAsPromised.mjs'; + + +const requiringCjsAsEsm = path.resolve(fixtures.path('/es-modules/cjs-esm.js')); +const requiringEsm = path.resolve(fixtures.path('/es-modules/cjs-esm-esm.js')); +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'; + spawn(execPath, [requiringCjsAsEsm]) + .then(mustCall(({ code, signal, stderr }) => { + 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); + })); +} + +{ + const required = path.resolve( + fixtures.path('/es-modules/package-type-module/esm.js') + ); + const basename = 'esm.js'; + spawn(execPath, [requiringEsm]) + .then(mustCall(({ code, signal, stderr }) => { + 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); + })); +} diff --git a/test/es-module/test-esm-cjs-builtins.js b/test/es-module/test-esm-cjs-builtins.js deleted file mode 100644 index 63aae732904137..00000000000000 --- a/test/es-module/test-esm-cjs-builtins.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -const common = require('../common'); -const fixtures = require('../common/fixtures'); -const { spawn } = require('child_process'); -const assert = require('assert'); - -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; -}); -child.on('close', common.mustCall((code, signal) => { - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - assert.strictEqual(stdout, 'ok\n'); -})); diff --git a/test/es-module/test-esm-cjs-builtins.mjs b/test/es-module/test-esm-cjs-builtins.mjs new file mode 100644 index 00000000000000..cedabf9a1a5aec --- /dev/null +++ b/test/es-module/test-esm-cjs-builtins.mjs @@ -0,0 +1,15 @@ +import { mustCall } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; + +import spawn from './helper.spawnAsPromised.mjs'; + +const entry = fixtures.path('/es-modules/builtin-imports-case.mjs'); + +spawn(execPath, [entry]) + .then(mustCall(({ code, signal, stdout }) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(stdout, 'ok\n'); + })); diff --git a/test/es-module/test-esm-cjs-exports.js b/test/es-module/test-esm-cjs-exports.js deleted file mode 100644 index 7db2c6fdb5971b..00000000000000 --- a/test/es-module/test-esm-cjs-exports.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; - -const common = require('../common'); -const fixtures = require('../common/fixtures'); -const { spawn } = require('child_process'); -const assert = require('assert'); - -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; -}); -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\'')); -})); diff --git a/test/es-module/test-esm-cjs-exports.mjs b/test/es-module/test-esm-cjs-exports.mjs new file mode 100644 index 00000000000000..f5588be970d095 --- /dev/null +++ b/test/es-module/test-esm-cjs-exports.mjs @@ -0,0 +1,24 @@ +import { mustCall } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; + +import spawn from './helper.spawnAsPromised.mjs'; + + +const validEntry = fixtures.path('/es-modules/cjs-exports.mjs'); +spawn(execPath, [validEntry]) + .then(mustCall(({ code, signal, stdout }) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(stdout, 'ok\n'); + })); + +const invalidEntry = fixtures.path('/es-modules/cjs-exports-invalid.mjs'); +spawn(execPath, [invalidEntry]) + .then(mustCall(({ code, signal, stderr }) => { + 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\'')); + })); diff --git a/test/es-module/test-esm-cjs-load-error-note.mjs b/test/es-module/test-esm-cjs-load-error-note.mjs index 0298432441391c..f5fac796cf05a1 100644 --- a/test/es-module/test-esm-cjs-load-error-note.mjs +++ b/test/es-module/test-esm-cjs-load-error-note.mjs @@ -1,163 +1,84 @@ import { mustCall } from '../common/index.mjs'; -import assert from 'assert'; -import fixtures from '../common/fixtures.js'; -import { spawn } from 'child_process'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; + +import spawn from './helper.spawnAsPromised.mjs'; -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 pExport1 = spawn(process.execPath, [Export1]); -let pExport1Stderr = ''; -pExport1.stderr.setEncoding('utf8'); -pExport1.stderr.on('data', (data) => { - pExport1Stderr += data; -}); -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}`); -})); +const mustIncludeMessage = { + getMessage: () => (stderr) => `${expectedNote} not found in ${stderr}`, + includeNote: true, +}; +const mustNotIncludeMessage = { + getMessage: () => (stderr) => `${expectedNote} must not be included in ${stderr}`, + includeNote: false, +}; + +for ( + const { errorNeedle, filePath, getMessage, includeNote } + of [ + { + filePath: fixtures.path('/es-modules/es-note-unexpected-export-1.cjs'), + ...mustIncludeMessage, + }, + { + filePath: fixtures.path('/es-modules/es-note-unexpected-import-1.cjs'), + ...mustIncludeMessage, + }, + { + filePath: fixtures.path('/es-modules/es-note-promiserej-import-2.cjs'), + ...mustNotIncludeMessage, + }, + { + filePath: fixtures.path('/es-modules/es-note-unexpected-import-3.cjs'), + ...mustIncludeMessage, + }, + { + filePath: fixtures.path('/es-modules/es-note-unexpected-import-4.cjs'), + ...mustIncludeMessage, + }, + { + filePath: fixtures.path('/es-modules/es-note-unexpected-import-5.cjs'), + ...mustNotIncludeMessage, + }, + { + filePath: fixtures.path('/es-modules/es-note-error-1.mjs'), + ...mustNotIncludeMessage, + errorNeedle: 'Error: some error', + }, + { + filePath: fixtures.path('/es-modules/es-note-error-2.mjs'), + ...mustNotIncludeMessage, + errorNeedle: 'string', + }, + { + filePath: fixtures.path('/es-modules/es-note-error-3.mjs'), + ...mustNotIncludeMessage, + errorNeedle: 'null', + }, + { + filePath: fixtures.path('/es-modules/es-note-error-4.mjs'), + ...mustNotIncludeMessage, + errorNeedle: 'undefined', + }, + ] +) { + spawn(execPath, [filePath]) + .then(mustCall(({ code, stderr }) => { + assert.strictEqual(code, 1); + + if (errorNeedle) stderr.includes(errorNeedle); + + const includesNote = stderr.includes(expectedNote); + assert.ok( + includeNote ? includesNote : !includesNote, + `${filePath} ${getMessage(stderr)}`, + ); + })); +} diff --git a/test/es-module/test-esm-cjs-main.js b/test/es-module/test-esm-cjs-main.js deleted file mode 100644 index 92f4124ccaab8a..00000000000000 --- a/test/es-module/test-esm-cjs-main.js +++ /dev/null @@ -1,21 +0,0 @@ -'use strict'; - -const common = require('../common'); -const fixtures = require('../common/fixtures'); -const { spawn } = require('child_process'); -const assert = require('assert'); - -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; -}); -child.on('close', common.mustCall((code, signal) => { - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - assert.strictEqual(stdout, 'executed\n'); -})); diff --git a/test/es-module/test-esm-cjs-main.mjs b/test/es-module/test-esm-cjs-main.mjs new file mode 100644 index 00000000000000..1275a917a86c7c --- /dev/null +++ b/test/es-module/test-esm-cjs-main.mjs @@ -0,0 +1,14 @@ +import { mustCall } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; + +import spawn from './helper.spawnAsPromised.mjs'; + + +spawn(execPath, [fixtures.path('/es-modules/cjs.js')]) + .then(mustCall(({ code, signal, stdout }) => { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(stdout, 'executed\n'); + })); diff --git a/test/es-module/test-esm-encoded-path-native.js b/test/es-module/test-esm-encoded-path-native.js deleted file mode 100644 index b8f5719b6089ee..00000000000000 --- a/test/es-module/test-esm-encoded-path-native.js +++ /dev/null @@ -1,11 +0,0 @@ -'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); -}); diff --git a/test/es-module/test-esm-encoded-path-native.mjs b/test/es-module/test-esm-encoded-path-native.mjs new file mode 100644 index 00000000000000..a8ef51dcb18813 --- /dev/null +++ b/test/es-module/test-esm-encoded-path-native.mjs @@ -0,0 +1,12 @@ +import { mustCall } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; + +import spawn from './helper.spawnAsPromised.mjs'; + + +spawn(execPath, [fixtures.path('es-module-url/native.mjs')]) + .then(mustCall(({ code }) => { + assert.strictEqual(code, 1); + })); diff --git a/test/es-module/test-esm-experimental-warnings.mjs b/test/es-module/test-esm-experimental-warnings.mjs index b6ef757a88302e..e0be18d4390cbd 100644 --- a/test/es-module/test-esm-experimental-warnings.mjs +++ b/test/es-module/test-esm-experimental-warnings.mjs @@ -1,31 +1,26 @@ import { mustCall } 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 { execPath } from 'node:process'; -// 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, - ]); +import spawn from './helper.spawnAsPromised.mjs'; - 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); + +// Verify no warnings are printed when no experimental features are enabled or used +spawn(execPath, [ + '--input-type=module', + '--eval', + `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`, +]) + .then(mustCall(({ code, signal, stderr }) => { doesNotMatch( stderr, /ExperimentalWarning/, new Error('No experimental warning(s) should be emitted when no experimental feature is enabled') ); + strictEqual(code, 0); + strictEqual(signal, null); })); -} // Verify experimental warning is printed when experimental feature is enabled for ( @@ -35,21 +30,16 @@ for ( [/specifier resolution/, '--experimental-specifier-resolution=node'], ] ) { - const input = `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`; - const child = spawn(execPath, [ + 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); - })); + `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`, + ]) + .then(mustCall(({ code, signal, stderr }) => { + match(stderr, /ExperimentalWarning/); + match(stderr, experiment); + strictEqual(code, 0); + strictEqual(signal, null); + })); } diff --git a/test/es-module/test-esm-export-not-found.mjs b/test/es-module/test-esm-export-not-found.mjs index cdfe6df0fcde31..663de2d7fe71bc 100644 --- a/test/es-module/test-esm-export-not-found.mjs +++ b/test/es-module/test-esm-export-not-found.mjs @@ -1,39 +1,39 @@ 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 * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; -const importStatement = - 'import { foo, notfound } from \'./module-named-exports.mjs\';'; +import spawn from './helper.spawnAsPromised.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, [ +for ( + const input + of [ + importStatement, + importStatementMultiline, + ] +) { + spawn(execPath, [ '--input-type=module', '--eval', input, ], { - cwd: 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); + cwd: fixtures.path('es-module-loaders'), + }) + .then(mustCall(({ code, stderr, stdout }) => { + 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/); + })); +} diff --git a/test/es-module/test-esm-import-json-named-export.mjs b/test/es-module/test-esm-import-json-named-export.mjs index 3c0f3af662c7cc..83ac87b4647263 100644 --- a/test/es-module/test-esm-import-json-named-export.mjs +++ b/test/es-module/test-esm-import-json-named-export.mjs @@ -1,24 +1,20 @@ 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 * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; -const child = spawn(execPath, [ - path('es-modules', 'import-json-named-export.mjs'), -]); +import spawn from './helper.spawnAsPromised.mjs'; -let stderr = ''; -child.stderr.setEncoding('utf8'); -child.stderr.on('data', (data) => { - stderr += data; -}); -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'/); -})); +spawn(execPath, [ + fixtures.path('es-modules', 'import-json-named-export.mjs'), +]) + .then(mustCall(({ code, stderr }) => { + // 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); + })); diff --git a/test/es-module/test-esm-invalid-pjson.js b/test/es-module/test-esm-invalid-pjson.js deleted file mode 100644 index cdbebb17b4bb34..00000000000000 --- a/test/es-module/test-esm-invalid-pjson.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict'; - -const { mustCall, checkoutEOL } = require('../common'); -const fixtures = require('../common/fixtures'); -const { spawn } = require('child_process'); -const { strictEqual, ok } = require('assert'); - -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; -}); -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); -})); diff --git a/test/es-module/test-esm-invalid-pjson.mjs b/test/es-module/test-esm-invalid-pjson.mjs new file mode 100644 index 00000000000000..22a57b0058a70f --- /dev/null +++ b/test/es-module/test-esm-invalid-pjson.mjs @@ -0,0 +1,24 @@ +import { checkoutEOL, mustCall } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; + +import spawn from './helper.spawnAsPromised.mjs'; + + +const entry = fixtures.path('/es-modules/import-invalid-pjson.mjs'); +const invalidJson = fixtures.path('/node_modules/invalid-pjson/package.json'); + +spawn(execPath, [entry]) + .then(mustCall(({ code, signal, stderr }) => { + 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); + })); diff --git a/test/es-module/test-esm-json.mjs b/test/es-module/test-esm-json.mjs index 6d55419eedc857..82c66cd215990c 100644 --- a/test/es-module/test-esm-json.mjs +++ b/test/es-module/test-esm-json.mjs @@ -1,27 +1,23 @@ -import '../common/index.mjs'; -import { path } from '../common/fixtures.mjs'; -import { strictEqual, ok } from 'assert'; -import { spawn } from 'child_process'; +import { mustCall } from '../common/index.mjs'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; import secret from '../fixtures/experimental.json' assert { type: 'json' }; +import spawn from './helper.spawnAsPromised.mjs'; -strictEqual(secret.ofLife, 42); -// Test warning message -const child = spawn(process.execPath, [ - path('/es-modules/json-modules.mjs'), -]); +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' - )); -}); +// Test warning message +spawn(execPath, [ + fixtures.path('/es-modules/json-modules.mjs'), +]) + .then(mustCall(({ code, signal, stderr }) => { + assert.ok(stderr.includes( + 'ExperimentalWarning: Importing JSON modules is an experimental feature. ' + + 'This feature could change at any time' + )); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + })); diff --git a/test/es-module/test-esm-loader-chaining.mjs b/test/es-module/test-esm-loader-chaining.mjs index f1ea13495ca5c4..e50286a54bd7ba 100644 --- a/test/es-module/test-esm-loader-chaining.mjs +++ b/test/es-module/test-esm-loader-chaining.mjs @@ -1,7 +1,10 @@ -import '../common/index.mjs'; -import fixtures from '../common/fixtures.js'; +import { mustCall } from '../common/index.mjs'; +import { fileURL } from '../common/fixtures.mjs'; import assert from 'node:assert'; -import { spawnSync } from 'node:child_process'; +import { execPath } from 'node:process'; + +import spawn from './helper.spawnAsPromised.mjs'; + const setupArgs = [ '--no-warnings', @@ -14,420 +17,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' }, - ); - - assert.strictEqual(stderr, ''); - assert.match(stdout, /number/); // node:fs is an object - assert.strictEqual(status, 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' }, - ); - - assert.strictEqual(stderr, ''); - assert.match(stdout, /load passthru/); - assert.match(stdout, /resolve passthru/); - assert.match(stdout, /foo/); - assert.strictEqual(status, 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' }, - ); - - 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); -} - -{ // 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' }, - ); - - assert.strictEqual(stderr, ''); - assert.match(stdout, /bar/); - assert.strictEqual(status, 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' }, - ); - - 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); -} - -{ // 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' }, - ); - - const countFoos = stdout.match(/resolve foo/g)?.length; - - assert.strictEqual(stderr, ''); - assert.strictEqual(countFoos, 2); - assert.strictEqual(status, 0); -} - -{ // Verify next 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' }, - ); - - assert.strictEqual(stderr, ''); - assert.match(stdout, /next: nextResolve/); - assert.strictEqual(status, 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' }, - ); - - 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); -} - -{ // 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(status, 0); -} - -{ // 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(status, 0); -} - -{ // 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(status, 1); -} - -{ // 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(status, 1); -} - -{ // 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(status, 1); -} - -{ // 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(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/); -} - -{ // 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(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/); -} - -{ // 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(status, 1); -} - -{ // 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(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/); -} - -{ // 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(status, 1); -} - -{ // 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(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); -} +// Verify unadulterated source is loaded when there are no loaders +spawn( + execPath, + [ + ...setupArgs, + 'import fs from "node:fs"; console.log(typeof fs?.constants?.F_OK )', + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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 +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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 +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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 +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-receiving-modified-context.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-passing-modified-context.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + assert.strictEqual(stderr, ''); + assert.match(stdout, /bar/); + assert.strictEqual(code, 0); + })); + +// Verify multiple changes from hooks result in proper output +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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 +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-multiple-next-calls.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + const countFoos = stdout.match(/resolve foo/g)?.length; + + assert.strictEqual(stderr, ''); + assert.strictEqual(countFoos, 2); + assert.strictEqual(code, 0); + })); + +// Verify next function's `name` is correct +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + assert.strictEqual(stderr, ''); + assert.match(stdout, /next: nextResolve/); + assert.strictEqual(code, 0); + })); + +// Verify error thrown for incomplete resolve chain, citing errant loader & hook +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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); + })); + +// Verify error NOT thrown when nested resolve hook signaled a short circuit +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-next-modified.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout.trim(), 'foo'); + assert.strictEqual(code, 0); + })); + +// Verify error NOT thrown when nested load hook signaled a short circuit +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-next-modified.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + assert.strictEqual(stderr, ''); + assert.match(stdout, /421/); + assert.strictEqual(code, 0); + })); + +// Verify resolve chain does break and throws appropriately +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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); + })); + +// Verify error thrown for incomplete load chain, citing errant loader & hook +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-incomplete.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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); + })); + +// Verify load chain does break and throws appropriately +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-incomplete.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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); + })); + +// Verify error thrown when invalid `specifier` argument passed to `nextResolve` +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-bad-next-specifier.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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/); + })); + +// Verify error thrown when resolve hook is invalid +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-null-return.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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/); + })); + +// Verify error thrown when invalid `context` argument passed to `nextResolve` +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-bad-next-context.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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); + })); + +// Verify error thrown when load hook is invalid +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-null-return.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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/); + })); + +// Verify error thrown when invalid `url` argument passed to `nextLoad` +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-bad-next-url.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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); + })); + +// Verify error thrown when invalid `url` argument passed to `nextLoad` +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-impersonating-next-url.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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); + })); + +// Verify error thrown when invalid `context` argument passed to `nextLoad` +spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-bad-next-context.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, +) + .then(mustCall(({ code, stderr, stdout }) => { + 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); + })); diff --git a/test/es-module/test-esm-loader-http-imports.mjs b/test/es-module/test-esm-loader-http-imports.mjs index 5f6cc47f388271..9741ef02de4a38 100644 --- a/test/es-module/test-esm-loader-http-imports.mjs +++ b/test/es-module/test-esm-loader-http-imports.mjs @@ -1,11 +1,13 @@ import { mustCall } 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 spawn from './helper.spawnAsPromised.mjs'; + const files = { 'main.mjs': 'export * from "./lib.mjs";', @@ -40,33 +42,23 @@ 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)`, - ] - ); - - let stderr = ''; - let stdout = ''; - - child.stderr.setEncoding('utf8'); - child.stderr.on('data', (data) => stderr += data); - child.stdout.setEncoding('utf8'); - child.stdout.on('data', (data) => stdout += data); - - child.on('close', mustCall((code, signal) => { - strictEqual(stderr, ''); - strictEqual(stdout, '[Module: null prototype] { sum: [Function: sum] }\n'); - strictEqual(code, 0); - strictEqual(signal, null); +// Verify nested HTTP imports work +spawn( // ! `spawn` MUST be used (vs `spawnSync`) to avoid blocking the event loop + 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)`, + ] +) + .then(mustCall(({ code, signal, stderr, stdout }) => { + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, '[Module: null prototype] { sum: [Function: sum] }\n'); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); server.close(); })); -} diff --git a/test/es-module/test-esm-loader-not-found.mjs b/test/es-module/test-esm-loader-not-found.mjs index 275f0b0f1e8515..772349e02a4d77 100644 --- a/test/es-module/test-esm-loader-not-found.mjs +++ b/test/es-module/test-esm-loader-not-found.mjs @@ -1,27 +1,23 @@ import { mustCall } from '../common/index.mjs'; -import { path } from '../common/fixtures.mjs'; -import { match, ok, notStrictEqual } from 'assert'; -import { spawn } from 'child_process'; +import * as fixtures from '../common/fixtures.mjs'; +import assert from 'assert'; import { execPath } from 'process'; -const child = spawn(execPath, [ +import spawn from './helper.spawnAsPromised.mjs'; + + +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; -}); -child.on('close', mustCall((code, _signal) => { - notStrictEqual(code, 0); + fixtures.path('print-error-message.js'), +]) + .then(mustCall(({ code, stderr }) => { + assert.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'/); + // 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'/); - ok(!stderr.includes('Bad command or file name')); -})); + assert.ok(!stderr.includes('Bad command or file name')); + })); diff --git a/test/fixtures/es-module-loaders/assertionless-json-import.mjs b/test/fixtures/es-module-loaders/assertionless-json-import.mjs index c5c2fadf28fb58..07656d4ec40fa3 100644 --- a/test/fixtures/es-module-loaders/assertionless-json-import.mjs +++ b/test/fixtures/es-module-loaders/assertionless-json-import.mjs @@ -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); } diff --git a/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs b/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs index e303ec196f6c6d..8c317c1b7ce31e 100644 --- a/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs +++ b/test/fixtures/es-module-loaders/builtin-named-exports-loader.mjs @@ -35,7 +35,7 @@ export function load(url, context, next) { format: 'module', }; } - return next(url, context); + return next(url); } function generateBuiltinModule(builtinName) { diff --git a/test/fixtures/es-module-loaders/example-loader.mjs b/test/fixtures/es-module-loaders/example-loader.mjs index f87054c8b70502..77d44d55f91523 100644 --- a/test/fixtures/es-module-loaders/example-loader.mjs +++ b/test/fixtures/es-module-loaders/example-loader.mjs @@ -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`); } diff --git a/test/fixtures/es-module-loaders/hook-resolve-type.mjs b/test/fixtures/es-module-loaders/hook-resolve-type.mjs index 5068d6265c57b2..b1f5606c0e4a0a 100644 --- a/test/fixtures/es-module-loaders/hook-resolve-type.mjs +++ b/test/fixtures/es-module-loaders/hook-resolve-type.mjs @@ -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) { diff --git a/test/fixtures/es-module-loaders/hooks-custom.mjs b/test/fixtures/es-module-loaders/hooks-custom.mjs index 4c4014db01ef3f..65dba3535c2d95 100644 --- a/test/fixtures/es-module-loaders/hooks-custom.mjs +++ b/test/fixtures/es-module-loaders/hooks-custom.mjs @@ -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); } diff --git a/test/fixtures/es-module-loaders/hooks-obsolete.mjs b/test/fixtures/es-module-loaders/hooks-obsolete.mjs index 9d12251923d7e9..bb10ef8ef4b29a 100644 --- a/test/fixtures/es-module-loaders/hooks-obsolete.mjs +++ b/test/fixtures/es-module-loaders/hooks-obsolete.mjs @@ -4,19 +4,19 @@ export function getSource() {} export function transformSource() {} -export function load(url, context, next) { - if (url === 'whatever') return { - format: 'module', - source: '', +export function resolve(specifier, context, next) { + if (specifier === 'whatever') return { + url: specifier, }; - return next(url, context, next); + return next(specifier); } -export function resolve(specifier, context, next) { - if (specifier === 'whatever') return { - url: specifier, +export function load(url, context, next) { + if (url === 'whatever') return { + format: 'module', + source: '', }; - return next(specifier, context, next); + return next(url); } diff --git a/test/fixtures/es-module-loaders/http-loader.mjs b/test/fixtures/es-module-loaders/http-loader.mjs index f0add5d5b419f8..8096dd9bb73a4c 100644 --- a/test/fixtures/es-module-loaders/http-loader.mjs +++ b/test/fixtures/es-module-loaders/http-loader.mjs @@ -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); } diff --git a/test/fixtures/es-module-loaders/loader-get-format.mjs b/test/fixtures/es-module-loaders/loader-get-format.mjs deleted file mode 100644 index 7ade70fca0ebe6..00000000000000 --- a/test/fixtures/es-module-loaders/loader-get-format.mjs +++ /dev/null @@ -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); -} diff --git a/test/fixtures/es-module-loaders/loader-invalid-format.mjs b/test/fixtures/es-module-loaders/loader-invalid-format.mjs index 438d50dacba433..e7dd06c108ba1d 100644 --- a/test/fixtures/es-module-loaders/loader-invalid-format.mjs +++ b/test/fixtures/es-module-loaders/loader-invalid-format.mjs @@ -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); } diff --git a/test/fixtures/es-module-loaders/loader-invalid-url.mjs b/test/fixtures/es-module-loaders/loader-invalid-url.mjs index 87d1a6a564b461..a54f39521f29ac 100644 --- a/test/fixtures/es-module-loaders/loader-invalid-url.mjs +++ b/test/fixtures/es-module-loaders/loader-invalid-url.mjs @@ -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); } diff --git a/test/fixtures/es-module-loaders/loader-load-bad-next-url.mjs b/test/fixtures/es-module-loaders/loader-load-bad-next-url.mjs index 4f53b695327dd1..c6a4c7504d43e5 100644 --- a/test/fixtures/es-module-loaders/loader-load-bad-next-url.mjs +++ b/test/fixtures/es-module-loaders/loader-load-bad-next-url.mjs @@ -1,3 +1,3 @@ export async function load(url, context, next) { - return next([], context); + return next([]); } diff --git a/test/fixtures/es-module-loaders/loader-load-impersonating-next-url.mjs b/test/fixtures/es-module-loaders/loader-load-impersonating-next-url.mjs index f98b091c8b9ff5..1028e093e46819 100644 --- a/test/fixtures/es-module-loaders/loader-load-impersonating-next-url.mjs +++ b/test/fixtures/es-module-loaders/loader-load-impersonating-next-url.mjs @@ -1,3 +1,3 @@ export async function load(url, context, next) { - return next('not/a/url', context); + return next('not/a/url'); } diff --git a/test/fixtures/es-module-loaders/loader-load-next-modified.mjs b/test/fixtures/es-module-loaders/loader-load-next-modified.mjs index 1f2382467f7122..401b52971311a7 100644 --- a/test/fixtures/es-module-loaders/loader-load-next-modified.mjs +++ b/test/fixtures/es-module-loaders/loader-load-next-modified.mjs @@ -2,7 +2,7 @@ export async function load(url, context, next) { const { format, source, - } = await next(url, context); + } = await next(url); return { format, diff --git a/test/fixtures/es-module-loaders/loader-load-passthru.mjs b/test/fixtures/es-module-loaders/loader-load-passthru.mjs index 8cfbcb6a3a5d0b..0de06142007562 100644 --- a/test/fixtures/es-module-loaders/loader-load-passthru.mjs +++ b/test/fixtures/es-module-loaders/loader-load-passthru.mjs @@ -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); } diff --git a/test/fixtures/es-module-loaders/loader-resolve-bad-next-specifier.mjs b/test/fixtures/es-module-loaders/loader-resolve-bad-next-specifier.mjs index a23785d3d956db..66c941754f90cc 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-bad-next-specifier.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-bad-next-specifier.mjs @@ -1,3 +1,3 @@ export async function resolve(specifier, context, next) { - return next([], context); + return next([]); } diff --git a/test/fixtures/es-module-loaders/loader-resolve-foo.mjs b/test/fixtures/es-module-loaders/loader-resolve-foo.mjs index 595385e12a0cf7..7d23d6c49088c9 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-foo.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-foo.mjs @@ -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'); } diff --git a/test/fixtures/es-module-loaders/loader-resolve-multiple-next-calls.mjs b/test/fixtures/es-module-loaders/loader-resolve-multiple-next-calls.mjs index 88d333c2404a3c..91dbec251edeba 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-multiple-next-calls.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-multiple-next-calls.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', diff --git a/test/fixtures/es-module-loaders/loader-resolve-passthru.mjs b/test/fixtures/es-module-loaders/loader-resolve-passthru.mjs index 1a373bab90ba57..3db5b21bb98793 100644 --- a/test/fixtures/es-module-loaders/loader-resolve-passthru.mjs +++ b/test/fixtures/es-module-loaders/loader-resolve-passthru.mjs @@ -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); } diff --git a/test/fixtures/es-module-loaders/loader-shared-dep.mjs b/test/fixtures/es-module-loaders/loader-shared-dep.mjs index 387575794c00dc..d41c1ae403399e 100644 --- a/test/fixtures/es-module-loaders/loader-shared-dep.mjs +++ b/test/fixtures/es-module-loaders/loader-shared-dep.mjs @@ -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); } diff --git a/test/fixtures/es-module-loaders/loader-unknown-builtin-module.mjs b/test/fixtures/es-module-loaders/loader-unknown-builtin-module.mjs index 1063f8dfd65f2f..65e1adf909d0bc 100644 --- a/test/fixtures/es-module-loaders/loader-unknown-builtin-module.mjs +++ b/test/fixtures/es-module-loaders/loader-unknown-builtin-module.mjs @@ -3,5 +3,5 @@ export function resolve(specifier, context, next) { url: 'node:unknown-builtin-module' }; - return next(specifier, context, next); + return next(specifier); } diff --git a/test/fixtures/es-module-loaders/missing-dynamic-instantiate-hook.mjs b/test/fixtures/es-module-loaders/missing-dynamic-instantiate-hook.mjs index ec15eb0bb8fc24..5d61d81bc31ed5 100644 --- a/test/fixtures/es-module-loaders/missing-dynamic-instantiate-hook.mjs +++ b/test/fixtures/es-module-loaders/missing-dynamic-instantiate-hook.mjs @@ -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) { diff --git a/test/fixtures/es-module-loaders/not-found-assert-loader.mjs b/test/fixtures/es-module-loaders/not-found-assert-loader.mjs index 5213ddedb34e8d..ea4c73724298db 100644 --- a/test/fixtures/es-module-loaders/not-found-assert-loader.mjs +++ b/test/fixtures/es-module-loaders/not-found-assert-loader.mjs @@ -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'); diff --git a/test/fixtures/es-module-loaders/string-sources.mjs b/test/fixtures/es-module-loaders/string-sources.mjs index 1fc2b7a8d6f7e3..396d17cb17a75c 100644 --- a/test/fixtures/es-module-loaders/string-sources.mjs +++ b/test/fixtures/es-module-loaders/string-sources.mjs @@ -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); } From 24157ab6fe230b6cffb1bdb3646422f01f850f74 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 13 Jul 2022 23:38:27 +0200 Subject: [PATCH 02/14] switch to node:test --- lib/internal/modules/esm/loader.js | 2 +- test/es-module/helper.spawnAsPromised.mjs | 1 + ...-cjs-esm-warn.mjs => test-cjs-esm-warn.js} | 54 +- test/es-module/test-esm-cjs-builtins.js | 24 + test/es-module/test-esm-cjs-builtins.mjs | 15 - test/es-module/test-esm-cjs-exports.js | 33 + test/es-module/test-esm-cjs-exports.mjs | 24 - .../test-esm-cjs-load-error-note.mjs | 122 ++-- test/es-module/test-esm-cjs-main.js | 24 + test/es-module/test-esm-cjs-main.mjs | 14 - .../es-module/test-esm-encoded-path-native.js | 22 + .../test-esm-encoded-path-native.mjs | 12 - .../test-esm-experimental-warnings.mjs | 67 +- test/es-module/test-esm-export-not-found.mjs | 46 +- .../test-esm-import-json-named-export.mjs | 16 +- test/es-module/test-esm-initialization.mjs | 39 +- test/es-module/test-esm-invalid-extension.js | 13 - test/es-module/test-esm-invalid-pjson.js | 32 + test/es-module/test-esm-invalid-pjson.mjs | 24 - test/es-module/test-esm-json.mjs | 27 +- test/es-module/test-esm-loader-chaining.mjs | 667 +++++++++--------- .../test-esm-loader-http-imports.mjs | 41 +- test/es-module/test-esm-loader-not-found.mjs | 27 +- .../test-esm-loader-obsolete-hooks.mjs | 52 +- test/es-module/test-esm-loader-thenable.mjs | 78 +- .../test-esm-loader-with-syntax-error.mjs | 36 +- ...est-esm-module-not-found-commonjs-hint.mjs | 61 +- test/es-module/test-esm-non-js.mjs | 36 +- test/es-module/test-esm-nowarn-exports.mjs | 36 +- test/es-module/test-esm-repl-imports.js | 34 +- test/es-module/test-esm-specifiers.mjs | 139 ++-- test/es-module/test-esm-syntax-error.mjs | 29 +- test/es-module/test-esm-tla-unfinished.mjs | 213 +++--- .../test-esm-unknown-or-no-extension.js | 70 +- test/es-module/test-esm-wasm.mjs | 64 +- test/es-module/test-http-imports-cli.mjs | 80 ++- 36 files changed, 1196 insertions(+), 1078 deletions(-) rename test/es-module/{test-cjs-esm-warn.mjs => test-cjs-esm-warn.js} (59%) create mode 100644 test/es-module/test-esm-cjs-builtins.js delete mode 100644 test/es-module/test-esm-cjs-builtins.mjs create mode 100644 test/es-module/test-esm-cjs-exports.js delete mode 100644 test/es-module/test-esm-cjs-exports.mjs create mode 100644 test/es-module/test-esm-cjs-main.js delete mode 100644 test/es-module/test-esm-cjs-main.mjs create mode 100644 test/es-module/test-esm-encoded-path-native.js delete mode 100644 test/es-module/test-esm-encoded-path-native.mjs delete mode 100644 test/es-module/test-esm-invalid-extension.js create mode 100644 test/es-module/test-esm-invalid-pjson.js delete mode 100644 test/es-module/test-esm-invalid-pjson.mjs diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js index 223fd68a79fd00..027077cbb6e781 100644 --- a/lib/internal/modules/esm/loader.js +++ b/lib/internal/modules/esm/loader.js @@ -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++) { diff --git a/test/es-module/helper.spawnAsPromised.mjs b/test/es-module/helper.spawnAsPromised.mjs index f2b1e87d0e468c..3d3308a4d04fcb 100644 --- a/test/es-module/helper.spawnAsPromised.mjs +++ b/test/es-module/helper.spawnAsPromised.mjs @@ -1,3 +1,4 @@ +import '../common/index.mjs'; import cp from 'node:child_process'; diff --git a/test/es-module/test-cjs-esm-warn.mjs b/test/es-module/test-cjs-esm-warn.js similarity index 59% rename from test/es-module/test-cjs-esm-warn.mjs rename to test/es-module/test-cjs-esm-warn.js index e3772b24d8f8af..5e49e779b0d912 100644 --- a/test/es-module/test-cjs-esm-warn.mjs +++ b/test/es-module/test-cjs-esm-warn.js @@ -1,10 +1,11 @@ -import { mustCall } from '../common/index.mjs'; -import * as fixtures from '../common/fixtures.mjs'; -import assert from 'node:assert'; -import path from 'node:path'; -import { execPath } from 'node:process'; +'use strict'; -import spawn from './helper.spawnAsPromised.mjs'; +const { mustCall } = 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')); @@ -13,13 +14,18 @@ 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'; - spawn(execPath, [requiringCjsAsEsm]) - .then(mustCall(({ code, signal, stderr }) => { +(async () => { + const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); + + 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 spawn(execPath, [requiringCjsAsEsm]); + assert.ok( stderr.replaceAll('\r', '').includes( `Error [ERR_REQUIRE_ESM]: require() of ES Module ${required} from ${requiringCjsAsEsm} not supported.\n` @@ -37,16 +43,15 @@ const pjson = path.resolve( assert.strictEqual(code, 1); assert.strictEqual(signal, null); - })); -} + }); + + it(async () => { + const required = path.resolve( + fixtures.path('/es-modules/package-type-module/esm.js') + ); + const basename = 'esm.js'; + const { code, signal, stderr } = await spawn(execPath, [requiringEsm]); -{ - const required = path.resolve( - fixtures.path('/es-modules/package-type-module/esm.js') - ); - const basename = 'esm.js'; - spawn(execPath, [requiringEsm]) - .then(mustCall(({ code, signal, stderr }) => { assert.ok( stderr.replace(/\r/g, '').includes( `Error [ERR_REQUIRE_ESM]: require() of ES Module ${required} from ${requiringEsm} not supported.\n` @@ -61,5 +66,6 @@ const pjson = path.resolve( assert.strictEqual(code, 1); assert.strictEqual(signal, null); - })); -} + }); + }); +})().then(mustCall()); diff --git a/test/es-module/test-esm-cjs-builtins.js b/test/es-module/test-esm-cjs-builtins.js new file mode 100644 index 00000000000000..416d279af0c093 --- /dev/null +++ b/test/es-module/test-esm-cjs-builtins.js @@ -0,0 +1,24 @@ +'use strict'; + +const { mustCall } = 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'); + +(async () => { + const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); + + describe('ESM: importing builtins & CJS', () => { + it('should work', async () => { + const { code, signal, stdout } = await spawn(execPath, [entry]); + + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(stdout, 'ok\n'); + }); + }); +})().then(mustCall()); diff --git a/test/es-module/test-esm-cjs-builtins.mjs b/test/es-module/test-esm-cjs-builtins.mjs deleted file mode 100644 index cedabf9a1a5aec..00000000000000 --- a/test/es-module/test-esm-cjs-builtins.mjs +++ /dev/null @@ -1,15 +0,0 @@ -import { mustCall } from '../common/index.mjs'; -import * as fixtures from '../common/fixtures.mjs'; -import assert from 'node:assert'; -import { execPath } from 'node:process'; - -import spawn from './helper.spawnAsPromised.mjs'; - -const entry = fixtures.path('/es-modules/builtin-imports-case.mjs'); - -spawn(execPath, [entry]) - .then(mustCall(({ code, signal, stdout }) => { - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - assert.strictEqual(stdout, 'ok\n'); - })); diff --git a/test/es-module/test-esm-cjs-exports.js b/test/es-module/test-esm-cjs-exports.js new file mode 100644 index 00000000000000..16d94dfcc7f389 --- /dev/null +++ b/test/es-module/test-esm-cjs-exports.js @@ -0,0 +1,33 @@ +'use strict'; + +const { mustCall } = require('../common'); +const fixtures = require('../common/fixtures.js'); +const assert = require('node:assert'); +const { execPath } = require('node:process'); +const { describe, it } = require('node:test'); + + +(async () => { + const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); + + 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 spawn(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 spawn(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\'')); + }); + }); +})().then(mustCall()); diff --git a/test/es-module/test-esm-cjs-exports.mjs b/test/es-module/test-esm-cjs-exports.mjs deleted file mode 100644 index f5588be970d095..00000000000000 --- a/test/es-module/test-esm-cjs-exports.mjs +++ /dev/null @@ -1,24 +0,0 @@ -import { mustCall } from '../common/index.mjs'; -import * as fixtures from '../common/fixtures.mjs'; -import assert from 'node:assert'; -import { execPath } from 'node:process'; - -import spawn from './helper.spawnAsPromised.mjs'; - - -const validEntry = fixtures.path('/es-modules/cjs-exports.mjs'); -spawn(execPath, [validEntry]) - .then(mustCall(({ code, signal, stdout }) => { - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - assert.strictEqual(stdout, 'ok\n'); - })); - -const invalidEntry = fixtures.path('/es-modules/cjs-exports-invalid.mjs'); -spawn(execPath, [invalidEntry]) - .then(mustCall(({ code, signal, stderr }) => { - 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\'')); - })); diff --git a/test/es-module/test-esm-cjs-load-error-note.mjs b/test/es-module/test-esm-cjs-load-error-note.mjs index f5fac796cf05a1..63ad3cd3eb781b 100644 --- a/test/es-module/test-esm-cjs-load-error-note.mjs +++ b/test/es-module/test-esm-cjs-load-error-note.mjs @@ -1,7 +1,8 @@ -import { mustCall } from '../common/index.mjs'; +import '../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 spawn from './helper.spawnAsPromised.mjs'; @@ -20,57 +21,69 @@ const mustNotIncludeMessage = { includeNote: false, }; -for ( - const { errorNeedle, filePath, getMessage, includeNote } - of [ - { - filePath: fixtures.path('/es-modules/es-note-unexpected-export-1.cjs'), - ...mustIncludeMessage, - }, - { - filePath: fixtures.path('/es-modules/es-note-unexpected-import-1.cjs'), - ...mustIncludeMessage, - }, - { - filePath: fixtures.path('/es-modules/es-note-promiserej-import-2.cjs'), - ...mustNotIncludeMessage, - }, - { - filePath: fixtures.path('/es-modules/es-note-unexpected-import-3.cjs'), - ...mustIncludeMessage, - }, - { - filePath: fixtures.path('/es-modules/es-note-unexpected-import-4.cjs'), - ...mustIncludeMessage, - }, - { - filePath: fixtures.path('/es-modules/es-note-unexpected-import-5.cjs'), - ...mustNotIncludeMessage, - }, - { - filePath: fixtures.path('/es-modules/es-note-error-1.mjs'), - ...mustNotIncludeMessage, - errorNeedle: 'Error: some error', - }, - { - filePath: fixtures.path('/es-modules/es-note-error-2.mjs'), - ...mustNotIncludeMessage, - errorNeedle: 'string', - }, - { - filePath: fixtures.path('/es-modules/es-note-error-3.mjs'), - ...mustNotIncludeMessage, - errorNeedle: 'null', - }, - { - filePath: fixtures.path('/es-modules/es-note-error-4.mjs'), - ...mustNotIncludeMessage, - errorNeedle: 'undefined', - }, - ] -) { - spawn(execPath, [filePath]) - .then(mustCall(({ code, stderr }) => { +describe('ESM: ', { concurrently: 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 spawn(execPath, [filePath]); + assert.strictEqual(code, 1); if (errorNeedle) stderr.includes(errorNeedle); @@ -80,5 +93,6 @@ for ( includeNote ? includesNote : !includesNote, `${filePath} ${getMessage(stderr)}`, ); - })); -} + }); + } +}); diff --git a/test/es-module/test-esm-cjs-main.js b/test/es-module/test-esm-cjs-main.js new file mode 100644 index 00000000000000..0d71100dbf597c --- /dev/null +++ b/test/es-module/test-esm-cjs-main.js @@ -0,0 +1,24 @@ +'use strict'; + +const { mustCall } = require('../common'); +const fixtures = require('../common/fixtures.js'); +const assert = require('node:assert'); +const { execPath } = require('node:process'); +const { describe, it } = require('node:test'); + + +(async () => { + const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); + + describe('ESM: importing CJS', () => { + it('should work', async () => { + const { code, signal, stdout } = await spawn(execPath, [ + fixtures.path('/es-modules/cjs.js'), + ]); + + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(stdout, 'executed\n'); + }); + }); +})().then(mustCall()); diff --git a/test/es-module/test-esm-cjs-main.mjs b/test/es-module/test-esm-cjs-main.mjs deleted file mode 100644 index 1275a917a86c7c..00000000000000 --- a/test/es-module/test-esm-cjs-main.mjs +++ /dev/null @@ -1,14 +0,0 @@ -import { mustCall } from '../common/index.mjs'; -import * as fixtures from '../common/fixtures.mjs'; -import assert from 'node:assert'; -import { execPath } from 'node:process'; - -import spawn from './helper.spawnAsPromised.mjs'; - - -spawn(execPath, [fixtures.path('/es-modules/cjs.js')]) - .then(mustCall(({ code, signal, stdout }) => { - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - assert.strictEqual(stdout, 'executed\n'); - })); diff --git a/test/es-module/test-esm-encoded-path-native.js b/test/es-module/test-esm-encoded-path-native.js new file mode 100644 index 00000000000000..365f8afe5a3031 --- /dev/null +++ b/test/es-module/test-esm-encoded-path-native.js @@ -0,0 +1,22 @@ +'use strict'; + +const { mustCall } = require('../common'); +const fixtures = require('../common/fixtures.js'); +const assert = require('node:assert'); +const { execPath } = require('node:process'); +const { describe, it } = require('node:test'); + + +(async () => { + const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); + + describe('ESM: importing an encoded path', () => { + it('should throw', async () => { + const { code } = await spawn(execPath, [ + fixtures.path('es-module-url/native.mjs'), + ]); + + assert.strictEqual(code, 1); + }); + }); +})().then(mustCall()); diff --git a/test/es-module/test-esm-encoded-path-native.mjs b/test/es-module/test-esm-encoded-path-native.mjs deleted file mode 100644 index a8ef51dcb18813..00000000000000 --- a/test/es-module/test-esm-encoded-path-native.mjs +++ /dev/null @@ -1,12 +0,0 @@ -import { mustCall } from '../common/index.mjs'; -import * as fixtures from '../common/fixtures.mjs'; -import assert from 'node:assert'; -import { execPath } from 'node:process'; - -import spawn from './helper.spawnAsPromised.mjs'; - - -spawn(execPath, [fixtures.path('es-module-url/native.mjs')]) - .then(mustCall(({ code }) => { - assert.strictEqual(code, 1); - })); diff --git a/test/es-module/test-esm-experimental-warnings.mjs b/test/es-module/test-esm-experimental-warnings.mjs index e0be18d4390cbd..3a61f36b15e51f 100644 --- a/test/es-module/test-esm-experimental-warnings.mjs +++ b/test/es-module/test-esm-experimental-warnings.mjs @@ -1,18 +1,20 @@ -import { mustCall } from '../common/index.mjs'; +import '../common/index.mjs'; import { fileURL } from '../common/fixtures.mjs'; -import { doesNotMatch, match, strictEqual } from 'assert'; +import { doesNotMatch, match, strictEqual } from 'node:assert'; import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; import spawn from './helper.spawnAsPromised.mjs'; -// Verify no warnings are printed when no experimental features are enabled or used -spawn(execPath, [ - '--input-type=module', - '--eval', - `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`, -]) - .then(mustCall(({ code, signal, stderr }) => { +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 spawn(execPath, [ + '--input-type=module', + '--eval', + `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`, + ]); + doesNotMatch( stderr, /ExperimentalWarning/, @@ -20,26 +22,29 @@ spawn(execPath, [ ); strictEqual(code, 0); strictEqual(signal, null); - })); + }); + + 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(/\//g, '')}`, async () => { + const { code, signal, stderr } = await spawn(execPath, [ + arg, + '--input-type=module', + '--eval', + `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`, + ]); -// 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'], - ] -) { - spawn(execPath, [ - arg, - '--input-type=module', - '--eval', - `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`, - ]) - .then(mustCall(({ code, signal, stderr }) => { - match(stderr, /ExperimentalWarning/); - match(stderr, experiment); - strictEqual(code, 0); - strictEqual(signal, null); - })); -} + match(stderr, /ExperimentalWarning/); + match(stderr, experiment); + strictEqual(code, 0); + strictEqual(signal, null); + }); + } + }); +}); diff --git a/test/es-module/test-esm-export-not-found.mjs b/test/es-module/test-esm-export-not-found.mjs index 663de2d7fe71bc..e947138a378f61 100644 --- a/test/es-module/test-esm-export-not-found.mjs +++ b/test/es-module/test-esm-export-not-found.mjs @@ -1,7 +1,8 @@ -import { mustCall } from '../common/index.mjs'; +import '../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 spawn from './helper.spawnAsPromised.mjs'; @@ -12,21 +13,29 @@ const importStatementMultiline = `import { } from './module-named-exports.mjs'; `; -for ( - const input - of [ - importStatement, - importStatementMultiline, - ] -) { - spawn(execPath, [ - '--input-type=module', - '--eval', - input, - ], { - cwd: fixtures.path('es-module-loaders'), - }) - .then(mustCall(({ code, stderr, stdout }) => { +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 spawn(execPath, [ + '--input-type=module', + '--eval', + input, + ], { + cwd: fixtures.path('es-module-loaders'), + }); + assert.notStrictEqual(code, 0); // SyntaxError: The requested module './module-named-exports.mjs' @@ -35,5 +44,6 @@ for ( // The quotes ensure that the path starts with ./ and not ../ assert.match(stderr, /'\.\/module-named-exports\.mjs'/); assert.match(stderr, /notfound/); - })); -} + }); + } +}); diff --git a/test/es-module/test-esm-import-json-named-export.mjs b/test/es-module/test-esm-import-json-named-export.mjs index 83ac87b4647263..b3458b4decd1ed 100644 --- a/test/es-module/test-esm-import-json-named-export.mjs +++ b/test/es-module/test-esm-import-json-named-export.mjs @@ -1,15 +1,18 @@ -import { mustCall } from '../common/index.mjs'; +import '../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 spawn from './helper.spawnAsPromised.mjs'; -spawn(execPath, [ - fixtures.path('es-modules', 'import-json-named-export.mjs'), -]) - .then(mustCall(({ code, stderr }) => { +describe('ESM: named JSON exports', { concurrency: true }, () => { + it('should throw, citing named import', async () => { + const { code, stderr } = await spawn(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:/); @@ -17,4 +20,5 @@ spawn(execPath, [ assert.match(stderr, /'ofLife'/); assert.notStrictEqual(code, 0); - })); + }); +}); diff --git a/test/es-module/test-esm-initialization.mjs b/test/es-module/test-esm-initialization.mjs index ab756c7a3619e1..ab98bcf114b99b 100644 --- a/test/es-module/test-esm-initialization.mjs +++ b/test/es-module/test-esm-initialization.mjs @@ -1,30 +1,31 @@ import '../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'; +import spawn from './helper.spawnAsPromised.mjs'; -{ // 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 spawn(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); + }); +}); diff --git a/test/es-module/test-esm-invalid-extension.js b/test/es-module/test-esm-invalid-extension.js deleted file mode 100644 index cca7704f7994f0..00000000000000 --- a/test/es-module/test-esm-invalid-extension.js +++ /dev/null @@ -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)); diff --git a/test/es-module/test-esm-invalid-pjson.js b/test/es-module/test-esm-invalid-pjson.js new file mode 100644 index 00000000000000..b1c5fe6e346ef9 --- /dev/null +++ b/test/es-module/test-esm-invalid-pjson.js @@ -0,0 +1,32 @@ +'use strict'; + +const { checkoutEOL, mustCall } = require('../common'); +const fixtures = require('../common/fixtures.js'); +const assert = require('node:assert'); +const { execPath } = require('node:process'); +const { describe, it } = require('node:test'); + + +mustCall(async () => { + const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); + + 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 spawn(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); + }); + }); +})(); diff --git a/test/es-module/test-esm-invalid-pjson.mjs b/test/es-module/test-esm-invalid-pjson.mjs deleted file mode 100644 index 22a57b0058a70f..00000000000000 --- a/test/es-module/test-esm-invalid-pjson.mjs +++ /dev/null @@ -1,24 +0,0 @@ -import { checkoutEOL, mustCall } from '../common/index.mjs'; -import * as fixtures from '../common/fixtures.mjs'; -import assert from 'node:assert'; -import { execPath } from 'node:process'; - -import spawn from './helper.spawnAsPromised.mjs'; - - -const entry = fixtures.path('/es-modules/import-invalid-pjson.mjs'); -const invalidJson = fixtures.path('/node_modules/invalid-pjson/package.json'); - -spawn(execPath, [entry]) - .then(mustCall(({ code, signal, stderr }) => { - 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); - })); diff --git a/test/es-module/test-esm-json.mjs b/test/es-module/test-esm-json.mjs index 82c66cd215990c..a6569ed326e4d8 100644 --- a/test/es-module/test-esm-json.mjs +++ b/test/es-module/test-esm-json.mjs @@ -1,23 +1,26 @@ -import { mustCall } from '../common/index.mjs'; +import '../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' }; import spawn from './helper.spawnAsPromised.mjs'; -assert.strictEqual(secret.ofLife, 42); +describe('ESM: importing JSON', () => { + it('should load JSON', () => { + assert.strictEqual(secret.ofLife, 42); + }); -// Test warning message -spawn(execPath, [ - fixtures.path('/es-modules/json-modules.mjs'), -]) - .then(mustCall(({ code, signal, stderr }) => { - assert.ok(stderr.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 spawn(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); - })); + }); +}); diff --git a/test/es-module/test-esm-loader-chaining.mjs b/test/es-module/test-esm-loader-chaining.mjs index e50286a54bd7ba..6d1ad1c4a436f3 100644 --- a/test/es-module/test-esm-loader-chaining.mjs +++ b/test/es-module/test-esm-loader-chaining.mjs @@ -1,7 +1,8 @@ -import { mustCall } from '../common/index.mjs'; +import '../common/index.mjs'; import { fileURL } from '../common/fixtures.mjs'; import assert from 'node:assert'; import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; import spawn from './helper.spawnAsPromised.mjs'; @@ -17,420 +18,420 @@ const commonArgs = [ commonInput, ]; -// Verify unadulterated source is loaded when there are no loaders -spawn( - execPath, - [ - ...setupArgs, - 'import fs from "node:fs"; console.log(typeof fs?.constants?.F_OK )', - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { +describe('ESM: loader chaining', { concurrency: true }, () => { + it('should load unadulterated source when there are no loaders', async () => { + const { code, stderr, stdout } = await spawn( + 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(code, 0); - })); - -// Verify loaded source is properly different when only load changes something -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should load properly different source when only load changes something', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + '--loader', + 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(code, 0); - })); - -// Verify multiple changes from hooks result in proper output -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should result in proper output from multiple changes in resolve hooks', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + 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(code, 0); - })); - -// Verify modifying context within resolve chain is respected -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-receiving-modified-context.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-passing-modified-context.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should respect modified context within resolve chain', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-receiving-modified-context.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-passing-modified-context.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, + ); + assert.strictEqual(stderr, ''); assert.match(stdout, /bar/); assert.strictEqual(code, 0); - })); - -// Verify multiple changes from hooks result in proper output -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should result in proper output from multiple changes in resolve hooks', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), + '--loader', + 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(code, 0); - })); - -// Verify multiple calls to next within same loader receive correct "next" fn -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-multiple-next-calls.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should provide the correct "next" fn when multiple calls to next within same loader', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-multiple-next-calls.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, + ); + const countFoos = stdout.match(/resolve foo/g)?.length; assert.strictEqual(stderr, ''); assert.strictEqual(countFoos, 2); assert.strictEqual(code, 0); - })); - -// Verify next function's `name` is correct -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should use the correct `name` for next\'s function', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, + ); + assert.strictEqual(stderr, ''); assert.match(stdout, /next: nextResolve/); assert.strictEqual(code, 0); - })); - -// Verify error thrown for incomplete resolve chain, citing errant loader & hook -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw for incomplete resolve chain, citing errant loader & hook', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + 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); - })); - -// Verify error NOT thrown when nested resolve hook signaled a short circuit -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-next-modified.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should NOT throw when nested resolve hook signaled a short circuit', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-next-modified.mjs'), + '--loader', + 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); - })); - -// Verify error NOT thrown when nested load hook signaled a short circuit -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-next-modified.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should NOT throw when nested load hook signaled a short circuit', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-next-modified.mjs'), + ...commonArgs, + ], + { encoding: 'utf8' }, + ); + assert.strictEqual(stderr, ''); assert.match(stdout, /421/); assert.strictEqual(code, 0); - })); - -// Verify resolve chain does break and throws appropriately -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw when the resolve chain is broken', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), + '--loader', + 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); - })); - -// Verify error thrown for incomplete load chain, citing errant loader & hook -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-incomplete.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw for incomplete load chain, citing errant loader & hook', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-incomplete.mjs'), + '--loader', + 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); - })); - -// Verify load chain does break and throws appropriately -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-incomplete.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw when the load chain is broken', async () => { + const { code, stderr, stdout } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + 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); - })); - -// Verify error thrown when invalid `specifier` argument passed to `nextResolve` -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-bad-next-specifier.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw when invalid `specifier` argument passed to `nextResolve`', async () => { + const { code, stderr } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + 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/); - })); - -// Verify error thrown when resolve hook is invalid -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-null-return.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw when resolve hook is invalid', async () => { + const { code, stderr } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + 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/); - })); - -// Verify error thrown when invalid `context` argument passed to `nextResolve` -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-resolve-bad-next-context.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw when invalid `context` argument passed to `nextResolve`', async () => { + const { code, stderr } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + '--loader', + 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); - })); - -// Verify error thrown when load hook is invalid -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-null-return.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw when load hook is invalid', async () => { + const { code, stderr } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + 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/); - })); - -// Verify error thrown when invalid `url` argument passed to `nextLoad` -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-bad-next-url.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw when invalid `url` argument passed to `nextLoad`', async () => { + const { code, stderr } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + 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); - })); - -// Verify error thrown when invalid `url` argument passed to `nextLoad` -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-impersonating-next-url.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw when invalid `url` argument passed to `nextLoad`', async () => { + const { code, stderr } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + 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); - })); - -// Verify error thrown when invalid `context` argument passed to `nextLoad` -spawn( - execPath, - [ - '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), - '--loader', - fileURL('es-module-loaders', 'loader-load-bad-next-context.mjs'), - ...commonArgs, - ], - { encoding: 'utf8' }, -) - .then(mustCall(({ code, stderr, stdout }) => { + }); + + it('should throw when invalid `context` argument passed to `nextLoad`', async () => { + const { code, stderr } = await spawn( + execPath, + [ + '--loader', + fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + '--loader', + 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); - })); + }); +}); diff --git a/test/es-module/test-esm-loader-http-imports.mjs b/test/es-module/test-esm-loader-http-imports.mjs index 9741ef02de4a38..5dea8b81ff57f1 100644 --- a/test/es-module/test-esm-loader-http-imports.mjs +++ b/test/es-module/test-esm-loader-http-imports.mjs @@ -1,10 +1,11 @@ -import { mustCall } from '../common/index.mjs'; +import '../common/index.mjs'; import fixtures from '../common/fixtures.js'; 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'; import spawn from './helper.spawnAsPromised.mjs'; @@ -42,23 +43,31 @@ const { port, } = server.address(); -// Verify nested HTTP imports work -spawn( // ! `spawn` MUST be used (vs `spawnSync`) to avoid blocking the event loop - 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)`, - ] -) - .then(mustCall(({ code, signal, stderr, stdout }) => { +/** + * ! 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. + */ + +describe('ESM: http import via loader', () => { + it('should work', async () => { + // ! MUST NOT use spawnSync to avoid blocking the event loop + const { code, signal, stderr, stdout } = await spawn( + 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)`, + ] + ); + assert.strictEqual(stderr, ''); assert.strictEqual(stdout, '[Module: null prototype] { sum: [Function: sum] }\n'); assert.strictEqual(code, 0); assert.strictEqual(signal, null); - server.close(); - })); + server.close(); // ! This MUST come after the final test, but inside the async `it` function + }); +}); diff --git a/test/es-module/test-esm-loader-not-found.mjs b/test/es-module/test-esm-loader-not-found.mjs index 772349e02a4d77..a453cb476a59b8 100644 --- a/test/es-module/test-esm-loader-not-found.mjs +++ b/test/es-module/test-esm-loader-not-found.mjs @@ -1,23 +1,26 @@ -import { mustCall } from '../common/index.mjs'; +import '../common/index.mjs'; import * as fixtures from '../common/fixtures.mjs'; -import assert from 'assert'; -import { execPath } from 'process'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; import spawn from './helper.spawnAsPromised.mjs'; -spawn(execPath, [ - '--experimental-loader', - 'i-dont-exist', - fixtures.path('print-error-message.js'), -]) - .then(mustCall(({ code, stderr }) => { +describe('ESM: nonexistent loader', () => { + it('should throw', async () => { + const { code, stderr } = await spawn(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 + // 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')); - })); + }); +}); diff --git a/test/es-module/test-esm-loader-obsolete-hooks.mjs b/test/es-module/test-esm-loader-obsolete-hooks.mjs index eff4104fc265ae..dc0d1c2b754d96 100644 --- a/test/es-module/test-esm-loader-obsolete-hooks.mjs +++ b/test/es-module/test-esm-loader-obsolete-hooks.mjs @@ -1,30 +1,30 @@ -import { mustCall } from '../common/index.mjs'; +import '../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'), -]); +import spawn from './helper.spawnAsPromised.mjs'; -let stderr = ''; -child.stderr.setEncoding('utf8'); -child.stderr.on('data', (data) => { - stderr += data; -}); -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/); -})); +describe('ESM: deprecation warnings for obsolete hooks', { concurrency: true }, () => { + it(async () => { + const { code, stderr } = await spawn(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); + }); +}); diff --git a/test/es-module/test-esm-loader-thenable.mjs b/test/es-module/test-esm-loader-thenable.mjs index c8c3ec2778e7e9..3f18ea1a588306 100644 --- a/test/es-module/test-esm-loader-thenable.mjs +++ b/test/es-module/test-esm-loader-thenable.mjs @@ -1,65 +1,45 @@ -import { mustCall } from '../common/index.mjs'; +import '../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'), - ]); +import spawn from './helper.spawnAsPromised.mjs'; + + +describe('ESM: thenable loader hooks', { concurrency: true }, () => { + it('should behave as a normal promise resolution', async () => { + const { code, stderr } = await 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) => { 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'), - ]); + it('should crash the node process rejection with an error', async () => { + const { code, stderr } = await 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); - 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'), - ]); + it('should just reject without an error (but NOT crash the node process)', async () => { + const { code, stderr } = await 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) => { notStrictEqual(code, 0); - match(stderr, /\sundefined\r?\n/); - ok(!stderr.includes('must not call')); - })); -} + }); +}); diff --git a/test/es-module/test-esm-loader-with-syntax-error.mjs b/test/es-module/test-esm-loader-with-syntax-error.mjs index d973e72975e88f..39e6c48fed2ed4 100644 --- a/test/es-module/test-esm-loader-with-syntax-error.mjs +++ b/test/es-module/test-esm-loader-with-syntax-error.mjs @@ -1,24 +1,22 @@ -import { mustCall } from '../common/index.mjs'; +import '../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'), -]); +import spawn from './helper.spawnAsPromised.mjs'; -let stderr = ''; -child.stderr.setEncoding('utf8'); -child.stderr.on('data', (data) => { - stderr += data; -}); -child.on('close', mustCall((code, _signal) => { - notStrictEqual(code, 0); - match(stderr, /SyntaxError:/); +describe('ESM: loader with syntax error', { concurrency: true }, () => { + it('should crash the node process', async () => { + const { code, stderr } = await spawn(execPath, [ + '--experimental-loader', + fileURL('es-module-loaders', 'syntax-error.mjs').href, + path('print-error-message.js'), + ]); - ok(!stderr.includes('Bad command or file name')); -})); + match(stderr, /SyntaxError:/); + ok(!stderr.includes('Bad command or file name')); + notStrictEqual(code, 0); + }); +}); diff --git a/test/es-module/test-esm-module-not-found-commonjs-hint.mjs b/test/es-module/test-esm-module-not-found-commonjs-hint.mjs index 58f70d0b685391..ee7a9100270cd1 100644 --- a/test/es-module/test-esm-module-not-found-commonjs-hint.mjs +++ b/test/es-module/test-esm-module-not-found-commonjs-hint.mjs @@ -1,35 +1,36 @@ -import { mustCall } from '../common/index.mjs'; +import '../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, - }); +import spawn from './helper.spawnAsPromised.mjs'; + + +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 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); match(stderr, expected); - })); + notStrictEqual(code, 0); + }); }); diff --git a/test/es-module/test-esm-non-js.mjs b/test/es-module/test-esm-non-js.mjs index 749cd0b6132086..e0e9781c419da4 100644 --- a/test/es-module/test-esm-non-js.mjs +++ b/test/es-module/test-esm-non-js.mjs @@ -1,23 +1,21 @@ -import { mustCall } from '../common/index.mjs'; +import '../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'))}`, -]); +import spawn from './helper.spawnAsPromised.mjs'; -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 spawn(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/); -})); diff --git a/test/es-module/test-esm-nowarn-exports.mjs b/test/es-module/test-esm-nowarn-exports.mjs index 57d5bc58c72356..d9fdac01a13279 100644 --- a/test/es-module/test-esm-nowarn-exports.mjs +++ b/test/es-module/test-esm-nowarn-exports.mjs @@ -1,25 +1,21 @@ import '../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'), -]); +import spawn from './helper.spawnAsPromised.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 spawn(execPath, [ + '--experimental-import-meta-resolve', + path('es-modules/import-resolve-exports.mjs'), + ]); + + strictEqual(stderr, ''); + strictEqual(code, 0); + strictEqual(signal, null); + }); }); diff --git a/test/es-module/test-esm-repl-imports.js b/test/es-module/test-esm-repl-imports.js index d2b39e05fb0588..c81e1a1be51f2d 100644 --- a/test/es-module/test-esm-repl-imports.js +++ b/test/es-module/test-esm-repl-imports.js @@ -1,19 +1,27 @@ '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'), -}); -child.stdin.end( - 'try{require("#test");await import("#test")}catch{process.exit(-1)}' -); +describe('ESM: REPL runs', { concurrency: true }, () => { + it(() => { + const child = spawn(execPath, [ + '--interactive', + ], { + cwd: fixtures.path('es-modules', 'pkgimports'), + }); -child.on('exit', mustCall((code) => { - assert.strictEqual(code, 0); -})); + child.stdin.end( + 'try{require("#test");await import("#test")}catch{process.exit(-1)}' + ); + + child.on('exit', mustCall((code) => { + assert.strictEqual(code, 0); + })); + }); +}); diff --git a/test/es-module/test-esm-specifiers.mjs b/test/es-module/test-esm-specifiers.mjs index bc6125f5f94ad9..259c2734c2a8f2 100644 --- a/test/es-module/test-esm-specifiers.mjs +++ b/test/es-module/test-esm-specifiers.mjs @@ -1,62 +1,81 @@ -// 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'; - -// 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'); - -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'); - } -} - -main().catch(mustNotCall); - -// 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); - }); +import '../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'; + +import spawn from './helper.spawnAsPromised.mjs'; + + +describe('ESM: specifier-resolution=node', { concurrency: true }, () => { + it(async () => { + const { code, stderr, stdout } = await spawn(execPath, [ + '--no-warnings', + '--experimental-specifier-resolution=node', + '--input-type=module', + '--eval', + [ + 'import { strictEqual } from "node:assert";', + // commonJS index.js + `import commonjs from "${fixtures.path('es-module-specifiers/package-type-commonjs')}";`, + // esm index.js + `import module from "${fixtures.path('es-module-specifiers/package-type-module')}";`, + // Notice the trailing slash + `import success, { explicit, implicit, implicitModule } from "${fixtures.path('es-module-specifiers/')}";`, + 'strictEqual(commonjs, "commonjs");', + 'strictEqual(module, "module");', + 'strictEqual(success, "success");', + 'strictEqual(explicit, "esm");', + 'strictEqual(implicit, "cjs");', + 'strictEqual(implicitModule, "cjs");', + ].join('\n'), + ]); + + strictEqual(stderr, ''); + strictEqual(stdout, ''); + strictEqual(code, 0); + }); + + it('should throw when the file doesn\'t exist', async () => { + const { code, stderr, stdout } = await spawn(execPath, [ + '--no-warnings', + fixtures.path('es-module-specifiers/do-not-exist.js'), + ]); + + 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 spawn(execPath, [ + '--no-warnings', + '--experimental-specifier-resolution=node', + '--input-type=module', + '--eval', + `import whatever from "${fixtures.path('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 spawn(execPath, [ + '--no-warnings', + '--experimental-specifier-resolution=node', + '--es-module-specifier-resolution=node', + fixtures.path('es-module-specifiers', item), + ]); + + strictEqual(code, 0); }); }); diff --git a/test/es-module/test-esm-syntax-error.mjs b/test/es-module/test-esm-syntax-error.mjs index a8c019171717dd..60b3b5c744c0a3 100644 --- a/test/es-module/test-esm-syntax-error.mjs +++ b/test/es-module/test-esm-syntax-error.mjs @@ -1,19 +1,18 @@ -import { mustCall } from '../common/index.mjs'; +import '../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'), -]); +import spawn from './helper.spawnAsPromised.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 spawn(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:/); -})); diff --git a/test/es-module/test-esm-tla-unfinished.mjs b/test/es-module/test-esm-tla-unfinished.mjs index a7b6e620d0620a..687976cb4e9bbf 100644 --- a/test/es-module/test-esm-tla-unfinished.mjs +++ b/test/es-module/test-esm-tla-unfinished.mjs @@ -1,7 +1,11 @@ import '../common/index.mjs'; -import assert from 'assert'; -import child_process from 'child_process'; import fixtures from '../common/fixtures.js'; +import assert from 'node:assert'; +import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; + +import spawn from './helper.spawnAsPromised.mjs'; + const commonArgs = [ '--no-warnings', @@ -9,102 +13,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, '', '']); -} - -{ - // 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/); -} - -{ - // Unresolved TLA promise with explicit exit code, --eval - const { status, stdout, stderr } = child_process.spawnSync( - process.execPath, - [ +describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { + it('should exit for an unsettled TLA promise via --eval', async () => { + const { code, stderr, stdout } = await spawn(execPath, [ + ...commonArgs, + 'await new Promise(() => {})', + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 13); + }); + + it('should throw for a rejected TLA promise via --eval', async () => { + // Rejected TLA promise, --eval + const { code, stderr, stdout } = await spawn(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 spawn(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 spawn(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, '', '']); -} - -{ - // 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/); -} - -{ - // 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, '', '']); -} - -{ - // 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/); -} - -{ - // 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, '', '']); -} - -{ - // 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, '', '']); -} + ]); + + assert.match(stderr, /Error: Xyz/); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 1); + }); + + it('should exit for an unsettled TLA promise via stdin', async () => { + const { code, stderr, stdout } = await spawn(execPath, [ + '--no-warnings', + fixtures.path('es-modules/tla/unresolved.mjs'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 13); + }); + + it('should throw for a rejected TLA promise via stdin', async () => { + const { code, stderr, stdout } = await spawn(execPath, [ + '--no-warnings', + fixtures.path('es-modules/tla/rejected.mjs'), + ]); + + 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 stdin', async () => { + const { code, stderr, stdout } = await spawn(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 spawn(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 spawn(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 spawn(execPath, [ + '--no-warnings', + fixtures.path('es-modules/tla/unresolved-with-worker-process-exit.mjs'), + ]); + + assert.strictEqual(stderr, ''); + assert.strictEqual(stdout, ''); + assert.strictEqual(code, 13); + }); +}); diff --git a/test/es-module/test-esm-unknown-or-no-extension.js b/test/es-module/test-esm-unknown-or-no-extension.js index 40f840ad670cf3..60f50152764022 100644 --- a/test/es-module/test-esm-unknown-or-no-extension.js +++ b/test/es-module/test-esm-unknown-or-no-extension.js @@ -1,40 +1,40 @@ 'use strict'; -const common = require('../common'); -const fixtures = require('../common/fixtures'); -const { spawn } = require('child_process'); -const assert = require('assert'); +const { mustCall } = 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`. -[ - '/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')); +(async () => { + const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); + + // 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 spawn(execPath, [entry]); + + 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')); + } + }); } - })); -}); + }); +})().then(mustCall()); diff --git a/test/es-module/test-esm-wasm.mjs b/test/es-module/test-esm-wasm.mjs index 01717c47714f6a..ddfd061c037dde 100644 --- a/test/es-module/test-esm-wasm.mjs +++ b/test/es-module/test-esm-wasm.mjs @@ -1,37 +1,45 @@ -// 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 { strictEqual, match } from 'node:assert'; +import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; -strictEqual(state, 'WASM Start Executed'); +import spawn from './helper.spawnAsPromised.mjs'; -strictEqual(add(10, 20), 30); -strictEqual(addImported(0), 42); +describe('ESM: WASM modules', { concurrency: true }, () => { + it('should load exports', async () => { + const { code, stderr, stdout } = await spawn(execPath, [ + '--no-warnings', + '--experimental-wasm-modules', + '--input-type=module', + '--eval', + [ + 'import { strictEqual, match } from "node:assert";', + `import { add, addImported } from "${path('es-modules/simple.wasm')}";`, + `import { state } from "${path('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(state, 'WASM JS Function Executed'); + strictEqual(stderr, ''); + strictEqual(stdout, ''); + strictEqual(code, 0); + }); -strictEqual(addImported(1), 43); + it('should emit experimental warning', async () => { + const { code, signal, stderr } = await spawn(execPath, [ + '--experimental-wasm-modules', + path('/es-modules/wasm-modules.mjs'), + ]); -// 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/); + }); }); diff --git a/test/es-module/test-http-imports-cli.mjs b/test/es-module/test-http-imports-cli.mjs index 67cefd69ddd889..699ec58d1e6499 100644 --- a/test/es-module/test-http-imports-cli.mjs +++ b/test/es-module/test-http-imports-cli.mjs @@ -1,48 +1,50 @@ import { mustCall } from '../common/index.mjs'; -import { match, notStrictEqual } from 'assert'; -import { spawn } from 'child_process'; -import { execPath } from 'process'; - -{ - 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) => { +import { match, notStrictEqual } from 'node:assert'; +import { spawn as spawnAsync } from 'node:child_process'; +import { execPath } from 'node:process'; +import { describe, it } from 'node:test'; + +import spawn from './helper.spawnAsPromised.mjs'; + + +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 spawn(execPath, [ + '--experimental-network-imports', + '--input-type=module', + '--eval', + `import "${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, new RegExp(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 "${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]/); + match(stderr, new RegExp(disallowedSpecifier)); + })); + }); +}); From a53214b193343597ae88f7bb5e9d79c44dbbf8fc Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Tue, 26 Jul 2022 20:19:36 +0200 Subject: [PATCH 03/14] move `spawnAsPromised` to test/common as `spawnPromisified` --- test/common/index.js | 33 ++++++- test/common/index.mjs | 6 +- test/es-module/helper.spawnAsPromised.mjs | 33 ------- test/es-module/test-cjs-esm-warn.js | 93 +++++++++---------- test/es-module/test-esm-cjs-builtins.js | 20 ++-- test/es-module/test-esm-cjs-exports.js | 38 ++++---- .../test-esm-cjs-load-error-note.mjs | 8 +- test/es-module/test-esm-cjs-main.js | 24 ++--- .../es-module/test-esm-encoded-path-native.js | 20 ++-- .../test-esm-experimental-warnings.mjs | 8 +- test/es-module/test-esm-export-not-found.mjs | 5 +- .../test-esm-import-json-named-export.mjs | 6 +- test/es-module/test-esm-initialization.mjs | 6 +- test/es-module/test-esm-invalid-pjson.js | 38 ++++---- test/es-module/test-esm-json.mjs | 5 +- test/es-module/test-esm-loader-chaining.mjs | 44 +++++---- .../test-esm-loader-http-imports.mjs | 6 +- test/es-module/test-esm-loader-not-found.mjs | 6 +- .../test-esm-loader-obsolete-hooks.mjs | 6 +- test/es-module/test-esm-loader-thenable.mjs | 10 +- .../test-esm-loader-with-syntax-error.mjs | 6 +- ...est-esm-module-not-found-commonjs-hint.mjs | 6 +- test/es-module/test-esm-non-js.mjs | 5 +- test/es-module/test-esm-nowarn-exports.mjs | 6 +- .../test-esm-preserve-symlinks-main.js | 18 ++-- test/es-module/test-esm-specifiers.mjs | 12 +-- test/es-module/test-esm-syntax-error.mjs | 6 +- test/es-module/test-esm-tla-unfinished.mjs | 24 +++-- .../test-esm-unknown-or-no-extension.js | 58 ++++++------ test/es-module/test-esm-wasm.mjs | 8 +- test/es-module/test-http-imports-cli.mjs | 6 +- 31 files changed, 253 insertions(+), 317 deletions(-) delete mode 100644 test/es-module/helper.spawnAsPromised.mjs diff --git a/test/common/index.js b/test/common/index.js index e14fbe59d1946b..428c841c8b892a 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -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, spawnSync, spawn: spawnAsync } = 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 = spawnAsync(...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 */ diff --git a/test/common/index.mjs b/test/common/index.mjs index 772d81135c7ef9..2b30f499343cc4 100644 --- a/test/common/index.mjs +++ b/test/common/index.mjs @@ -48,7 +48,8 @@ const { getArrayBufferViews, getBufferSources, getTTYfd, - runWithInvalidFD + runWithInvalidFD, + spawnPromisified, } = common; export { @@ -97,5 +98,6 @@ export { getBufferSources, getTTYfd, runWithInvalidFD, - createRequire + createRequire, + spawnPromisified, }; diff --git a/test/es-module/helper.spawnAsPromised.mjs b/test/es-module/helper.spawnAsPromised.mjs deleted file mode 100644 index 3d3308a4d04fcb..00000000000000 --- a/test/es-module/helper.spawnAsPromised.mjs +++ /dev/null @@ -1,33 +0,0 @@ -import '../common/index.mjs'; -import cp from 'node:child_process'; - - -export default function spawn(...args) { - let stderr = ''; - let stdout = ''; - - const child = cp.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, - }); - }); - }); -} diff --git a/test/es-module/test-cjs-esm-warn.js b/test/es-module/test-cjs-esm-warn.js index 5e49e779b0d912..c1d60a209502bb 100644 --- a/test/es-module/test-cjs-esm-warn.js +++ b/test/es-module/test-cjs-esm-warn.js @@ -1,6 +1,6 @@ 'use strict'; -const { mustCall } = require('../common'); +const { spawnPromisified } = require('../common'); const fixtures = require('../common/fixtures.js'); const assert = require('node:assert'); const path = require('node:path'); @@ -14,58 +14,55 @@ const pjson = path.resolve( fixtures.path('/es-modules/package-type-module/package.json') ); -(async () => { - const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); - describe('CJS ↔︎ ESM interop warnings', { concurrency: true }, () => { +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 spawn(execPath, [requiringCjsAsEsm]); + 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.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.strictEqual(code, 1); + assert.strictEqual(signal, null); + }); - it(async () => { - const required = path.resolve( - fixtures.path('/es-modules/package-type-module/esm.js') - ); - const basename = 'esm.js'; - const { code, signal, stderr } = await spawn(execPath, [requiringEsm]); + 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.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.strictEqual(code, 1); + assert.strictEqual(signal, null); }); -})().then(mustCall()); +}); diff --git a/test/es-module/test-esm-cjs-builtins.js b/test/es-module/test-esm-cjs-builtins.js index 416d279af0c093..c49abfd8c93222 100644 --- a/test/es-module/test-esm-cjs-builtins.js +++ b/test/es-module/test-esm-cjs-builtins.js @@ -1,6 +1,6 @@ 'use strict'; -const { mustCall } = require('../common'); +const { spawnPromisified } = require('../common'); const fixtures = require('../common/fixtures.js'); const assert = require('node:assert'); const { execPath } = require('node:process'); @@ -9,16 +9,12 @@ const { describe, it } = require('node:test'); const entry = fixtures.path('/es-modules/builtin-imports-case.mjs'); -(async () => { - const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); +describe('ESM: importing builtins & CJS', () => { + it('should work', async () => { + const { code, signal, stdout } = await spawnPromisified(execPath, [entry]); - describe('ESM: importing builtins & CJS', () => { - it('should work', async () => { - const { code, signal, stdout } = await spawn(execPath, [entry]); - - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - assert.strictEqual(stdout, 'ok\n'); - }); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(stdout, 'ok\n'); }); -})().then(mustCall()); +}); diff --git a/test/es-module/test-esm-cjs-exports.js b/test/es-module/test-esm-cjs-exports.js index 16d94dfcc7f389..4a5a9ffceecc2a 100644 --- a/test/es-module/test-esm-cjs-exports.js +++ b/test/es-module/test-esm-cjs-exports.js @@ -1,33 +1,29 @@ 'use strict'; -const { mustCall } = require('../common'); +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'); -(async () => { - const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); +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]); - 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 spawn(execPath, [validEntry]); - - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - assert.strictEqual(stdout, 'ok\n'); - }); + 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 spawn(execPath, [invalidEntry]); + 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\'')); - }); + 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\'')); }); -})().then(mustCall()); +}); diff --git a/test/es-module/test-esm-cjs-load-error-note.mjs b/test/es-module/test-esm-cjs-load-error-note.mjs index 63ad3cd3eb781b..1413c263927081 100644 --- a/test/es-module/test-esm-cjs-load-error-note.mjs +++ b/test/es-module/test-esm-cjs-load-error-note.mjs @@ -1,11 +1,9 @@ -import '../common/index.mjs'; +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 spawn from './helper.spawnAsPromised.mjs'; - // Expect note to be included in the error output const expectedNote = 'To load an ES module, ' + @@ -21,7 +19,7 @@ const mustNotIncludeMessage = { includeNote: false, }; -describe('ESM: ', { concurrently: true }, () => { +describe('ESM: Errors for unexpected exports', { concurrently: true }, () => { for ( const { errorNeedle, filePath, getMessage, includeNote } of [ @@ -82,7 +80,7 @@ describe('ESM: ', { concurrently: true }, () => { ] ) { it(`should ${includeNote ? '' : 'NOT'} include note`, async () => { - const { code, stderr } = await spawn(execPath, [filePath]); + const { code, stderr } = await spawnPromisified(execPath, [filePath]); assert.strictEqual(code, 1); diff --git a/test/es-module/test-esm-cjs-main.js b/test/es-module/test-esm-cjs-main.js index 0d71100dbf597c..bb209648356d10 100644 --- a/test/es-module/test-esm-cjs-main.js +++ b/test/es-module/test-esm-cjs-main.js @@ -1,24 +1,20 @@ 'use strict'; -const { mustCall } = require('../common'); +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'); -(async () => { - const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); +describe('ESM: importing CJS', () => { + it('should work', async () => { + const { code, signal, stdout } = await spawnPromisified(execPath, [ + fixtures.path('/es-modules/cjs.js'), + ]); - describe('ESM: importing CJS', () => { - it('should work', async () => { - const { code, signal, stdout } = await spawn(execPath, [ - fixtures.path('/es-modules/cjs.js'), - ]); - - assert.strictEqual(code, 0); - assert.strictEqual(signal, null); - assert.strictEqual(stdout, 'executed\n'); - }); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(stdout, 'executed\n'); }); -})().then(mustCall()); +}); diff --git a/test/es-module/test-esm-encoded-path-native.js b/test/es-module/test-esm-encoded-path-native.js index 365f8afe5a3031..7574e55278bd1f 100644 --- a/test/es-module/test-esm-encoded-path-native.js +++ b/test/es-module/test-esm-encoded-path-native.js @@ -1,22 +1,18 @@ 'use strict'; -const { mustCall } = require('../common'); +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'); -(async () => { - const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); +describe('ESM: importing an encoded path', () => { + it('should throw', async () => { + const { code } = await spawnPromisified(execPath, [ + fixtures.path('es-module-url/native.mjs'), + ]); - describe('ESM: importing an encoded path', () => { - it('should throw', async () => { - const { code } = await spawn(execPath, [ - fixtures.path('es-module-url/native.mjs'), - ]); - - assert.strictEqual(code, 1); - }); + assert.strictEqual(code, 1); }); -})().then(mustCall()); +}); diff --git a/test/es-module/test-esm-experimental-warnings.mjs b/test/es-module/test-esm-experimental-warnings.mjs index 3a61f36b15e51f..6a501a041ca657 100644 --- a/test/es-module/test-esm-experimental-warnings.mjs +++ b/test/es-module/test-esm-experimental-warnings.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { fileURL } from '../common/fixtures.mjs'; import { doesNotMatch, match, strictEqual } from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - 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 spawn(execPath, [ + const { code, signal, stderr } = await spawnPromisified(execPath, [ '--input-type=module', '--eval', `import ${JSON.stringify(fileURL('es-module-loaders', 'module-named-exports.mjs'))}`, @@ -33,7 +31,7 @@ describe('ESM: warn for obsolete hooks provided', { concurrency: true }, () => { ] ) { it(`should print for ${experiment.toString().replaceAll(/\//g, '')}`, async () => { - const { code, signal, stderr } = await spawn(execPath, [ + const { code, signal, stderr } = await spawnPromisified(execPath, [ arg, '--input-type=module', '--eval', diff --git a/test/es-module/test-esm-export-not-found.mjs b/test/es-module/test-esm-export-not-found.mjs index e947138a378f61..48ccd0f910227f 100644 --- a/test/es-module/test-esm-export-not-found.mjs +++ b/test/es-module/test-esm-export-not-found.mjs @@ -1,10 +1,9 @@ -import '../common/index.mjs'; +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 spawn from './helper.spawnAsPromised.mjs'; const importStatement = 'import { foo, notfound } from \'./module-named-exports.mjs\';'; const importStatementMultiline = `import { @@ -28,7 +27,7 @@ describe('ESM: nonexistent exports', { concurrency: true }, () => { ] ) { it(`should throw for nonexistent exports via ${name}`, async () => { - const { code, stderr } = await spawn(execPath, [ + const { code, stderr } = await spawnPromisified(execPath, [ '--input-type=module', '--eval', input, diff --git a/test/es-module/test-esm-import-json-named-export.mjs b/test/es-module/test-esm-import-json-named-export.mjs index b3458b4decd1ed..c8a4ad8dce3e5e 100644 --- a/test/es-module/test-esm-import-json-named-export.mjs +++ b/test/es-module/test-esm-import-json-named-export.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +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 spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: named JSON exports', { concurrency: true }, () => { it('should throw, citing named import', async () => { - const { code, stderr } = await spawn(execPath, [ + const { code, stderr } = await spawnPromisified(execPath, [ fixtures.path('es-modules', 'import-json-named-export.mjs'), ]); diff --git a/test/es-module/test-esm-initialization.mjs b/test/es-module/test-esm-initialization.mjs index ab98bcf114b99b..2bfd16135a0189 100644 --- a/test/es-module/test-esm-initialization.mjs +++ b/test/es-module/test-esm-initialization.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +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 spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: ensure initialisation happens only once', { concurrency: true }, () => { it(async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--loader', fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--no-warnings', diff --git a/test/es-module/test-esm-invalid-pjson.js b/test/es-module/test-esm-invalid-pjson.js index b1c5fe6e346ef9..f3a38018637aa3 100644 --- a/test/es-module/test-esm-invalid-pjson.js +++ b/test/es-module/test-esm-invalid-pjson.js @@ -1,32 +1,28 @@ 'use strict'; -const { checkoutEOL, mustCall } = require('../common'); +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'); -mustCall(async () => { - const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); +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'); - 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]); - const { code, signal, stderr } = await spawn(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); - }); + 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); }); -})(); +}); diff --git a/test/es-module/test-esm-json.mjs b/test/es-module/test-esm-json.mjs index a6569ed326e4d8..14c86bac80af98 100644 --- a/test/es-module/test-esm-json.mjs +++ b/test/es-module/test-esm-json.mjs @@ -1,11 +1,10 @@ -import '../common/index.mjs'; +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' }; -import spawn from './helper.spawnAsPromised.mjs'; describe('ESM: importing JSON', () => { @@ -14,7 +13,7 @@ describe('ESM: importing JSON', () => { }); it('should print an experimental warning', async () => { - const { code, signal, stderr } = await spawn(execPath, [ + const { code, signal, stderr } = await spawnPromisified(execPath, [ fixtures.path('/es-modules/json-modules.mjs'), ]); diff --git a/test/es-module/test-esm-loader-chaining.mjs b/test/es-module/test-esm-loader-chaining.mjs index 6d1ad1c4a436f3..a5301ab72658ef 100644 --- a/test/es-module/test-esm-loader-chaining.mjs +++ b/test/es-module/test-esm-loader-chaining.mjs @@ -1,11 +1,9 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { fileURL } from '../common/fixtures.mjs'; import assert from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - const setupArgs = [ '--no-warnings', @@ -20,7 +18,7 @@ const commonArgs = [ describe('ESM: loader chaining', { concurrency: true }, () => { it('should load unadulterated source when there are no loaders', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ ...setupArgs, @@ -35,7 +33,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should load properly different source when only load changes something', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -57,7 +55,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should result in proper output from multiple changes in resolve hooks', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -80,7 +78,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should respect modified context within resolve chain', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -104,7 +102,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should result in proper output from multiple changes in resolve hooks', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -127,7 +125,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should provide the correct "next" fn when multiple calls to next within same loader', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -151,7 +149,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should use the correct `name` for next\'s function', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -171,7 +169,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw for incomplete resolve chain, citing errant loader & hook', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -192,7 +190,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should NOT throw when nested resolve hook signaled a short circuit', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -212,7 +210,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should NOT throw when nested load hook signaled a short circuit', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -234,7 +232,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw when the resolve chain is broken', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -256,7 +254,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw for incomplete load chain, citing errant loader & hook', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -278,7 +276,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw when the load chain is broken', async () => { - const { code, stderr, stdout } = await spawn( + const { code, stderr, stdout } = await spawnPromisified( execPath, [ '--loader', @@ -300,7 +298,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw when invalid `specifier` argument passed to `nextResolve`', async () => { - const { code, stderr } = await spawn( + const { code, stderr } = await spawnPromisified( execPath, [ '--loader', @@ -319,7 +317,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw when resolve hook is invalid', async () => { - const { code, stderr } = await spawn( + const { code, stderr } = await spawnPromisified( execPath, [ '--loader', @@ -340,7 +338,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw when invalid `context` argument passed to `nextResolve`', async () => { - const { code, stderr } = await spawn( + const { code, stderr } = await spawnPromisified( execPath, [ '--loader', @@ -359,7 +357,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw when load hook is invalid', async () => { - const { code, stderr } = await spawn( + const { code, stderr } = await spawnPromisified( execPath, [ '--loader', @@ -380,7 +378,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw when invalid `url` argument passed to `nextLoad`', async () => { - const { code, stderr } = await spawn( + const { code, stderr } = await spawnPromisified( execPath, [ '--loader', @@ -399,7 +397,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw when invalid `url` argument passed to `nextLoad`', async () => { - const { code, stderr } = await spawn( + const { code, stderr } = await spawnPromisified( execPath, [ '--loader', @@ -418,7 +416,7 @@ describe('ESM: loader chaining', { concurrency: true }, () => { }); it('should throw when invalid `context` argument passed to `nextLoad`', async () => { - const { code, stderr } = await spawn( + const { code, stderr } = await spawnPromisified( execPath, [ '--loader', diff --git a/test/es-module/test-esm-loader-http-imports.mjs b/test/es-module/test-esm-loader-http-imports.mjs index 5dea8b81ff57f1..b1bf12e4fef98a 100644 --- a/test/es-module/test-esm-loader-http-imports.mjs +++ b/test/es-module/test-esm-loader-http-imports.mjs @@ -1,4 +1,4 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import fixtures from '../common/fixtures.js'; import assert from 'node:assert'; import http from 'node:http'; @@ -7,8 +7,6 @@ import { execPath } from 'node:process'; import { promisify } from 'node:util'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - const files = { 'main.mjs': 'export * from "./lib.mjs";', @@ -51,7 +49,7 @@ const { describe('ESM: http import via loader', () => { it('should work', async () => { // ! MUST NOT use spawnSync to avoid blocking the event loop - const { code, signal, stderr, stdout } = await spawn( + const { code, signal, stderr, stdout } = await spawnPromisified( execPath, [ '--no-warnings', diff --git a/test/es-module/test-esm-loader-not-found.mjs b/test/es-module/test-esm-loader-not-found.mjs index a453cb476a59b8..2abaf3078d113d 100644 --- a/test/es-module/test-esm-loader-not-found.mjs +++ b/test/es-module/test-esm-loader-not-found.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +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 spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: nonexistent loader', () => { it('should throw', async () => { - const { code, stderr } = await spawn(execPath, [ + const { code, stderr } = await spawnPromisified(execPath, [ '--experimental-loader', 'i-dont-exist', fixtures.path('print-error-message.js'), diff --git a/test/es-module/test-esm-loader-obsolete-hooks.mjs b/test/es-module/test-esm-loader-obsolete-hooks.mjs index dc0d1c2b754d96..fa0baef8a216b7 100644 --- a/test/es-module/test-esm-loader-obsolete-hooks.mjs +++ b/test/es-module/test-esm-loader-obsolete-hooks.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { fileURL, path } from '../common/fixtures.mjs'; import { match, notStrictEqual } from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: deprecation warnings for obsolete hooks', { concurrency: true }, () => { it(async () => { - const { code, stderr } = await spawn(execPath, [ + const { code, stderr } = await spawnPromisified(execPath, [ '--no-warnings', '--throw-deprecation', '--experimental-loader', diff --git a/test/es-module/test-esm-loader-thenable.mjs b/test/es-module/test-esm-loader-thenable.mjs index 3f18ea1a588306..5e802b8393bcd4 100644 --- a/test/es-module/test-esm-loader-thenable.mjs +++ b/test/es-module/test-esm-loader-thenable.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { fileURL, path } from '../common/fixtures.mjs'; import { match, ok, notStrictEqual, strictEqual } from 'assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: thenable loader hooks', { concurrency: true }, () => { it('should behave as a normal promise resolution', async () => { - const { code, stderr } = await spawn(execPath, [ + const { code, stderr } = await spawnPromisified(execPath, [ '--experimental-loader', fileURL('es-module-loaders', 'thenable-load-hook.mjs').href, path('es-modules', 'test-esm-ok.mjs'), @@ -20,7 +18,7 @@ describe('ESM: thenable loader hooks', { concurrency: true }, () => { }); it('should crash the node process rejection with an error', async () => { - const { code, stderr } = await spawn(execPath, [ + 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'), @@ -32,7 +30,7 @@ describe('ESM: thenable loader hooks', { concurrency: true }, () => { }); it('should just reject without an error (but NOT crash the node process)', async () => { - const { code, stderr } = await spawn(execPath, [ + 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'), diff --git a/test/es-module/test-esm-loader-with-syntax-error.mjs b/test/es-module/test-esm-loader-with-syntax-error.mjs index 39e6c48fed2ed4..0ed995ad510ee7 100644 --- a/test/es-module/test-esm-loader-with-syntax-error.mjs +++ b/test/es-module/test-esm-loader-with-syntax-error.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { fileURL, path } from '../common/fixtures.mjs'; import { match, ok, notStrictEqual } from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: loader with syntax error', { concurrency: true }, () => { it('should crash the node process', async () => { - const { code, stderr } = await spawn(execPath, [ + const { code, stderr } = await spawnPromisified(execPath, [ '--experimental-loader', fileURL('es-module-loaders', 'syntax-error.mjs').href, path('print-error-message.js'), diff --git a/test/es-module/test-esm-module-not-found-commonjs-hint.mjs b/test/es-module/test-esm-module-not-found-commonjs-hint.mjs index ee7a9100270cd1..51633564f81458 100644 --- a/test/es-module/test-esm-module-not-found-commonjs-hint.mjs +++ b/test/es-module/test-esm-module-not-found-commonjs-hint.mjs @@ -1,11 +1,9 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { fixturesDir } from '../common/fixtures.mjs'; import { match, notStrictEqual } from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: module not found hint', { concurrency: true }, () => { for ( @@ -22,7 +20,7 @@ describe('ESM: module not found hint', { concurrency: true }, () => { }, ] ) it('should cite a variant form', async () => { - const { code, stderr } = await spawn(execPath, [ + const { code, stderr } = await spawnPromisified(execPath, [ '--input-type=module', '--eval', input, diff --git a/test/es-module/test-esm-non-js.mjs b/test/es-module/test-esm-non-js.mjs index e0e9781c419da4..2630d3136a42ba 100644 --- a/test/es-module/test-esm-non-js.mjs +++ b/test/es-module/test-esm-non-js.mjs @@ -1,14 +1,13 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { fileURL } from '../common/fixtures.mjs'; import { match, strictEqual } from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; describe('ESM: non-js extensions fail', { concurrency: true }, () => { it(async () => { - const { code, stderr, signal } = await spawn(execPath, [ + const { code, stderr, signal } = await spawnPromisified(execPath, [ '--input-type=module', '--eval', `import ${JSON.stringify(fileURL('es-modules', 'file.unknown'))}`, diff --git a/test/es-module/test-esm-nowarn-exports.mjs b/test/es-module/test-esm-nowarn-exports.mjs index d9fdac01a13279..695e924e03ccbe 100644 --- a/test/es-module/test-esm-nowarn-exports.mjs +++ b/test/es-module/test-esm-nowarn-exports.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { path } from '../common/fixtures.mjs'; import { strictEqual } from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: experiemental warning for import.meta.resolve', { concurrency: true }, () => { it('should not warn when caught', async () => { - const { code, signal, stderr } = await spawn(execPath, [ + const { code, signal, stderr } = await spawnPromisified(execPath, [ '--experimental-import-meta-resolve', path('es-modules/import-resolve-exports.mjs'), ]); diff --git a/test/es-module/test-esm-preserve-symlinks-main.js b/test/es-module/test-esm-preserve-symlinks-main.js index b8fb301e02d85b..6f921f656fe22f 100644 --- a/test/es-module/test-esm-preserve-symlinks-main.js +++ b/test/es-module/test-esm-preserve-symlinks-main.js @@ -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 diff --git a/test/es-module/test-esm-specifiers.mjs b/test/es-module/test-esm-specifiers.mjs index 259c2734c2a8f2..8c1f38ec664b6a 100644 --- a/test/es-module/test-esm-specifiers.mjs +++ b/test/es-module/test-esm-specifiers.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +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'; -import spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: specifier-resolution=node', { concurrency: true }, () => { it(async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', '--experimental-specifier-resolution=node', '--input-type=module', @@ -37,7 +35,7 @@ describe('ESM: specifier-resolution=node', { concurrency: true }, () => { }); it('should throw when the file doesn\'t exist', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', fixtures.path('es-module-specifiers/do-not-exist.js'), ]); @@ -48,7 +46,7 @@ describe('ESM: specifier-resolution=node', { concurrency: true }, () => { }); it('should throw when the omitted file extension is .mjs (legacy loader doesn\'t support it)', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', '--experimental-specifier-resolution=node', '--input-type=module', @@ -69,7 +67,7 @@ describe('ESM: specifier-resolution=node', { concurrency: true }, () => { '/index', ] ) it('should ', async () => { - const { code } = await spawn(execPath, [ + const { code } = await spawnPromisified(execPath, [ '--no-warnings', '--experimental-specifier-resolution=node', '--es-module-specifier-resolution=node', diff --git a/test/es-module/test-esm-syntax-error.mjs b/test/es-module/test-esm-syntax-error.mjs index 60b3b5c744c0a3..de87187b069441 100644 --- a/test/es-module/test-esm-syntax-error.mjs +++ b/test/es-module/test-esm-syntax-error.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { path } from '../common/fixtures.mjs'; import { match, notStrictEqual } from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: importing a module with syntax error(s)', { concurrency: true }, () => { it('should throw', async () => { - const { code, stderr } = await spawn(execPath, [ + const { code, stderr } = await spawnPromisified(execPath, [ path('es-module-loaders', 'syntax-error.mjs'), ]); match(stderr, /SyntaxError:/); diff --git a/test/es-module/test-esm-tla-unfinished.mjs b/test/es-module/test-esm-tla-unfinished.mjs index 687976cb4e9bbf..48bc4d77f42b4e 100644 --- a/test/es-module/test-esm-tla-unfinished.mjs +++ b/test/es-module/test-esm-tla-unfinished.mjs @@ -1,11 +1,9 @@ -import '../common/index.mjs'; +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'; -import spawn from './helper.spawnAsPromised.mjs'; - const commonArgs = [ '--no-warnings', @@ -15,7 +13,7 @@ const commonArgs = [ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { it('should exit for an unsettled TLA promise via --eval', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ ...commonArgs, 'await new Promise(() => {})', ]); @@ -27,7 +25,7 @@ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { it('should throw for a rejected TLA promise via --eval', async () => { // Rejected TLA promise, --eval - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ ...commonArgs, 'await Promise.reject(new Error("Xyz"))', ]); @@ -39,7 +37,7 @@ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { 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 spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ ...commonArgs, 'process.exitCode = 42;await new Promise(() => {})', ]); @@ -51,7 +49,7 @@ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { 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 spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ ...commonArgs, 'process.exitCode = 42;await Promise.reject(new Error("Xyz"))', ]); @@ -62,7 +60,7 @@ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { }); it('should exit for an unsettled TLA promise via stdin', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', fixtures.path('es-modules/tla/unresolved.mjs'), ]); @@ -73,7 +71,7 @@ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { }); it('should throw for a rejected TLA promise via stdin', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', fixtures.path('es-modules/tla/rejected.mjs'), ]); @@ -84,7 +82,7 @@ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { }); it('should exit for an unsettled TLA promise and respect explicit exit code via stdin', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', fixtures.path('es-modules/tla/unresolved-withexitcode.mjs'), ]); @@ -95,7 +93,7 @@ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { }); it('should throw for a rejected TLA promise and ignore explicit exit code via stdin', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', fixtures.path('es-modules/tla/rejected-withexitcode.mjs'), ]); @@ -106,7 +104,7 @@ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { }); it('should exit successfully when calling `process.exit()` in `.mjs` file', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', fixtures.path('es-modules/tla/process-exit.mjs'), ]); @@ -117,7 +115,7 @@ describe('ESM: unsettled and rejected promises', { concurrency: true }, () => { }); it('should be unaffected by `process.exit()` in worker thread', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', fixtures.path('es-modules/tla/unresolved-with-worker-process-exit.mjs'), ]); diff --git a/test/es-module/test-esm-unknown-or-no-extension.js b/test/es-module/test-esm-unknown-or-no-extension.js index 60f50152764022..3f0660e5aa9225 100644 --- a/test/es-module/test-esm-unknown-or-no-extension.js +++ b/test/es-module/test-esm-unknown-or-no-extension.js @@ -1,40 +1,36 @@ 'use strict'; -const { mustCall } = require('../common'); +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'); -(async () => { - const { default: spawn } = await import('./helper.spawnAsPromised.mjs'); +// 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]); - // 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 spawn(execPath, [entry]); - - 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')); - } - }); - } - }); -})().then(mustCall()); + 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')); + } + }); + } +}); diff --git a/test/es-module/test-esm-wasm.mjs b/test/es-module/test-esm-wasm.mjs index ddfd061c037dde..8c58485b09127a 100644 --- a/test/es-module/test-esm-wasm.mjs +++ b/test/es-module/test-esm-wasm.mjs @@ -1,15 +1,13 @@ -import '../common/index.mjs'; +import { spawnPromisified } from '../common/index.mjs'; import { path } from '../common/fixtures.mjs'; import { strictEqual, match } from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - describe('ESM: WASM modules', { concurrency: true }, () => { it('should load exports', async () => { - const { code, stderr, stdout } = await spawn(execPath, [ + const { code, stderr, stdout } = await spawnPromisified(execPath, [ '--no-warnings', '--experimental-wasm-modules', '--input-type=module', @@ -32,7 +30,7 @@ describe('ESM: WASM modules', { concurrency: true }, () => { }); it('should emit experimental warning', async () => { - const { code, signal, stderr } = await spawn(execPath, [ + const { code, signal, stderr } = await spawnPromisified(execPath, [ '--experimental-wasm-modules', path('/es-modules/wasm-modules.mjs'), ]); diff --git a/test/es-module/test-http-imports-cli.mjs b/test/es-module/test-http-imports-cli.mjs index 699ec58d1e6499..e180b5eddeb978 100644 --- a/test/es-module/test-http-imports-cli.mjs +++ b/test/es-module/test-http-imports-cli.mjs @@ -1,17 +1,15 @@ -import { mustCall } from '../common/index.mjs'; +import { mustCall, spawnPromisified } from '../common/index.mjs'; import { match, notStrictEqual } from 'node:assert'; import { spawn as spawnAsync } from 'node:child_process'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -import spawn from './helper.spawnAsPromised.mjs'; - 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 spawn(execPath, [ + const { code, stderr } = await spawnPromisified(execPath, [ '--experimental-network-imports', '--input-type=module', '--eval', From e9fcef035fc9d2051202fb816e22fbfe5098c435 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Tue, 26 Jul 2022 20:28:23 +0200 Subject: [PATCH 04/14] tidy shouldIncludeNote --- test/es-module/test-esm-cjs-load-error-note.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/es-module/test-esm-cjs-load-error-note.mjs b/test/es-module/test-esm-cjs-load-error-note.mjs index 1413c263927081..42910ed46547b2 100644 --- a/test/es-module/test-esm-cjs-load-error-note.mjs +++ b/test/es-module/test-esm-cjs-load-error-note.mjs @@ -84,11 +84,11 @@ describe('ESM: Errors for unexpected exports', { concurrently: true }, () => { assert.strictEqual(code, 1); - if (errorNeedle) stderr.includes(errorNeedle); + if (errorNeedle) assert.match(stderr, new RegExp(errorNeedle)); - const includesNote = stderr.includes(expectedNote); + const shouldIncludeNote = stderr.includes(expectedNote); assert.ok( - includeNote ? includesNote : !includesNote, + includeNote ? shouldIncludeNote : !shouldIncludeNote, `${filePath} ${getMessage(stderr)}`, ); }); From 41980ee7b2d1232dd2160bcb5d7d6378deed8de3 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Tue, 26 Jul 2022 20:30:15 +0200 Subject: [PATCH 05/14] =?UTF-8?q?replaceAll=20regex=20=E2=86=92=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/es-module/test-esm-experimental-warnings.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/es-module/test-esm-experimental-warnings.mjs b/test/es-module/test-esm-experimental-warnings.mjs index 6a501a041ca657..fc167c63584b87 100644 --- a/test/es-module/test-esm-experimental-warnings.mjs +++ b/test/es-module/test-esm-experimental-warnings.mjs @@ -30,7 +30,7 @@ describe('ESM: warn for obsolete hooks provided', { concurrency: true }, () => { [/specifier resolution/, '--experimental-specifier-resolution=node'], ] ) { - it(`should print for ${experiment.toString().replaceAll(/\//g, '')}`, async () => { + it(`should print for ${experiment.toString().replaceAll('/', '')}`, async () => { const { code, signal, stderr } = await spawnPromisified(execPath, [ arg, '--input-type=module', From d7a25417c506959f0a2dcdc21d82a16c2b09ddf6 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Tue, 26 Jul 2022 20:31:51 +0200 Subject: [PATCH 06/14] REPL done() --- test/es-module/test-esm-repl-imports.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/es-module/test-esm-repl-imports.js b/test/es-module/test-esm-repl-imports.js index c81e1a1be51f2d..9547824756f5ec 100644 --- a/test/es-module/test-esm-repl-imports.js +++ b/test/es-module/test-esm-repl-imports.js @@ -9,7 +9,7 @@ const { describe, it } = require('node:test'); describe('ESM: REPL runs', { concurrency: true }, () => { - it(() => { + it((context, done) => { const child = spawn(execPath, [ '--interactive', ], { @@ -22,6 +22,7 @@ describe('ESM: REPL runs', { concurrency: true }, () => { child.on('exit', mustCall((code) => { assert.strictEqual(code, 0); + done(); })); }); }); From 3d02b2f08a81ce657b0b3fd15333c15a65424a21 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 27 Jul 2022 08:42:59 +0200 Subject: [PATCH 07/14] =?UTF-8?q?`spawnAsync`=20=E2=86=92=20`spawn`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/common/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/common/index.js b/test/common/index.js index 428c841c8b892a..9ba2fd9cd9edb5 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -24,7 +24,7 @@ const process = global.process; // Some tests tamper with the process global. const assert = require('assert'); -const { exec, execSync, spawnSync, spawn: spawnAsync } = 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. @@ -846,7 +846,7 @@ function spawnPromisified(...args) { let stderr = ''; let stdout = ''; - const child = spawnAsync(...args); + const child = spawn(...args); child.stderr.setEncoding('utf8'); child.stderr.on('data', (data) => { stderr += data; }); child.stdout.setEncoding('utf8'); From aa67d37f948d8704b339bd4baaf43bba61eb7d68 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Wed, 27 Jul 2022 02:44:15 -0400 Subject: [PATCH 08/14] =?UTF-8?q?`concurrently`=20=E2=86=92=20`concurrency?= =?UTF-8?q?`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Moshe Atlow --- test/es-module/test-esm-cjs-load-error-note.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/es-module/test-esm-cjs-load-error-note.mjs b/test/es-module/test-esm-cjs-load-error-note.mjs index 42910ed46547b2..c499daf8592041 100644 --- a/test/es-module/test-esm-cjs-load-error-note.mjs +++ b/test/es-module/test-esm-cjs-load-error-note.mjs @@ -19,7 +19,7 @@ const mustNotIncludeMessage = { includeNote: false, }; -describe('ESM: Errors for unexpected exports', { concurrently: true }, () => { +describe('ESM: Errors for unexpected exports', { concurrency: true }, () => { for ( const { errorNeedle, filePath, getMessage, includeNote } of [ From d9c320fae5c9d01837ac7e02e48257749a568e2c Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:37:12 +0200 Subject: [PATCH 09/14] strings to regexes --- test/es-module/test-esm-cjs-load-error-note.mjs | 10 +++++----- test/es-module/test-http-imports-cli.mjs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/es-module/test-esm-cjs-load-error-note.mjs b/test/es-module/test-esm-cjs-load-error-note.mjs index 42910ed46547b2..3c0b647caf049c 100644 --- a/test/es-module/test-esm-cjs-load-error-note.mjs +++ b/test/es-module/test-esm-cjs-load-error-note.mjs @@ -57,25 +57,25 @@ describe('ESM: Errors for unexpected exports', { concurrently: true }, () => { // name: '', filePath: fixtures.path('/es-modules/es-note-error-1.mjs'), ...mustNotIncludeMessage, - errorNeedle: 'Error: some error', + errorNeedle: /Error: some error/, }, { // name: '', filePath: fixtures.path('/es-modules/es-note-error-2.mjs'), ...mustNotIncludeMessage, - errorNeedle: 'string', + errorNeedle: /string/, }, { // name: '', filePath: fixtures.path('/es-modules/es-note-error-3.mjs'), ...mustNotIncludeMessage, - errorNeedle: 'null', + errorNeedle: /null/, }, { // name: '', filePath: fixtures.path('/es-modules/es-note-error-4.mjs'), ...mustNotIncludeMessage, - errorNeedle: 'undefined', + errorNeedle: /undefined/, }, ] ) { @@ -84,7 +84,7 @@ describe('ESM: Errors for unexpected exports', { concurrently: true }, () => { assert.strictEqual(code, 1); - if (errorNeedle) assert.match(stderr, new RegExp(errorNeedle)); + if (errorNeedle != null) assert.match(stderr, errorNeedle); const shouldIncludeNote = stderr.includes(expectedNote); assert.ok( diff --git a/test/es-module/test-http-imports-cli.mjs b/test/es-module/test-http-imports-cli.mjs index e180b5eddeb978..627fc8adad8150 100644 --- a/test/es-module/test-http-imports-cli.mjs +++ b/test/es-module/test-http-imports-cli.mjs @@ -1,5 +1,5 @@ import { mustCall, spawnPromisified } from '../common/index.mjs'; -import { match, notStrictEqual } from 'node:assert'; +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'; @@ -21,8 +21,8 @@ describe('ESM: http import via CLI', { concurrency: true }, () => { // [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]/); - match(stderr, new RegExp(disallowedSpecifier)); + match(stderr, /\[ERR_NETWORK_IMPORT_DISALLOWED\]/); + ok(stderr.includes(disallowedSpecifier)); }); it('should throw disallowed error for insecure protocol in REPL', () => { @@ -41,8 +41,8 @@ describe('ESM: http import via CLI', { concurrency: true }, () => { // [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]/); - match(stderr, new RegExp(disallowedSpecifier)); + match(stderr, /\[ERR_NETWORK_IMPORT_DISALLOWED\]/); + ok(stderr.includes(disallowedSpecifier)); })); }); }); From 120cc6ad44d7928d3bdfe06cf9e339bbe7a60721 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:37:45 +0200 Subject: [PATCH 10/14] fileURLs --- test/es-module/test-esm-loader-chaining.mjs | 114 ++++++++++---------- test/es-module/test-esm-wasm.mjs | 8 +- test/es-module/test-http-imports-cli.mjs | 2 +- 3 files changed, 62 insertions(+), 62 deletions(-) diff --git a/test/es-module/test-esm-loader-chaining.mjs b/test/es-module/test-esm-loader-chaining.mjs index a5301ab72658ef..14303cb5c42665 100644 --- a/test/es-module/test-esm-loader-chaining.mjs +++ b/test/es-module/test-esm-loader-chaining.mjs @@ -1,5 +1,5 @@ import { spawnPromisified } from '../common/index.mjs'; -import { fileURL } from '../common/fixtures.mjs'; +import * as fixtures from '../common/fixtures.mjs'; import assert from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; @@ -37,11 +37,11 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -59,13 +59,13 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -82,15 +82,15 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-receiving-modified-context.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-receiving-modified-context.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-passing-modified-context.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-passing-modified-context.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -106,13 +106,13 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -129,13 +129,13 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-foo.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-multiple-next-calls.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-multiple-next-calls.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -153,11 +153,11 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -173,11 +173,11 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -194,11 +194,11 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-next-modified.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-next-modified.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -214,13 +214,13 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-shortcircuit.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-42.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-next-modified.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-next-modified.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -236,11 +236,11 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-incomplete.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-foo-or-42.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -258,11 +258,11 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-incomplete.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-incomplete.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -280,11 +280,11 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-incomplete.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-incomplete.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -302,9 +302,9 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-bad-next-specifier.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-bad-next-specifier.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -321,9 +321,9 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-null-return.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-null-return.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -342,9 +342,9 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-resolve-bad-next-context.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-resolve-bad-next-context.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -361,9 +361,9 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-null-return.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-null-return.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -382,9 +382,9 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-bad-next-url.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-bad-next-url.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -401,9 +401,9 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-impersonating-next-url.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-impersonating-next-url.mjs'), ...commonArgs, ], { encoding: 'utf8' }, @@ -420,9 +420,9 @@ describe('ESM: loader chaining', { concurrency: true }, () => { execPath, [ '--loader', - fileURL('es-module-loaders', 'loader-load-passthru.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-passthru.mjs'), '--loader', - fileURL('es-module-loaders', 'loader-load-bad-next-context.mjs'), + fixtures.fileURL('es-module-loaders', 'loader-load-bad-next-context.mjs'), ...commonArgs, ], { encoding: 'utf8' }, diff --git a/test/es-module/test-esm-wasm.mjs b/test/es-module/test-esm-wasm.mjs index 8c58485b09127a..fac1d4b2837df0 100644 --- a/test/es-module/test-esm-wasm.mjs +++ b/test/es-module/test-esm-wasm.mjs @@ -1,5 +1,5 @@ import { spawnPromisified } from '../common/index.mjs'; -import { path } from '../common/fixtures.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'; @@ -14,8 +14,8 @@ describe('ESM: WASM modules', { concurrency: true }, () => { '--eval', [ 'import { strictEqual, match } from "node:assert";', - `import { add, addImported } from "${path('es-modules/simple.wasm')}";`, - `import { state } from "${path('es-modules/wasm-dep.mjs')}";`, + `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);', @@ -32,7 +32,7 @@ describe('ESM: WASM modules', { concurrency: true }, () => { it('should emit experimental warning', async () => { const { code, signal, stderr } = await spawnPromisified(execPath, [ '--experimental-wasm-modules', - path('/es-modules/wasm-modules.mjs'), + fixtures.path('es-modules/wasm-modules.mjs'), ]); strictEqual(code, 0); diff --git a/test/es-module/test-http-imports-cli.mjs b/test/es-module/test-http-imports-cli.mjs index 627fc8adad8150..f9227bdf8dd642 100644 --- a/test/es-module/test-http-imports-cli.mjs +++ b/test/es-module/test-http-imports-cli.mjs @@ -13,7 +13,7 @@ describe('ESM: http import via CLI', { concurrency: true }, () => { '--experimental-network-imports', '--input-type=module', '--eval', - `import "${disallowedSpecifier}"`, + `import ${JSON.stringify(disallowedSpecifier)}`, ]); notStrictEqual(code, 0); From 5e4db682e179cc20ca0ddee7d1b6eedcfbd18aa6 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:38:18 +0200 Subject: [PATCH 11/14] explicitly disable `concurrency` for `test-esm-loader-http-imports.mjs` --- test/es-module/test-esm-loader-http-imports.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/es-module/test-esm-loader-http-imports.mjs b/test/es-module/test-esm-loader-http-imports.mjs index b1bf12e4fef98a..ad42829f5d1cee 100644 --- a/test/es-module/test-esm-loader-http-imports.mjs +++ b/test/es-module/test-esm-loader-http-imports.mjs @@ -46,7 +46,7 @@ const { * ! `afterAll` teardown in which to close the server. */ -describe('ESM: http import via loader', () => { +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( From a5897d520880b38ab60c4ea6c51cc5717551b58b Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 28 Jul 2022 09:40:37 +0200 Subject: [PATCH 12/14] . --- test/es-module/test-http-imports-cli.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/es-module/test-http-imports-cli.mjs b/test/es-module/test-http-imports-cli.mjs index f9227bdf8dd642..1605de2f10c487 100644 --- a/test/es-module/test-http-imports-cli.mjs +++ b/test/es-module/test-http-imports-cli.mjs @@ -30,7 +30,7 @@ describe('ESM: http import via CLI', { concurrency: true }, () => { '--experimental-network-imports', '--input-type=module', ]); - child.stdin.end(`import "${disallowedSpecifier}"`); + child.stdin.end(`import ${JSON.stringify(disallowedSpecifier)}`); let stderr = ''; child.stderr.setEncoding('utf8'); From 11c0019e804ec0839a5f1a200936e0afbeac4d28 Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 28 Jul 2022 23:50:14 +0200 Subject: [PATCH 13/14] windows path BS --- test/es-module/test-esm-specifiers.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/es-module/test-esm-specifiers.mjs b/test/es-module/test-esm-specifiers.mjs index 8c1f38ec664b6a..670cd93c9b0b28 100644 --- a/test/es-module/test-esm-specifiers.mjs +++ b/test/es-module/test-esm-specifiers.mjs @@ -15,11 +15,11 @@ describe('ESM: specifier-resolution=node', { concurrency: true }, () => { [ 'import { strictEqual } from "node:assert";', // commonJS index.js - `import commonjs from "${fixtures.path('es-module-specifiers/package-type-commonjs')}";`, + `import commonjs from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-commonjs'))};`, // esm index.js - `import module from "${fixtures.path('es-module-specifiers/package-type-module')}";`, + `import module from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/package-type-module'))};`, // Notice the trailing slash - `import success, { explicit, implicit, implicitModule } from "${fixtures.path('es-module-specifiers/')}";`, + `import success, { explicit, implicit, implicitModule } from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/'))};`, 'strictEqual(commonjs, "commonjs");', 'strictEqual(module, "module");', 'strictEqual(success, "success");', @@ -51,7 +51,7 @@ describe('ESM: specifier-resolution=node', { concurrency: true }, () => { '--experimental-specifier-resolution=node', '--input-type=module', '--eval', - `import whatever from "${fixtures.path('es-module-specifiers/implicit-main-type-commonjs')}";`, + `import whatever from ${JSON.stringify(fixtures.fileURL('es-module-specifiers/implicit-main-type-commonjs'))};`, ]); match(stderr, /ERR_MODULE_NOT_FOUND/); From 64bf3336e9196944bd6b24018864df39e51905dd Mon Sep 17 00:00:00 2001 From: Jacob Smith <3012099+JakobJingleheimer@users.noreply.github.com> Date: Thu, 28 Jul 2022 23:50:41 +0200 Subject: [PATCH 14/14] remove superfluous characters from err match --- test/es-module/test-http-imports-cli.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/es-module/test-http-imports-cli.mjs b/test/es-module/test-http-imports-cli.mjs index 1605de2f10c487..7deb31a288c7f7 100644 --- a/test/es-module/test-http-imports-cli.mjs +++ b/test/es-module/test-http-imports-cli.mjs @@ -21,7 +21,7 @@ describe('ESM: http import via CLI', { concurrency: true }, () => { // [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\]/); + match(stderr, /ERR_NETWORK_IMPORT_DISALLOWED/); ok(stderr.includes(disallowedSpecifier)); });