From 6bb2db9a10d7ec65f811808126fc831091dc8842 Mon Sep 17 00:00:00 2001 From: MayaLekova Date: Tue, 2 Jun 2026 16:58:30 +0300 Subject: [PATCH] module: enable existing machinery for import defer This commit enables deferred module imports by using the corresponding functionality in V8. It also adds a single test, but more test coverage should be added. Refs: https://github.com/tc39/proposal-defer-import-eval Signed-off-by: Maya Lekova --- src/module_wrap.cc | 3 +++ src/module_wrap.h | 3 ++- test/es-module/module-deferred-eval.mjs | 8 ++++++++ test/es-module/test-defer-import-eval.mjs | 20 ++++++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/es-module/module-deferred-eval.mjs create mode 100644 test/es-module/test-defer-import-eval.mjs diff --git a/src/module_wrap.cc b/src/module_wrap.cc index 87a8b4d57726af..4f47648f15135f 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -555,6 +555,8 @@ ModulePhase to_phase_constant(ModuleImportPhase phase) { switch (phase) { case ModuleImportPhase::kEvaluation: return kEvaluationPhase; + case ModuleImportPhase::kDefer: + return kDeferPhase; case ModuleImportPhase::kSource: return kSourcePhase; default: @@ -1682,6 +1684,7 @@ void ModuleWrap::CreatePerContextProperties(Local target, V(Module::Status, kErrored); V(ModulePhase, kEvaluationPhase); + V(ModulePhase, kDeferPhase); V(ModulePhase, kSourcePhase); #undef V } diff --git a/src/module_wrap.h b/src/module_wrap.h index a91a7cb6573415..14a8f1a4f2d611 100644 --- a/src/module_wrap.h +++ b/src/module_wrap.h @@ -35,7 +35,8 @@ enum HostDefinedOptions : int { enum ModulePhase : int { kSourcePhase = 1, - kEvaluationPhase = 2, + kDeferPhase = 2, + kEvaluationPhase = 3, }; /** diff --git a/test/es-module/module-deferred-eval.mjs b/test/es-module/module-deferred-eval.mjs new file mode 100644 index 00000000000000..181ac4c07f0600 --- /dev/null +++ b/test/es-module/module-deferred-eval.mjs @@ -0,0 +1,8 @@ +if (!globalThis.eval_list) { + globalThis.eval_list = []; +} +globalThis.eval_list.push('defer-1'); + +export const foo = 42; + +console.log('executed'); diff --git a/test/es-module/test-defer-import-eval.mjs b/test/es-module/test-defer-import-eval.mjs new file mode 100644 index 00000000000000..c504717d3771fd --- /dev/null +++ b/test/es-module/test-defer-import-eval.mjs @@ -0,0 +1,20 @@ +// Flags: --js-defer-import-eval + +// Tests that defer import actually evaluates the imported module +// only when properties that it exports are accessed. + +import * as assert from 'assert' + +globalThis.eval_list = []; + +import defer * as deferred from './module-deferred-eval.mjs' + +assert.strictEqual(0, globalThis.eval_list.length); + +// Attempts to define a property on the deferred module. This should +// trigger its execution, similar to accessing the `foo` property. +assert.throws(() => Object.defineProperty(deferred, 'newProp', {value: 15}), TypeError); +assert.equal(42, deferred.foo); + +// Check that the module has been evaluated at this point. +assert.partialDeepStrictEqual(['defer-1'], globalThis.eval_list);