Files
serenity/Userland/Libraries/LibJS/Runtime/AsyncFunctionDriverWrapper.h
Andreas Kling 7b2568bc9a LibJS: Stop having AsyncFunctionDriverWrapper leak itself
Async functions whose promise is never resolved were leaking, since they
had a strong root JS::Handle on themselves.

This doesn't appear to actually be necessary, since the wrapper will be
kept alive as long as it's reachable (and if it's not reachable, nobody
is going to resolve/reject the promise either).

This fixes the vast majority of leaks on Speedometer, bringing memory
usage at the end of a full run from ~12 GiB to ~3 GiB.

(cherry picked from commit b6a5b7e18626ce0dee11a25bb0d51d2e84d3c057)
2024-11-12 19:57:55 -05:00

45 lines
1.3 KiB
C++

/*
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Bytecode/Interpreter.h>
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
#include <LibJS/Runtime/GeneratorObject.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/Promise.h>
namespace JS {
class AsyncFunctionDriverWrapper final : public Promise {
JS_OBJECT(AsyncFunctionDriverWrapper, Promise);
JS_DECLARE_ALLOCATOR(AsyncFunctionDriverWrapper);
public:
enum class IsInitialExecution {
No,
Yes,
};
[[nodiscard]] static NonnullGCPtr<Promise> create(Realm&, GeneratorObject*);
virtual ~AsyncFunctionDriverWrapper() override = default;
void visit_edges(Cell::Visitor&) override;
void continue_async_execution(VM&, Value, bool is_successful, IsInitialExecution is_initial_execution = IsInitialExecution::No);
private:
AsyncFunctionDriverWrapper(Realm&, NonnullGCPtr<GeneratorObject>, NonnullGCPtr<Promise> top_level_promise);
ThrowCompletionOr<void> await(Value);
NonnullGCPtr<GeneratorObject> m_generator_object;
NonnullGCPtr<Promise> m_top_level_promise;
GCPtr<Promise> m_current_promise { nullptr };
OwnPtr<ExecutionContext> m_suspended_execution_context;
};
}