commit 6a1bf0a168094a71f21f700472b00de770b18e0e
parent a278af2759c343173c898684d3a3c0d08c29c9bf
Author: Yoshi Cheng-Hao Huang <allstars.chh@gmail.com>
Date: Fri, 19 Dec 2025 21:40:07 +0000
Bug 2006871 - Part 3: Pass ImportPhase to various module functions. r=jonco
Defer Import Evaluation:
- FinishLoadingImportedModule : https://tc39.es/proposal-defer-import-eval/#sec-FinishLoadingImportedModule
- ContinueDynamicImport: https://tc39.es/proposal-defer-import-eval/#sec-ContinueDynamicImport
Source Phase Import:
- FinishLoadingImportedModule: https://tc39.es/proposal-source-phase-imports/#sec-FinishLoadingImportedModule
- ContinueModuleLoading: https://tc39.es/proposal-source-phase-imports/#sec-ContinueModuleLoading
- InnerModuleLinking: https://tc39.es/proposal-source-phase-imports/#sec-InnerModuleLinking
- InnerModuleEvaluation: https://tc39.es/proposal-source-phase-imports/#sec-innermoduleevaluation
Differential Revision: https://phabricator.services.mozilla.com/D277003
Diffstat:
1 file changed, 41 insertions(+), 15 deletions(-)
diff --git a/js/src/vm/Modules.cpp b/js/src/vm/Modules.cpp
@@ -56,16 +56,15 @@ static bool SyntheticModuleEvaluate(JSContext* cx, Handle<ModuleObject*> module,
static bool ContinueModuleLoading(JSContext* cx,
Handle<GraphLoadingStateRecordObject*> state,
Handle<ModuleObject*> moduleCompletion,
- Handle<Value> error);
+ ImportPhase phase, Handle<Value> error);
static bool TryStartDynamicModuleImport(JSContext* cx, HandleScript script,
HandleValue specifierArg,
HandleValue optionsArg,
HandleObject promise);
static bool ContinueDynamicImport(JSContext* cx, Handle<JSScript*> referrer,
- Handle<JSObject*> moduleRequest,
Handle<PromiseObject*> promiseCapability,
Handle<ModuleObject*> module,
- bool usePromise);
+ ImportPhase phase, bool usePromise);
static bool LinkAndEvaluateDynamicImport(JSContext* cx, unsigned argc,
Value* vp);
static bool LinkAndEvaluateDynamicImport(
@@ -109,6 +108,7 @@ JS_PUBLIC_API bool JS::FinishLoadingImportedModule(
CHECK_THREAD(cx);
cx->check(referrer, moduleRequest, payload, result);
+ MOZ_ASSERT(moduleRequest->is<ModuleRequestObject>());
MOZ_ASSERT(result);
Rooted<ModuleObject*> module(cx, &result->as<ModuleObject>());
@@ -140,14 +140,17 @@ JS_PUBLIC_API bool JS::FinishLoadingImportedModule(
if (object->is<GraphLoadingStateRecordObject>()) {
Rooted<GraphLoadingStateRecordObject*> state(cx);
state = &object->as<GraphLoadingStateRecordObject>();
- return ContinueModuleLoading(cx, state, module, UndefinedHandleValue);
+ return ContinueModuleLoading(
+ cx, state, module, moduleRequest->as<ModuleRequestObject>().phase(),
+ UndefinedHandleValue);
}
// Step 3. Else,
// Step 3.a. Perform ContinueDynamicImport(payload, result).
MOZ_ASSERT(object->is<PromiseObject>());
Rooted<PromiseObject*> promise(cx, &object->as<PromiseObject>());
- return ContinueDynamicImport(cx, referrer, moduleRequest, promise, module,
+ return ContinueDynamicImport(cx, referrer, promise, module,
+ moduleRequest->as<ModuleRequestObject>().phase(),
usePromise);
}
@@ -166,7 +169,8 @@ JS_PUBLIC_API bool JS::FinishLoadingImportedModuleFailed(
if (payload->is<GraphLoadingStateRecordObject>()) {
Rooted<GraphLoadingStateRecordObject*> state(cx);
state = &payload->as<GraphLoadingStateRecordObject>();
- return ContinueModuleLoading(cx, state, nullptr, error);
+ return ContinueModuleLoading(cx, state, nullptr, ImportPhase::Evaluation,
+ error);
}
// Step 3. Else,
@@ -1437,7 +1441,8 @@ static bool FailWithUnsupportedAttributeException(
return false;
}
- return ContinueModuleLoading(cx, state, nullptr, exnStack.exception());
+ return ContinueModuleLoading(cx, state, nullptr, ImportPhase::Evaluation,
+ exnStack.exception());
}
// https://tc39.es/ecma262/#sec-InnerModuleLoading
@@ -1552,8 +1557,9 @@ static bool InnerModuleLoading(JSContext* cx,
static bool ContinueModuleLoading(JSContext* cx,
Handle<GraphLoadingStateRecordObject*> state,
Handle<ModuleObject*> moduleCompletion,
- Handle<Value> error) {
+ ImportPhase phase, Handle<Value> error) {
MOZ_ASSERT_IF(moduleCompletion, error.isUndefined());
+ MOZ_ASSERT(phase < ImportPhase::Limit);
// Step 1. If state.[[IsLoading]] is false, return unused.
if (!state->isLoading()) {
@@ -1562,6 +1568,9 @@ static bool ContinueModuleLoading(JSContext* cx,
// Step 2. If moduleCompletion is a normal completion, then
if (moduleCompletion) {
+ // TODO: Bug 1943933: Implement Source Phase Imports
+ MOZ_ASSERT(phase == ImportPhase::Evaluation);
+
// Step 2.a. Perform InnerModuleLoading(state, moduleCompletion.[[Value]]).
return InnerModuleLoading(cx, state, moduleCompletion);
}
@@ -1757,6 +1766,7 @@ static bool InnerModuleLinking(JSContext* cx, Handle<ModuleObject*> module,
for (const RequestedModule& request : module->requestedModules()) {
// Step 9.a. Let requiredModule be ? GetImportedModule(module, required).
required = request.moduleRequest();
+ MOZ_ASSERT(required->phase() == ImportPhase::Evaluation);
requiredModule = GetImportedModule(cx, module, required);
if (!requiredModule) {
return false;
@@ -2058,6 +2068,7 @@ static bool InnerModuleEvaluation(JSContext* cx, Handle<ModuleObject*> module,
// Step 11.a. Let requiredModule be GetImportedModule(module,
// required).
required = request.moduleRequest();
+ MOZ_ASSERT(required->phase() == ImportPhase::Evaluation);
requiredModule = GetImportedModule(cx, module, required);
if (!requiredModule) {
return false;
@@ -2667,7 +2678,8 @@ static bool TryStartDynamicModuleImport(JSContext* cx, HandleScript script,
// Step 12. Let moduleRequest be a new ModuleRequest Record { [[Specifier]]:
// specifierString, [[Attributes]]: attributes }.
RootedObject moduleRequest(
- cx, ModuleRequestObject::create(cx, specifierAtom, attributes));
+ cx, ModuleRequestObject::create(cx, specifierAtom, attributes,
+ ImportPhase::Evaluation));
if (!moduleRequest) {
return false;
}
@@ -2738,17 +2750,18 @@ bool js::OnModuleEvaluationFailure(JSContext* cx,
// required.
class DynamicImportContextObject : public NativeObject {
public:
- enum { ReferrerSlot = 0, PromiseSlot, ModuleSlot, SlotCount };
+ enum { ReferrerSlot = 0, PromiseSlot, ModuleSlot, PhaseSlot, SlotCount };
static const JSClass class_;
[[nodiscard]] static DynamicImportContextObject* create(
JSContext* cx, Handle<JSScript*> referrer, Handle<PromiseObject*> promise,
- Handle<ModuleObject*> module);
+ Handle<ModuleObject*> module, ImportPhase phase);
JSScript* referrer() const;
PromiseObject* promise() const;
ModuleObject* module() const;
+ ImportPhase phase() const;
static void finalize(JS::GCContext* gcx, JSObject* obj);
};
@@ -2761,7 +2774,7 @@ const JSClass DynamicImportContextObject::class_ = {
/* static */
DynamicImportContextObject* DynamicImportContextObject::create(
JSContext* cx, Handle<JSScript*> referrer, Handle<PromiseObject*> promise,
- Handle<ModuleObject*> module) {
+ Handle<ModuleObject*> module, ImportPhase phase) {
Rooted<DynamicImportContextObject*> self(
cx, NewObjectWithGivenProto<DynamicImportContextObject>(cx, nullptr));
if (!self) {
@@ -2773,6 +2786,7 @@ DynamicImportContextObject* DynamicImportContextObject::create(
}
self->initReservedSlot(PromiseSlot, ObjectValue(*promise));
self->initReservedSlot(ModuleSlot, ObjectValue(*module));
+ self->initReservedSlot(PhaseSlot, Int32Value(int32_t(phase)));
return self;
}
@@ -2803,12 +2817,21 @@ ModuleObject* DynamicImportContextObject::module() const {
return &value.toObject().as<ModuleObject>();
}
+ImportPhase DynamicImportContextObject::phase() const {
+ Value value = getReservedSlot(PhaseSlot);
+ if (value.isUndefined()) {
+ return ImportPhase::Limit;
+ }
+
+ return static_cast<ImportPhase>(value.toInt32());
+}
+
// https://tc39.es/ecma262/#sec-ContinueDynamicImport
/* static */
bool ContinueDynamicImport(JSContext* cx, Handle<JSScript*> referrer,
- Handle<JSObject*> moduleRequest,
Handle<PromiseObject*> promiseCapability,
- Handle<ModuleObject*> module, bool usePromise) {
+ Handle<ModuleObject*> module, ImportPhase phase,
+ bool usePromise) {
MOZ_ASSERT(module);
// Step 1, 2: Already handled in FinishLoadingImportedModuleFailed functions.
@@ -2817,7 +2840,7 @@ bool ContinueDynamicImport(JSContext* cx, Handle<JSScript*> referrer,
// parameters that captures module, promiseCapability, and onRejected...
Rooted<DynamicImportContextObject*> context(
cx, DynamicImportContextObject::create(cx, referrer, promiseCapability,
- module));
+ module, phase));
if (!context) {
return RejectPromiseWithPendingError(cx, promiseCapability);
}
@@ -2878,6 +2901,9 @@ static bool LinkAndEvaluateDynamicImport(
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
+ // TODO: Bug 1952263: Implement Defer Imports Evaluation.
+ MOZ_ASSERT(context->phase() == ImportPhase::Evaluation);
+
// Step 6.c. Let evaluatePromise be module.Evaluate().
JS::Rooted<JS::Value> rval(cx);
mozilla::DebugOnly<bool> ok = JS::ModuleEvaluate(cx, module, &rval);