/* * Copyright (c) 2022, Linus Groh * Copyright (c) 2023, Luke Wilde * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include 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); GC_DECLARE_ALLOCATOR(AsyncGenerator); public: enum class State { SuspendedStart, SuspendedYield, Executing, AwaitingReturn, Completed, }; static ThrowCompletionOr> create(Realm&, Value, ECMAScriptFunctionObject*, NonnullOwnPtr); virtual ~AsyncGenerator() override; void async_generator_enqueue(Completion, GC::Ref); ThrowCompletionOr 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, State value); Optional const& generator_brand() const { return m_generator_brand; } private: AsyncGenerator(Realm&, Object& prototype, NonnullOwnPtr); virtual void visit_edges(Cell::Visitor&) override; void execute(VM&, Completion completion); ThrowCompletionOr 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 m_async_generator_context; // [[AsyncGeneratorContext]] Vector m_async_generator_queue; // [[AsyncGeneratorQueue]] Optional m_generator_brand; // [[GeneratorBrand]] GC::Ptr m_generating_function; Value m_previous_value; GC::Ptr m_current_promise; }; }