From cf04942876aee1d1c050f10adfe28aa372239ce9 Mon Sep 17 00:00:00 2001 From: MayaLekova Date: Tue, 25 Aug 2026 13:38:18 +0300 Subject: [PATCH] test: add smoke tests for defer importing synthetic modules The tests added ensure that Node.js doesn't crash or produce incorrect results when importing synthetic modules (i.e. JSON, text or builtin modules) with the `defer` modifier. Signed-off-by: Maya Lekova --- .../test-defer-import-builtin-module.mjs | 29 +++++++++++++++++++ .../test-defer-import-json-module.mjs | 22 ++++++++++++++ .../test-defer-import-text-module.mjs | 18 ++++++++++++ .../import-builtin-module-intermediate.mjs | 8 +++++ 4 files changed, 77 insertions(+) create mode 100644 test/es-module/test-defer-import-builtin-module.mjs create mode 100644 test/es-module/test-defer-import-json-module.mjs create mode 100644 test/es-module/test-defer-import-text-module.mjs create mode 100755 test/fixtures/es-modules/import-builtin-module-intermediate.mjs diff --git a/test/es-module/test-defer-import-builtin-module.mjs b/test/es-module/test-defer-import-builtin-module.mjs new file mode 100644 index 000000000000..e63d19db77e3 --- /dev/null +++ b/test/es-module/test-defer-import-builtin-module.mjs @@ -0,0 +1,29 @@ +// Flags: --js-defer-import-eval --expose-internals + +// Test that uses import.defer for a builtin module. Currently +// defer importing of a synthetic module should be a no-op +// in Node.js as they are born pre-evaluated, so the test +// is mostly a smoke test that Node doesn't crash. + +// TODO: after deferring the evaluation of builtin modules +// is implemented, accessing any property from it will +// trigger the evaluation. + +import '../common/index.mjs'; +import * as assert from 'assert'; + +// Check that there are no modules with 'http' in their name loaded yet. +let modules = process.moduleLoadList.filter((item) => item.endsWith('http')); +assert.strictEqual(modules.length, 0); + +const intermediate = await import('../fixtures/es-modules/import-builtin-module-intermediate.mjs'); + +// Check that after dynamically importing the module with imports 'http' +// itself, the builtin module is already present in the module list. +modules = process.moduleLoadList.filter((item) => item.endsWith('http')); +assert.partialDeepStrictEqual(modules, ['NativeModule http']); + +// Check that the imported module contains some known properties. +assert.notStrictEqual(intermediate.http.STATUS_CODES, undefined); +assert.notStrictEqual(intermediate.http.createServer, undefined); +assert.strictEqual(typeof intermediate.http.createServer, 'function'); diff --git a/test/es-module/test-defer-import-json-module.mjs b/test/es-module/test-defer-import-json-module.mjs new file mode 100644 index 000000000000..1b1d2b23353a --- /dev/null +++ b/test/es-module/test-defer-import-json-module.mjs @@ -0,0 +1,22 @@ +// Flags: --js-defer-import-eval + +// Test that uses import.defer for a JSON module. Currently +// defer importing of a synthetic module should be a no-op +// in Node.js, so the test is mostly a smoke test that Node +// doesn't crash. + +import '../common/index.mjs'; +import * as assert from 'assert'; + +import defer * as imported_json + from '../fixtures/json-with-directory-name-module/module-stub.json' + with { type: 'json' }; + +// eslint-disable-next-line no-duplicate-imports +import * as imported_json_eager + from '../fixtures/json-with-directory-name-module/module-stub.json' + with { type: 'json' }; + +// Check that the imported object has the expected key/value. +assert.strictEqual(imported_json.default.rocko, 'artischocko'); +assert.deepStrictEqual(imported_json_eager.default, imported_json.default); diff --git a/test/es-module/test-defer-import-text-module.mjs b/test/es-module/test-defer-import-text-module.mjs new file mode 100644 index 000000000000..e6710d72fd73 --- /dev/null +++ b/test/es-module/test-defer-import-text-module.mjs @@ -0,0 +1,18 @@ +// Flags: --js-defer-import-eval --experimental-import-text + +// Test that uses import.defer for a text module. Currently +// defer importing of a synthetic module should be a no-op +// in Node.js, so the test is mostly a smoke test that Node +// doesn't crash. + +import '../common/index.mjs'; +import * as assert from 'assert'; + +import defer * as imported_text + from '../fixtures/file-to-read-without-bom.txt' + with { type: 'text' }; + +const expected_text = 'abc\ndef\nghi\n'; + +// Check that the imported text has the expected value. +assert.strictEqual(imported_text.default, expected_text); diff --git a/test/fixtures/es-modules/import-builtin-module-intermediate.mjs b/test/fixtures/es-modules/import-builtin-module-intermediate.mjs new file mode 100755 index 000000000000..5e5b45770983 --- /dev/null +++ b/test/fixtures/es-modules/import-builtin-module-intermediate.mjs @@ -0,0 +1,8 @@ +// This module uses import.defer to import the http builtin module. +// It's dynamically imported by a test module, to ensure the HTTP +// module is actually present in the module list after importing +// this middle module. + +// Import the http builtin module and export all its properties. +import defer * as http from 'node:http'; +export { http };