diff --git a/test/es-module/test-esm-loader-hooks.mjs b/test/es-module/test-esm-loader-hooks.mjs index 7cd967189ec1fc..ce8085bbaf9d29 100644 --- a/test/es-module/test-esm-loader-hooks.mjs +++ b/test/es-module/test-esm-loader-hooks.mjs @@ -4,7 +4,7 @@ import assert from 'node:assert'; import { execPath } from 'node:process'; import { describe, it } from 'node:test'; -describe('Loader hooks', () => { +describe('Loader hooks', { concurrency: true }, () => { it('are called with all expected arguments', async () => { const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ '--no-warnings', @@ -23,4 +23,94 @@ describe('Loader hooks', () => { assert.match(lines[2], /{"url":"file:\/\/\/.*\/experimental\.json","format":"test","shortCircuit":true}/); assert.match(lines[3], /{"source":{"type":"Buffer","data":\[.*\]},"format":"json","shortCircuit":true}/); }); + + describe('should handle never-settling hooks in ESM files', { concurrency: true }, () => { + it('top-level await of a never-settling resolve', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + fixtures.fileURL('es-module-loaders/never-settling-resolve-step/loader.mjs'), + fixtures.path('es-module-loaders/never-settling-resolve-step/never-resolve.mjs'), + ]); + + assert.strictEqual(stderr, ''); + assert.match(stdout, /^should be output\r?\n$/); + assert.strictEqual(code, 13); + assert.strictEqual(signal, null); + }); + + it('top-level await of a never-settling load', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + fixtures.fileURL('es-module-loaders/never-settling-resolve-step/loader.mjs'), + fixtures.path('es-module-loaders/never-settling-resolve-step/never-load.mjs'), + ]); + + assert.strictEqual(stderr, ''); + assert.match(stdout, /^should be output\r?\n$/); + assert.strictEqual(code, 13); + assert.strictEqual(signal, null); + }); + + + it('top-level await of a race of never-settling hooks', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + fixtures.fileURL('es-module-loaders/never-settling-resolve-step/loader.mjs'), + fixtures.path('es-module-loaders/never-settling-resolve-step/race.mjs'), + ]); + + assert.strictEqual(stderr, ''); + assert.match(stdout, /^true\r?\n$/); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + }); + + describe('should handle never-settling hooks in CJS files', { concurrency: true }, () => { + it('never-settling resolve', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + fixtures.fileURL('es-module-loaders/never-settling-resolve-step/loader.mjs'), + fixtures.path('es-module-loaders/never-settling-resolve-step/never-resolve.cjs'), + ]); + + assert.strictEqual(stderr, ''); + assert.match(stdout, /^should be output\r?\n$/); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + + it('never-settling load', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + fixtures.fileURL('es-module-loaders/never-settling-resolve-step/loader.mjs'), + fixtures.path('es-module-loaders/never-settling-resolve-step/never-load.cjs'), + ]); + + assert.strictEqual(stderr, ''); + assert.match(stdout, /^should be output\r?\n$/); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + + it('race of never-settling hooks', async () => { + const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ + '--no-warnings', + '--experimental-loader', + fixtures.fileURL('es-module-loaders/never-settling-resolve-step/loader.mjs'), + fixtures.path('es-module-loaders/never-settling-resolve-step/race.cjs'), + ]); + + assert.strictEqual(stderr, ''); + assert.match(stdout, /^true\r?\n$/); + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); + }); }); diff --git a/test/fixtures/es-module-loaders/never-settling-resolve-step/loader.mjs b/test/fixtures/es-module-loaders/never-settling-resolve-step/loader.mjs new file mode 100644 index 00000000000000..c180583b4c74db --- /dev/null +++ b/test/fixtures/es-module-loaders/never-settling-resolve-step/loader.mjs @@ -0,0 +1,10 @@ +export function resolve(specifier, context, next) { + if (specifier === 'never-settle-resolve') return new Promise(() => {}); + if (specifier === 'never-settle-load') return { __proto__: null, shortCircuit: true, url: 'never-settle:///' }; + return next(specifier, context); +} + +export function load(url, context, next) { + if (url === 'never-settle:///') return new Promise(() => {}); + return next(url, context); +} diff --git a/test/fixtures/es-module-loaders/never-settling-resolve-step/never-load.cjs b/test/fixtures/es-module-loaders/never-settling-resolve-step/never-load.cjs new file mode 100644 index 00000000000000..cc81affe7d0dc6 --- /dev/null +++ b/test/fixtures/es-module-loaders/never-settling-resolve-step/never-load.cjs @@ -0,0 +1,7 @@ +'use strict'; + +const neverSettlingDynamicImport = import('never-settle-load'); + +console.log('should be output'); + +neverSettlingDynamicImport.then(() => process.exit(1)); diff --git a/test/fixtures/es-module-loaders/never-settling-resolve-step/never-load.mjs b/test/fixtures/es-module-loaders/never-settling-resolve-step/never-load.mjs new file mode 100644 index 00000000000000..3dbf801c76051c --- /dev/null +++ b/test/fixtures/es-module-loaders/never-settling-resolve-step/never-load.mjs @@ -0,0 +1,5 @@ +const neverSettlingDynamicImport = import('never-settle-load'); + +console.log('should be output'); + +await neverSettlingDynamicImport; diff --git a/test/fixtures/es-module-loaders/never-settling-resolve-step/never-resolve.cjs b/test/fixtures/es-module-loaders/never-settling-resolve-step/never-resolve.cjs new file mode 100644 index 00000000000000..bf6387560b4704 --- /dev/null +++ b/test/fixtures/es-module-loaders/never-settling-resolve-step/never-resolve.cjs @@ -0,0 +1,7 @@ +'use strict'; + +const neverSettlingDynamicImport = import('never-settle-resolve'); + +console.log('should be output'); + +neverSettlingDynamicImport.then(() => process.exit(1)); diff --git a/test/fixtures/es-module-loaders/never-settling-resolve-step/never-resolve.mjs b/test/fixtures/es-module-loaders/never-settling-resolve-step/never-resolve.mjs new file mode 100644 index 00000000000000..806a131928c339 --- /dev/null +++ b/test/fixtures/es-module-loaders/never-settling-resolve-step/never-resolve.mjs @@ -0,0 +1,5 @@ +const neverSettlingDynamicImport = import('never-settle-resolve'); + +console.log('should be output'); + +await neverSettlingDynamicImport; diff --git a/test/fixtures/es-module-loaders/never-settling-resolve-step/race.cjs b/test/fixtures/es-module-loaders/never-settling-resolve-step/race.cjs new file mode 100644 index 00000000000000..41884ab9d2e769 --- /dev/null +++ b/test/fixtures/es-module-loaders/never-settling-resolve-step/race.cjs @@ -0,0 +1,7 @@ +'use strict'; + +Promise.race([ + import('never-settle-resolve'), + import('never-settle-load'), + import('node:process'), +]).then(result => console.log(result.default === process)); diff --git a/test/fixtures/es-module-loaders/never-settling-resolve-step/race.mjs b/test/fixtures/es-module-loaders/never-settling-resolve-step/race.mjs new file mode 100644 index 00000000000000..8213bbe59d4437 --- /dev/null +++ b/test/fixtures/es-module-loaders/never-settling-resolve-step/race.mjs @@ -0,0 +1,7 @@ +const result = await Promise.race([ + import('never-settle-resolve'), + import('never-settle-load'), + import('node:process'), +]); + +console.log(result.default === process);