From c1640e8ff83c2e1f3cd0efa1b1995c9fed337109 Mon Sep 17 00:00:00 2001 From: Efe Karasakal Date: Tue, 4 Aug 2026 00:21:08 +0200 Subject: [PATCH 1/2] esm: only register text format when enabled Signed-off-by: Efe Karasakal --- lib/internal/modules/esm/assert.js | 18 +++++++++------ lib/internal/process/pre_execution.js | 2 ++ .../es-module/test-esm-loader-text-format.mjs | 23 +++++++++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 test/es-module/test-esm-loader-text-format.mjs diff --git a/lib/internal/modules/esm/assert.js b/lib/internal/modules/esm/assert.js index 406c0f4e4513..3bb6367b56fb 100644 --- a/lib/internal/modules/esm/assert.js +++ b/lib/internal/modules/esm/assert.js @@ -3,6 +3,7 @@ const { ArrayPrototypeFilter, ArrayPrototypeIncludes, + ArrayPrototypePush, ObjectKeys, ObjectPrototypeHasOwnProperty, ObjectValues, @@ -30,7 +31,6 @@ const formatTypeMap = { 'commonjs': kImplicitTypeAttribute, 'json': 'json', 'module': kImplicitTypeAttribute, - 'text': 'text', 'wasm': kImplicitTypeAttribute, // It's unclear whether the HTML spec will require an type attribute or not for Wasm; see https://github.com/WebAssembly/esm-integration/issues/42 }; // NOTE: Don't add bytes support yet as it requires Uint8Arrays backed by immutable ArrayBuffers, @@ -48,6 +48,15 @@ const supportedTypeAttributes = ArrayPrototypeFilter( ObjectValues(formatTypeMap), (type) => type !== kImplicitTypeAttribute); +function initializeImportAttributes() { + if (getOptionValue('--experimental-import-text') && + formatTypeMap['text'] === undefined + ) { + formatTypeMap['text'] = 'text'; + ArrayPrototypePush(supportedTypeAttributes, 'text'); + } +} + /** * Test a module's import attributes. * @param {string} url The URL of the imported module, for error reporting. @@ -67,12 +76,6 @@ function validateAttributes(url, format, } const validType = formatTypeMap[format]; - if (validType !== undefined && - importAttributes.type === 'text' && - !getOptionValue('--experimental-import-text')) { - throw new ERR_IMPORT_ATTRIBUTE_UNSUPPORTED('type', importAttributes.type, url); - } - switch (validType) { case undefined: // Ignore attributes for module formats we don't recognize, to allow new @@ -122,6 +125,7 @@ function handleInvalidType(url, type) { module.exports = { + initializeImportAttributes, kImplicitTypeAttribute, validateAttributes, }; diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js index 9d5891e7a24a..a07da28fa93b 100644 --- a/lib/internal/process/pre_execution.js +++ b/lib/internal/process/pre_execution.js @@ -169,6 +169,8 @@ function prepareExecution(options) { const { initializeExtensionFormatMap } = require('internal/modules/esm/get_format'); initializeExtensionFormatMap(); + const { initializeImportAttributes } = require('internal/modules/esm/assert'); + initializeImportAttributes(); setupVmModules(); if (initializeModules) { diff --git a/test/es-module/test-esm-loader-text-format.mjs b/test/es-module/test-esm-loader-text-format.mjs new file mode 100644 index 000000000000..2a35992dbcf4 --- /dev/null +++ b/test/es-module/test-esm-loader-text-format.mjs @@ -0,0 +1,23 @@ +import '../common/index.mjs'; +import assert from 'node:assert'; +import { registerHooks } from 'node:module'; + +// A user loader can use `text` with and without import attributes without the feature flag. + +registerHooks({ + load(url, context, nextLoad) { + if (url.endsWith('.txt')) { + return nextLoad(url, { ...context, format: 'text' }); + } + return nextLoad(url, context); + }, +}); + +const { default: text } = await import('../fixtures/file-to-read-without-bom.txt'); +const { default: empty } = await import( + '../fixtures/empty.txt', + { with: { type: 'text' } } +); + +assert.strictEqual(text, 'abc\ndef\nghi\n'); +assert.strictEqual(empty, ''); From c26da19a0434370544649a1cfd09ccb54fdfe0e3 Mon Sep 17 00:00:00 2001 From: Efe Karasakal Date: Tue, 4 Aug 2026 17:32:21 +0200 Subject: [PATCH 2/2] esm: apply review changes Signed-off-by: Efe Karasakal --- lib/internal/modules/esm/assert.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/modules/esm/assert.js b/lib/internal/modules/esm/assert.js index 3bb6367b56fb..fcf1368a074c 100644 --- a/lib/internal/modules/esm/assert.js +++ b/lib/internal/modules/esm/assert.js @@ -50,9 +50,9 @@ const supportedTypeAttributes = ArrayPrototypeFilter( function initializeImportAttributes() { if (getOptionValue('--experimental-import-text') && - formatTypeMap['text'] === undefined + formatTypeMap.text === undefined ) { - formatTypeMap['text'] = 'text'; + formatTypeMap.text = 'text'; ArrayPrototypePush(supportedTypeAttributes, 'text'); } }