فهرست منبع

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.
Timothy Flynn 2 سال پیش
والد
کامیت
566a8dfd93

+ 4 - 4
Userland/Libraries/LibJS/Print.cpp

@@ -421,15 +421,15 @@ ErrorOr<void> print_shadow_realm(JS::PrintContext& print_context, JS::ShadowReal
     return {};
 }
 
-ErrorOr<void> print_generator(JS::PrintContext& print_context, JS::GeneratorObject const&, HashTable<JS::Object*>&)
+ErrorOr<void> print_generator(JS::PrintContext& print_context, JS::GeneratorObject const& generator, HashTable<JS::Object*>&)
 {
-    TRY(print_type(print_context, "Generator"sv));
+    TRY(print_type(print_context, generator.class_name()));
     return {};
 }
 
-ErrorOr<void> print_async_generator(JS::PrintContext& print_context, JS::AsyncGenerator const&, HashTable<JS::Object*>&)
+ErrorOr<void> print_async_generator(JS::PrintContext& print_context, JS::AsyncGenerator const& generator, HashTable<JS::Object*>&)
 {
-    TRY(print_type(print_context, "AsyncGenerator"sv));
+    TRY(print_type(print_context, generator.class_name()));
     return {};
 }
 

+ 2 - 1
Userland/Libraries/LibJS/Runtime/GeneratorObject.cpp

@@ -35,9 +35,10 @@ ThrowCompletionOr<NonnullGCPtr<GeneratorObject>> GeneratorObject::create(Realm&
     return object;
 }
 
-GeneratorObject::GeneratorObject(Realm&, Object& prototype, ExecutionContext context)
+GeneratorObject::GeneratorObject(Realm&, Object& prototype, ExecutionContext context, Optional<StringView> generator_brand)
     : Object(ConstructWithPrototypeTag::Tag, prototype)
     , m_execution_context(move(context))
+    , m_generator_brand(move(generator_brand))
 {
 }
 

+ 8 - 5
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<Value> resume(VM&, Value value, Optional<StringView> const& generator_brand);
     ThrowCompletionOr<Value> resume_abrupt(VM&, JS::Completion abrupt_completion, Optional<StringView> 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<StringView> generator_brand = {});
 
     ThrowCompletionOr<GeneratorState> validate(VM&, Optional<StringView> const& generator_brand);
-    ThrowCompletionOr<Value> execute(VM&, JS::Completion const& completion);
+    virtual ThrowCompletionOr<Value> execute(VM&, JS::Completion const& completion);
 
+private:
     ExecutionContext m_execution_context;
     GCPtr<ECMAScriptFunctionObject> m_generating_function;
     Value m_previous_value;