11cb0ef41Sopenharmony_ciimport { spawnPromisified } from '../common/index.mjs'; 21cb0ef41Sopenharmony_ciimport * as fixtures from '../common/fixtures.mjs'; 31cb0ef41Sopenharmony_ciimport assert from 'node:assert'; 41cb0ef41Sopenharmony_ciimport { execPath } from 'node:process'; 51cb0ef41Sopenharmony_ciimport { describe, it } from 'node:test'; 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_cidescribe('Loader hooks throwing errors', { concurrency: true }, () => { 81cb0ef41Sopenharmony_ci it('throws on nonexistent modules', async () => { 91cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 101cb0ef41Sopenharmony_ci '--no-warnings', 111cb0ef41Sopenharmony_ci '--experimental-loader', 121cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 131cb0ef41Sopenharmony_ci '--input-type=module', 141cb0ef41Sopenharmony_ci '--eval', 151cb0ef41Sopenharmony_ci 'import "nonexistent/file.mjs"', 161cb0ef41Sopenharmony_ci ]); 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci assert.match(stderr, /ERR_MODULE_NOT_FOUND/); 191cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 201cb0ef41Sopenharmony_ci assert.strictEqual(code, 1); 211cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 221cb0ef41Sopenharmony_ci }); 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci it('throws on unknown extensions', async () => { 251cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 261cb0ef41Sopenharmony_ci '--no-warnings', 271cb0ef41Sopenharmony_ci '--experimental-loader', 281cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 291cb0ef41Sopenharmony_ci '--input-type=module', 301cb0ef41Sopenharmony_ci '--eval', 311cb0ef41Sopenharmony_ci `import ${JSON.stringify(fixtures.fileURL('/es-modules/file.unknown'))}`, 321cb0ef41Sopenharmony_ci ]); 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci assert.match(stderr, /ERR_UNKNOWN_FILE_EXTENSION/); 351cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 361cb0ef41Sopenharmony_ci assert.strictEqual(code, 1); 371cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 381cb0ef41Sopenharmony_ci }); 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci it('throws on invalid return values', async () => { 411cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 421cb0ef41Sopenharmony_ci '--no-warnings', 431cb0ef41Sopenharmony_ci '--experimental-loader', 441cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 451cb0ef41Sopenharmony_ci '--input-type=module', 461cb0ef41Sopenharmony_ci '--eval', 471cb0ef41Sopenharmony_ci 'import "esmHook/badReturnVal.mjs"', 481cb0ef41Sopenharmony_ci ]); 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci assert.match(stderr, /ERR_INVALID_RETURN_VALUE/); 511cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 521cb0ef41Sopenharmony_ci assert.strictEqual(code, 1); 531cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 541cb0ef41Sopenharmony_ci }); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci it('throws on boolean false', async () => { 571cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 581cb0ef41Sopenharmony_ci '--no-warnings', 591cb0ef41Sopenharmony_ci '--experimental-loader', 601cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 611cb0ef41Sopenharmony_ci '--input-type=module', 621cb0ef41Sopenharmony_ci '--eval', 631cb0ef41Sopenharmony_ci 'import "esmHook/format.false"', 641cb0ef41Sopenharmony_ci ]); 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci assert.match(stderr, /ERR_INVALID_RETURN_PROPERTY_VALUE/); 671cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 681cb0ef41Sopenharmony_ci assert.strictEqual(code, 1); 691cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 701cb0ef41Sopenharmony_ci }); 711cb0ef41Sopenharmony_ci it('throws on boolean true', async () => { 721cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 731cb0ef41Sopenharmony_ci '--no-warnings', 741cb0ef41Sopenharmony_ci '--experimental-loader', 751cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 761cb0ef41Sopenharmony_ci '--input-type=module', 771cb0ef41Sopenharmony_ci '--eval', 781cb0ef41Sopenharmony_ci 'import "esmHook/format.true"', 791cb0ef41Sopenharmony_ci ]); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci assert.match(stderr, /ERR_INVALID_RETURN_PROPERTY_VALUE/); 821cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 831cb0ef41Sopenharmony_ci assert.strictEqual(code, 1); 841cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 851cb0ef41Sopenharmony_ci }); 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci it('throws on invalid returned object', async () => { 881cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 891cb0ef41Sopenharmony_ci '--no-warnings', 901cb0ef41Sopenharmony_ci '--experimental-loader', 911cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 921cb0ef41Sopenharmony_ci '--input-type=module', 931cb0ef41Sopenharmony_ci '--eval', 941cb0ef41Sopenharmony_ci 'import "esmHook/badReturnFormatVal.mjs"', 951cb0ef41Sopenharmony_ci ]); 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci assert.match(stderr, /ERR_INVALID_RETURN_PROPERTY_VALUE/); 981cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 991cb0ef41Sopenharmony_ci assert.strictEqual(code, 1); 1001cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 1011cb0ef41Sopenharmony_ci }); 1021cb0ef41Sopenharmony_ci 1031cb0ef41Sopenharmony_ci it('throws on unsupported format', async () => { 1041cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 1051cb0ef41Sopenharmony_ci '--no-warnings', 1061cb0ef41Sopenharmony_ci '--experimental-loader', 1071cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 1081cb0ef41Sopenharmony_ci '--input-type=module', 1091cb0ef41Sopenharmony_ci '--eval', 1101cb0ef41Sopenharmony_ci 'import "esmHook/unsupportedReturnFormatVal.mjs"', 1111cb0ef41Sopenharmony_ci ]); 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci assert.match(stderr, /ERR_UNKNOWN_MODULE_FORMAT/); 1141cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 1151cb0ef41Sopenharmony_ci assert.strictEqual(code, 1); 1161cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 1171cb0ef41Sopenharmony_ci }); 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci it('throws on invalid format property type', async () => { 1201cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 1211cb0ef41Sopenharmony_ci '--no-warnings', 1221cb0ef41Sopenharmony_ci '--experimental-loader', 1231cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 1241cb0ef41Sopenharmony_ci '--input-type=module', 1251cb0ef41Sopenharmony_ci '--eval', 1261cb0ef41Sopenharmony_ci 'import "esmHook/badReturnSourceVal.mjs"', 1271cb0ef41Sopenharmony_ci ]); 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci assert.match(stderr, /ERR_INVALID_RETURN_PROPERTY_VALUE/); 1301cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 1311cb0ef41Sopenharmony_ci assert.strictEqual(code, 1); 1321cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 1331cb0ef41Sopenharmony_ci }); 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci it('rejects dynamic imports for all of the error cases checked above', async () => { 1361cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 1371cb0ef41Sopenharmony_ci '--no-warnings', 1381cb0ef41Sopenharmony_ci '--experimental-loader', 1391cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 1401cb0ef41Sopenharmony_ci '--input-type=module', 1411cb0ef41Sopenharmony_ci '--eval', 1421cb0ef41Sopenharmony_ci `import assert from 'node:assert'; 1431cb0ef41Sopenharmony_ci await Promise.allSettled([ 1441cb0ef41Sopenharmony_ci import('nonexistent/file.mjs'), 1451cb0ef41Sopenharmony_ci import(${JSON.stringify(fixtures.fileURL('/es-modules/file.unknown'))}), 1461cb0ef41Sopenharmony_ci import('esmHook/badReturnVal.mjs'), 1471cb0ef41Sopenharmony_ci import('esmHook/format.false'), 1481cb0ef41Sopenharmony_ci import('esmHook/format.true'), 1491cb0ef41Sopenharmony_ci import('esmHook/badReturnFormatVal.mjs'), 1501cb0ef41Sopenharmony_ci import('esmHook/unsupportedReturnFormatVal.mjs'), 1511cb0ef41Sopenharmony_ci import('esmHook/badReturnSourceVal.mjs'), 1521cb0ef41Sopenharmony_ci ]).then((results) => { 1531cb0ef41Sopenharmony_ci assert.strictEqual(results.every((result) => result.status === 'rejected'), true); 1541cb0ef41Sopenharmony_ci })`, 1551cb0ef41Sopenharmony_ci ]); 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci assert.strictEqual(stderr, ''); 1581cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 1591cb0ef41Sopenharmony_ci assert.strictEqual(code, 0); 1601cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 1611cb0ef41Sopenharmony_ci }); 1621cb0ef41Sopenharmony_ci}); 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_cidescribe('Loader hooks parsing modules', { concurrency: true }, () => { 1651cb0ef41Sopenharmony_ci it('can parse .js files as ESM', async () => { 1661cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 1671cb0ef41Sopenharmony_ci '--no-warnings', 1681cb0ef41Sopenharmony_ci '--experimental-loader', 1691cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 1701cb0ef41Sopenharmony_ci '--input-type=module', 1711cb0ef41Sopenharmony_ci '--eval', 1721cb0ef41Sopenharmony_ci `import assert from 'node:assert'; 1731cb0ef41Sopenharmony_ci await import(${JSON.stringify(fixtures.fileURL('/es-module-loaders/js-as-esm.js'))}) 1741cb0ef41Sopenharmony_ci .then((parsedModule) => { 1751cb0ef41Sopenharmony_ci assert.strictEqual(typeof parsedModule, 'object'); 1761cb0ef41Sopenharmony_ci assert.strictEqual(parsedModule.namedExport, 'named-export'); 1771cb0ef41Sopenharmony_ci })`, 1781cb0ef41Sopenharmony_ci ]); 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci assert.strictEqual(stderr, ''); 1811cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 1821cb0ef41Sopenharmony_ci assert.strictEqual(code, 0); 1831cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 1841cb0ef41Sopenharmony_ci }); 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci it('can define .ext files as ESM', async () => { 1871cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 1881cb0ef41Sopenharmony_ci '--no-warnings', 1891cb0ef41Sopenharmony_ci '--experimental-loader', 1901cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 1911cb0ef41Sopenharmony_ci '--input-type=module', 1921cb0ef41Sopenharmony_ci '--eval', 1931cb0ef41Sopenharmony_ci `import assert from 'node:assert'; 1941cb0ef41Sopenharmony_ci await import(${JSON.stringify(fixtures.fileURL('/es-modules/file.ext'))}) 1951cb0ef41Sopenharmony_ci .then((parsedModule) => { 1961cb0ef41Sopenharmony_ci assert.strictEqual(typeof parsedModule, 'object'); 1971cb0ef41Sopenharmony_ci const { default: defaultExport } = parsedModule; 1981cb0ef41Sopenharmony_ci assert.strictEqual(typeof defaultExport, 'function'); 1991cb0ef41Sopenharmony_ci assert.strictEqual(defaultExport.name, 'iAmReal'); 2001cb0ef41Sopenharmony_ci assert.strictEqual(defaultExport(), true); 2011cb0ef41Sopenharmony_ci })`, 2021cb0ef41Sopenharmony_ci ]); 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci assert.strictEqual(stderr, ''); 2051cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 2061cb0ef41Sopenharmony_ci assert.strictEqual(code, 0); 2071cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 2081cb0ef41Sopenharmony_ci }); 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci it('can predetermine the format in the custom loader resolve hook', async () => { 2111cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 2121cb0ef41Sopenharmony_ci '--no-warnings', 2131cb0ef41Sopenharmony_ci '--experimental-loader', 2141cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 2151cb0ef41Sopenharmony_ci '--input-type=module', 2161cb0ef41Sopenharmony_ci '--eval', 2171cb0ef41Sopenharmony_ci `import assert from 'node:assert'; 2181cb0ef41Sopenharmony_ci await import('esmHook/preknownFormat.pre') 2191cb0ef41Sopenharmony_ci .then((parsedModule) => { 2201cb0ef41Sopenharmony_ci assert.strictEqual(typeof parsedModule, 'object'); 2211cb0ef41Sopenharmony_ci assert.strictEqual(parsedModule.default, 'hello world'); 2221cb0ef41Sopenharmony_ci })`, 2231cb0ef41Sopenharmony_ci ]); 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci assert.strictEqual(stderr, ''); 2261cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 2271cb0ef41Sopenharmony_ci assert.strictEqual(code, 0); 2281cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 2291cb0ef41Sopenharmony_ci }); 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_ci it('can provide source for a nonexistent file', async () => { 2321cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 2331cb0ef41Sopenharmony_ci '--no-warnings', 2341cb0ef41Sopenharmony_ci '--experimental-loader', 2351cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 2361cb0ef41Sopenharmony_ci '--input-type=module', 2371cb0ef41Sopenharmony_ci '--eval', 2381cb0ef41Sopenharmony_ci `import assert from 'node:assert'; 2391cb0ef41Sopenharmony_ci await import('esmHook/virtual.mjs') 2401cb0ef41Sopenharmony_ci .then((parsedModule) => { 2411cb0ef41Sopenharmony_ci assert.strictEqual(typeof parsedModule, 'object'); 2421cb0ef41Sopenharmony_ci assert.strictEqual(typeof parsedModule.default, 'undefined'); 2431cb0ef41Sopenharmony_ci assert.strictEqual(parsedModule.message, 'WOOHOO!'); 2441cb0ef41Sopenharmony_ci })`, 2451cb0ef41Sopenharmony_ci ]); 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci assert.strictEqual(stderr, ''); 2481cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 2491cb0ef41Sopenharmony_ci assert.strictEqual(code, 0); 2501cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 2511cb0ef41Sopenharmony_ci }); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci it('ensures that loaders have a separate context from userland', async () => { 2541cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 2551cb0ef41Sopenharmony_ci '--no-warnings', 2561cb0ef41Sopenharmony_ci '--experimental-loader', 2571cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/hooks-custom.mjs'), 2581cb0ef41Sopenharmony_ci '--input-type=module', 2591cb0ef41Sopenharmony_ci '--eval', 2601cb0ef41Sopenharmony_ci `import assert from 'node:assert'; 2611cb0ef41Sopenharmony_ci await import(${JSON.stringify(fixtures.fileURL('/es-modules/stateful.mjs'))}) 2621cb0ef41Sopenharmony_ci .then(({ default: count }) => { 2631cb0ef41Sopenharmony_ci assert.strictEqual(count(), 1); 2641cb0ef41Sopenharmony_ci });`, 2651cb0ef41Sopenharmony_ci ]); 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci assert.strictEqual(stderr, ''); 2681cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 2691cb0ef41Sopenharmony_ci assert.strictEqual(code, 0); 2701cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 2711cb0ef41Sopenharmony_ci }); 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci it('ensures that user loaders are not bound to the internal loader', async () => { 2741cb0ef41Sopenharmony_ci const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 2751cb0ef41Sopenharmony_ci '--no-warnings', 2761cb0ef41Sopenharmony_ci '--experimental-loader', 2771cb0ef41Sopenharmony_ci fixtures.fileURL('/es-module-loaders/loader-this-value-inside-hook-functions.mjs'), 2781cb0ef41Sopenharmony_ci '--input-type=module', 2791cb0ef41Sopenharmony_ci '--eval', 2801cb0ef41Sopenharmony_ci ';', // Actual test is inside the loader module. 2811cb0ef41Sopenharmony_ci ]); 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci assert.strictEqual(stderr, ''); 2841cb0ef41Sopenharmony_ci assert.strictEqual(stdout, ''); 2851cb0ef41Sopenharmony_ci assert.strictEqual(code, 0); 2861cb0ef41Sopenharmony_ci assert.strictEqual(signal, null); 2871cb0ef41Sopenharmony_ci }); 2881cb0ef41Sopenharmony_ci}); 289