ladybird/Userland/Libraries/LibJS/Runtime/AsyncGenerator.h
Andreas Kling 3fc0333ee6 LibJS: Put Bytecode::CallFrame + register slots in a single allocation
The number of registers in a call frame never changes, so we can
allocate it at the end of the CallFrame object and save ourselves the
cost of allocating separate Vector storage for every call frame.
2023-11-29 09:48:18 +01:00

67 lines
2.3 KiB
C++

/*
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Variant.h>
#include <LibJS/Bytecode/Interpreter.h>
#include <LibJS/Runtime/ExecutionContext.h>
#include <LibJS/Runtime/Object.h>
namespace JS {
// 27.6.2 Properties of AsyncGenerator Instances, https://tc39.es/ecma262/#sec-properties-of-asyncgenerator-intances
class AsyncGenerator final : public Object {
JS_OBJECT(AsyncGenerator, Object);
JS_DECLARE_ALLOCATOR(AsyncGenerator);
public:
enum class State {
SuspendedStart,
SuspendedYield,
Executing,
AwaitingReturn,
Completed,
};
static ThrowCompletionOr<NonnullGCPtr<AsyncGenerator>> create(Realm&, Value, ECMAScriptFunctionObject*, NonnullOwnPtr<ExecutionContext>, NonnullOwnPtr<Bytecode::CallFrame>);
virtual ~AsyncGenerator() override = default;
void async_generator_enqueue(Completion, NonnullGCPtr<PromiseCapability>);
ThrowCompletionOr<void> resume(VM&, Completion completion);
void await_return();
void complete_step(Completion, bool done, Realm* realm = nullptr);
void drain_queue();
State async_generator_state() const { return m_async_generator_state; }
void set_async_generator_state(Badge<AsyncGeneratorPrototype>, State value);
Optional<String> const& generator_brand() const { return m_generator_brand; }
private:
AsyncGenerator(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext>);
virtual void visit_edges(Cell::Visitor&) override;
void execute(VM&, Completion completion);
ThrowCompletionOr<void> await(Value);
// At the time of constructing an AsyncGenerator, we still need to point to an
// execution context on the stack, but later need to 'adopt' it.
State m_async_generator_state { State::SuspendedStart }; // [[AsyncGeneratorState]]
NonnullOwnPtr<ExecutionContext> m_async_generator_context; // [[AsyncGeneratorContext]]
Vector<AsyncGeneratorRequest> m_async_generator_queue; // [[AsyncGeneratorQueue]]
Optional<String> m_generator_brand; // [[GeneratorBrand]]
GCPtr<ECMAScriptFunctionObject> m_generating_function;
Value m_previous_value;
OwnPtr<Bytecode::CallFrame> m_frame;
GCPtr<Promise> m_current_promise;
};
}