mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-23 01:38:56 +00:00
LibJS: Don't create Handles in Promise.finally()
Capturing Handles like this was creating unbreakable GC reference cycles and causing us to leak entire realms.
This commit is contained in:
parent
12fce55caf
commit
338dde70a1
Notes:
sideshowbarker
2024-07-17 22:09:47 +09:00
Author: https://github.com/awesomekling
Commit: 338dde70a1
Pull-request: https://github.com/SerenityOS/serenity/pull/23815
Reviewed-by: https://github.com/ADKaster
1 changed files with 8 additions and 12 deletions
|
@ -104,22 +104,20 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
|
||||||
// 6. Else,
|
// 6. Else,
|
||||||
else {
|
else {
|
||||||
// a. Let thenFinallyClosure be a new Abstract Closure with parameters (value) that captures onFinally and C and performs the following steps when called:
|
// a. Let thenFinallyClosure be a new Abstract Closure with parameters (value) that captures onFinally and C and performs the following steps when called:
|
||||||
auto then_finally_closure = [constructor_handle = make_handle(constructor), on_finally_handle = make_handle(&on_finally.as_function())](auto& vm) -> ThrowCompletionOr<Value> {
|
auto then_finally_closure = [constructor, on_finally](auto& vm) -> ThrowCompletionOr<Value> {
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
auto& constructor = const_cast<FunctionObject&>(*constructor_handle.cell());
|
|
||||||
auto& on_finally = const_cast<FunctionObject&>(*on_finally_handle.cell());
|
|
||||||
auto value = vm.argument(0);
|
auto value = vm.argument(0);
|
||||||
|
|
||||||
// i. Let result be ? Call(onFinally, undefined).
|
// i. Let result be ? Call(onFinally, undefined).
|
||||||
auto result = TRY(call(vm, on_finally, js_undefined()));
|
auto result = TRY(call(vm, on_finally, js_undefined()));
|
||||||
|
|
||||||
// ii. Let promise be ? PromiseResolve(C, result).
|
// ii. Let promise be ? PromiseResolve(C, result).
|
||||||
auto promise = TRY(promise_resolve(vm, constructor, result));
|
auto promise = TRY(promise_resolve(vm, *constructor, result));
|
||||||
|
|
||||||
// iii. Let returnValue be a new Abstract Closure with no parameters that captures value and performs the following steps when called:
|
// iii. Let returnValue be a new Abstract Closure with no parameters that captures value and performs the following steps when called:
|
||||||
auto return_value = [value_handle = make_handle(value)](auto&) -> ThrowCompletionOr<Value> {
|
auto return_value = [value](auto&) -> ThrowCompletionOr<Value> {
|
||||||
// 1. Return value.
|
// 1. Return value.
|
||||||
return value_handle.value();
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// iv. Let valueThunk be CreateBuiltinFunction(returnValue, 0, "", « »).
|
// iv. Let valueThunk be CreateBuiltinFunction(returnValue, 0, "", « »).
|
||||||
|
@ -133,22 +131,20 @@ JS_DEFINE_NATIVE_FUNCTION(PromisePrototype::finally)
|
||||||
then_finally = NativeFunction::create(realm, move(then_finally_closure), 1, "");
|
then_finally = NativeFunction::create(realm, move(then_finally_closure), 1, "");
|
||||||
|
|
||||||
// c. Let catchFinallyClosure be a new Abstract Closure with parameters (reason) that captures onFinally and C and performs the following steps when called:
|
// c. Let catchFinallyClosure be a new Abstract Closure with parameters (reason) that captures onFinally and C and performs the following steps when called:
|
||||||
auto catch_finally_closure = [constructor_handle = make_handle(constructor), on_finally_handle = make_handle(&on_finally.as_function())](auto& vm) -> ThrowCompletionOr<Value> {
|
auto catch_finally_closure = [constructor, on_finally](auto& vm) -> ThrowCompletionOr<Value> {
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
auto& constructor = const_cast<FunctionObject&>(*constructor_handle.cell());
|
|
||||||
auto& on_finally = const_cast<FunctionObject&>(*on_finally_handle.cell());
|
|
||||||
auto reason = vm.argument(0);
|
auto reason = vm.argument(0);
|
||||||
|
|
||||||
// i. Let result be ? Call(onFinally, undefined).
|
// i. Let result be ? Call(onFinally, undefined).
|
||||||
auto result = TRY(call(vm, on_finally, js_undefined()));
|
auto result = TRY(call(vm, on_finally, js_undefined()));
|
||||||
|
|
||||||
// ii. Let promise be ? PromiseResolve(C, result).
|
// ii. Let promise be ? PromiseResolve(C, result).
|
||||||
auto promise = TRY(promise_resolve(vm, constructor, result));
|
auto promise = TRY(promise_resolve(vm, *constructor, result));
|
||||||
|
|
||||||
// iii. Let throwReason be a new Abstract Closure with no parameters that captures reason and performs the following steps when called:
|
// iii. Let throwReason be a new Abstract Closure with no parameters that captures reason and performs the following steps when called:
|
||||||
auto throw_reason = [reason_handle = make_handle(reason)](auto&) -> ThrowCompletionOr<Value> {
|
auto throw_reason = [reason](auto&) -> ThrowCompletionOr<Value> {
|
||||||
// 1. Return ThrowCompletion(reason).
|
// 1. Return ThrowCompletion(reason).
|
||||||
return throw_completion(reason_handle.value());
|
return throw_completion(reason);
|
||||||
};
|
};
|
||||||
|
|
||||||
// iv. Let thrower be CreateBuiltinFunction(throwReason, 0, "", « »).
|
// iv. Let thrower be CreateBuiltinFunction(throwReason, 0, "", « »).
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue