mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 12:55:09 +00:00
LibJS: Make PromiseCapability GC-allocated
A struct with three raw pointers to other GC'd types is a pretty big liability, let's just turn this into a Cell itself. This comes with the additional benefit of being able to capture it in a lambda effortlessly, without having to create handles for individual members.
This commit is contained in:
parent
0585029c30
commit
fc9d587e39
29 changed files with 243 additions and 217 deletions
|
@ -197,10 +197,9 @@ ThrowCompletionOr<Promise*> CyclicModule::evaluate(VM& vm)
|
|||
}
|
||||
|
||||
// 4. If module.[[TopLevelCapability]] is not empty, then
|
||||
if (m_top_level_capability.has_value()) {
|
||||
if (m_top_level_capability != nullptr) {
|
||||
// a. Return module.[[TopLevelCapability]].[[Promise]].
|
||||
VERIFY(is<Promise>(*m_top_level_capability->promise));
|
||||
return static_cast<Promise*>(m_top_level_capability->promise);
|
||||
return verify_cast<Promise>(m_top_level_capability->promise().ptr());
|
||||
}
|
||||
|
||||
// 5. Let stack be a new empty List.
|
||||
|
@ -243,7 +242,7 @@ ThrowCompletionOr<Promise*> CyclicModule::evaluate(VM& vm)
|
|||
VERIFY(m_evaluation_error.is_error() && same_value(*m_evaluation_error.throw_completion().value(), *result.throw_completion().value()));
|
||||
|
||||
// d. Perform ! Call(capability.[[Reject]], undefined, « result.[[Value]] »).
|
||||
MUST(call(vm, m_top_level_capability->reject, js_undefined(), *result.throw_completion().value()));
|
||||
MUST(call(vm, *m_top_level_capability->reject(), js_undefined(), *result.throw_completion().value()));
|
||||
}
|
||||
// 10. Else,
|
||||
else {
|
||||
|
@ -257,7 +256,7 @@ ThrowCompletionOr<Promise*> CyclicModule::evaluate(VM& vm)
|
|||
// i. Assert: module.[[Status]] is evaluated.
|
||||
VERIFY(m_status == ModuleStatus::Evaluated);
|
||||
// ii. Perform ! Call(capability.[[Resolve]], undefined, « undefined »).
|
||||
MUST(call(vm, m_top_level_capability->resolve, js_undefined(), js_undefined()));
|
||||
MUST(call(vm, *m_top_level_capability->resolve(), js_undefined(), js_undefined()));
|
||||
}
|
||||
|
||||
// d. Assert: stack is empty.
|
||||
|
@ -265,8 +264,7 @@ ThrowCompletionOr<Promise*> CyclicModule::evaluate(VM& vm)
|
|||
}
|
||||
|
||||
// 11. Return capability.[[Promise]].
|
||||
VERIFY(is<Promise>(*m_top_level_capability->promise));
|
||||
return static_cast<Promise*>(m_top_level_capability->promise);
|
||||
return verify_cast<Promise>(m_top_level_capability->promise().ptr());
|
||||
}
|
||||
|
||||
// 16.2.1.5.2.1 InnerModuleEvaluation ( module, stack, index ), https://tc39.es/ecma262/#sec-innermoduleevaluation
|
||||
|
@ -432,7 +430,7 @@ ThrowCompletionOr<void> CyclicModule::initialize_environment(VM&)
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ThrowCompletionOr<void> CyclicModule::execute_module(VM&, Optional<PromiseCapability>)
|
||||
ThrowCompletionOr<void> CyclicModule::execute_module(VM&, GCPtr<PromiseCapability>)
|
||||
{
|
||||
// Note: In ecma262 this is never called on a cyclic module only on SourceTextModules.
|
||||
// So this check is to make sure we don't accidentally call this.
|
||||
|
@ -479,10 +477,8 @@ void CyclicModule::execute_async_module(VM& vm)
|
|||
// 7. Let onRejected be CreateBuiltinFunction(rejectedClosure, 0, "", « »).
|
||||
auto* on_rejected = NativeFunction::create(realm, move(rejected_closure), 0, "");
|
||||
|
||||
VERIFY(is<Promise>(*capability.promise));
|
||||
|
||||
// 8. Perform PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected).
|
||||
static_cast<Promise*>(capability.promise)->perform_then(on_fulfilled, on_rejected, {});
|
||||
verify_cast<Promise>(capability->promise().ptr())->perform_then(on_fulfilled, on_rejected, {});
|
||||
|
||||
// 9. Perform ! module.ExecuteModule(capability).
|
||||
MUST(execute_module(vm, capability));
|
||||
|
@ -555,12 +551,12 @@ void CyclicModule::async_module_execution_fulfilled(VM& vm)
|
|||
m_status = ModuleStatus::Evaluated;
|
||||
|
||||
// 7. If module.[[TopLevelCapability]] is not empty, then
|
||||
if (m_top_level_capability.has_value()) {
|
||||
if (m_top_level_capability != nullptr) {
|
||||
// a. Assert: module.[[CycleRoot]] is module.
|
||||
VERIFY(m_cycle_root == this);
|
||||
|
||||
// b. Perform ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »).
|
||||
MUST(call(vm, m_top_level_capability->resolve, js_undefined(), js_undefined()));
|
||||
MUST(call(vm, *m_top_level_capability->resolve(), js_undefined(), js_undefined()));
|
||||
}
|
||||
|
||||
// 8. Let execList be a new empty List.
|
||||
|
@ -603,12 +599,12 @@ void CyclicModule::async_module_execution_fulfilled(VM& vm)
|
|||
module->m_status = ModuleStatus::Evaluated;
|
||||
|
||||
// 2. If m.[[TopLevelCapability]] is not empty, then
|
||||
if (module->m_top_level_capability.has_value()) {
|
||||
if (module->m_top_level_capability != nullptr) {
|
||||
// a. Assert: m.[[CycleRoot]] is m.
|
||||
VERIFY(module->m_cycle_root == module);
|
||||
|
||||
// b. Perform ! Call(m.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »).
|
||||
MUST(call(vm, module->m_top_level_capability->resolve, js_undefined(), js_undefined()));
|
||||
MUST(call(vm, *module->m_top_level_capability->resolve(), js_undefined(), js_undefined()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -652,12 +648,12 @@ void CyclicModule::async_module_execution_rejected(VM& vm, Value error)
|
|||
}
|
||||
|
||||
// 8. If module.[[TopLevelCapability]] is not empty, then
|
||||
if (m_top_level_capability.has_value()) {
|
||||
if (m_top_level_capability != nullptr) {
|
||||
// a. Assert: module.[[CycleRoot]] is module.
|
||||
VERIFY(m_cycle_root == this);
|
||||
|
||||
// b. Perform ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »).
|
||||
MUST(call(vm, m_top_level_capability->reject, js_undefined(), error));
|
||||
MUST(call(vm, *m_top_level_capability->reject(), js_undefined(), error));
|
||||
}
|
||||
|
||||
// 9. Return unused.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue