From 566a8dfd93ac78516f8571ba1f2c98d779821c96 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sun, 16 Jul 2023 14:37:35 -0400 Subject: [PATCH] LibJS: Allow GeneratorObject to be subclassed In the Iterator Helpers proposal, we must create a generator object with additional internal slots and behavior differences. GeneratorObject is currently implemented assuming it wraps around an ECMAScriptFunctionObject with generated bytecode. In this proposal, we instead have "Abstract Closure" blocks. So this marks the `execute` method as virtual, to allow the future subclass to essentially just invoke those closures. We will also require mutable access to the [[GeneratorState]] internal slot. --- Userland/Libraries/LibJS/Print.cpp | 8 ++++---- .../Libraries/LibJS/Runtime/GeneratorObject.cpp | 3 ++- Userland/Libraries/LibJS/Runtime/GeneratorObject.h | 13 ++++++++----- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Userland/Libraries/LibJS/Print.cpp b/Userland/Libraries/LibJS/Print.cpp index 2ae606baf78..11d95eacb1a 100644 --- a/Userland/Libraries/LibJS/Print.cpp +++ b/Userland/Libraries/LibJS/Print.cpp @@ -421,15 +421,15 @@ ErrorOr print_shadow_realm(JS::PrintContext& print_context, JS::ShadowReal return {}; } -ErrorOr print_generator(JS::PrintContext& print_context, JS::GeneratorObject const&, HashTable&) +ErrorOr print_generator(JS::PrintContext& print_context, JS::GeneratorObject const& generator, HashTable&) { - TRY(print_type(print_context, "Generator"sv)); + TRY(print_type(print_context, generator.class_name())); return {}; } -ErrorOr print_async_generator(JS::PrintContext& print_context, JS::AsyncGenerator const&, HashTable&) +ErrorOr print_async_generator(JS::PrintContext& print_context, JS::AsyncGenerator const& generator, HashTable&) { - TRY(print_type(print_context, "AsyncGenerator"sv)); + TRY(print_type(print_context, generator.class_name())); return {}; } diff --git a/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp b/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp index f5400323261..39ab4e66fc3 100644 --- a/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp @@ -35,9 +35,10 @@ ThrowCompletionOr> GeneratorObject::create(Realm& return object; } -GeneratorObject::GeneratorObject(Realm&, Object& prototype, ExecutionContext context) +GeneratorObject::GeneratorObject(Realm&, Object& prototype, ExecutionContext context, Optional generator_brand) : Object(ConstructWithPrototypeTag::Tag, prototype) , m_execution_context(move(context)) + , m_generator_brand(move(generator_brand)) { } diff --git a/Userland/Libraries/LibJS/Runtime/GeneratorObject.h b/Userland/Libraries/LibJS/Runtime/GeneratorObject.h index 2989d41dd64..1217870e92e 100644 --- a/Userland/Libraries/LibJS/Runtime/GeneratorObject.h +++ b/Userland/Libraries/LibJS/Runtime/GeneratorObject.h @@ -12,7 +12,7 @@ namespace JS { -class GeneratorObject final : public Object { +class GeneratorObject : public Object { JS_OBJECT(GeneratorObject, Object); public: @@ -23,19 +23,22 @@ public: ThrowCompletionOr resume(VM&, Value value, Optional const& generator_brand); ThrowCompletionOr resume_abrupt(VM&, JS::Completion abrupt_completion, Optional const& generator_brand); -private: - GeneratorObject(Realm&, Object& prototype, ExecutionContext); - 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, ExecutionContext, Optional generator_brand = {}); ThrowCompletionOr validate(VM&, Optional const& generator_brand); - ThrowCompletionOr execute(VM&, JS::Completion const& completion); + virtual ThrowCompletionOr execute(VM&, JS::Completion const& completion); +private: ExecutionContext m_execution_context; GCPtr m_generating_function; Value m_previous_value;