ladybird/Libraries/LibJS/Runtime/GeneratorObject.h
Luke Wilde a63b0cfaba LibJS: Introduce NativeJavaScriptBackedFunction
This hosts the ability to compile and run JavaScript to implement
native functions. This is particularly useful for any native function
that is not a normal function, for example async functions such as
Array.fromAsync, which require yielding.

These functions are not allowed to observe anything from outside their
environment. Any global identifiers will instead be assumed to be a
reference to an abstract operation or a constant. The generator will
inject the appropriate bytecode if the name of the global identifier
matches a known name. Anything else will cause a code generation error.
2025-11-30 11:54:54 +01:00

62 lines
2 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/Object.h>
namespace JS {
class GeneratorObject : public Object {
JS_OBJECT(GeneratorObject, Object);
GC_DECLARE_ALLOCATOR(GeneratorObject);
public:
static GC::Ref<GeneratorObject> create(Realm&, Value, Variant<GC::Ref<ECMAScriptFunctionObject>, GC::Ref<NativeJavaScriptBackedFunction>>, NonnullOwnPtr<ExecutionContext>);
virtual ~GeneratorObject() override = default;
void visit_edges(Cell::Visitor&) override;
struct IterationResult {
IterationResult() = delete;
explicit IterationResult(Value value, bool done)
: done(done)
, value(value)
{
}
bool done { false };
Value value;
};
ThrowCompletionOr<IterationResult> resume(VM&, Value value, Optional<StringView> const& generator_brand);
ThrowCompletionOr<IterationResult> resume_abrupt(VM&, JS::Completion abrupt_completion, Optional<StringView> const& generator_brand);
enum class GeneratorState {
SuspendedStart,
SuspendedYield,
Executing,
Completed,
};
GeneratorState generator_state() const { return m_generator_state; }
void set_generator_state(GeneratorState generator_state) { m_generator_state = generator_state; }
protected:
GeneratorObject(Realm&, Object* prototype, NonnullOwnPtr<ExecutionContext>, Optional<StringView> generator_brand = {});
ThrowCompletionOr<GeneratorState> validate(VM&, Optional<StringView> const& generator_brand);
virtual ThrowCompletionOr<IterationResult> execute(VM&, JS::Completion const& completion);
private:
NonnullOwnPtr<ExecutionContext> m_execution_context;
GC::Ptr<Bytecode::Executable> m_generating_executable;
Value m_previous_value;
GeneratorState m_generator_state { GeneratorState::SuspendedStart };
Optional<StringView> m_generator_brand;
};
}