LibJS: Allow constructing generator from function with null "prototype"

Fixes 4 test262 tests and simplifies some upcoming stuff.
This commit is contained in:
Andreas Kling 2025-11-17 10:23:56 +01:00 committed by Andreas Kling
parent acce880359
commit d8f5971ddf
Notes: github-actions[bot] 2025-11-17 22:44:21 +00:00
5 changed files with 13 additions and 9 deletions

View file

@ -24,15 +24,17 @@ ThrowCompletionOr<GC::Ref<AsyncGenerator>> AsyncGenerator::create(Realm& realm,
// This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png) // This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
static Bytecode::PropertyLookupCache cache; static Bytecode::PropertyLookupCache cache;
auto generating_function_prototype = TRY(generating_function->get(vm.names.prototype, cache)); auto generating_function_prototype = TRY(generating_function->get(vm.names.prototype, cache));
auto generating_function_prototype_object = TRY(generating_function_prototype.to_object(vm)); GC::Ptr<Object> generating_function_prototype_object = nullptr;
if (!generating_function_prototype.is_nullish())
generating_function_prototype_object = MUST(generating_function_prototype.to_object(vm));
auto object = realm.create<AsyncGenerator>(realm, generating_function_prototype_object, move(execution_context)); auto object = realm.create<AsyncGenerator>(realm, generating_function_prototype_object, move(execution_context));
object->m_generating_function = generating_function; object->m_generating_function = generating_function;
object->m_previous_value = initial_value; object->m_previous_value = initial_value;
return object; return object;
} }
AsyncGenerator::AsyncGenerator(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext> context) AsyncGenerator::AsyncGenerator(Realm& realm, Object* prototype, NonnullOwnPtr<ExecutionContext> context)
: Object(ConstructWithPrototypeTag::Tag, prototype) : Object(realm, prototype)
, m_async_generator_context(move(context)) , m_async_generator_context(move(context))
{ {
} }

View file

@ -44,7 +44,7 @@ public:
Optional<String> const& generator_brand() const { return m_generator_brand; } Optional<String> const& generator_brand() const { return m_generator_brand; }
private: private:
AsyncGenerator(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext>); AsyncGenerator(Realm&, Object* prototype, NonnullOwnPtr<ExecutionContext>);
virtual void visit_edges(Cell::Visitor&) override; virtual void visit_edges(Cell::Visitor&) override;

View file

@ -32,15 +32,17 @@ ThrowCompletionOr<GC::Ref<GeneratorObject>> GeneratorObject::create(Realm& realm
static Bytecode::PropertyLookupCache cache; static Bytecode::PropertyLookupCache cache;
generating_function_prototype = TRY(generating_function->get(vm.names.prototype, cache)); generating_function_prototype = TRY(generating_function->get(vm.names.prototype, cache));
} }
auto generating_function_prototype_object = TRY(generating_function_prototype.to_object(vm)); GC::Ptr<Object> generating_function_prototype_object = nullptr;
if (!generating_function_prototype.is_nullish())
generating_function_prototype_object = MUST(generating_function_prototype.to_object(vm));
auto object = realm.create<GeneratorObject>(realm, generating_function_prototype_object, move(execution_context)); auto object = realm.create<GeneratorObject>(realm, generating_function_prototype_object, move(execution_context));
object->m_generating_function = generating_function; object->m_generating_function = generating_function;
object->m_previous_value = initial_value; object->m_previous_value = initial_value;
return object; return object;
} }
GeneratorObject::GeneratorObject(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext> context, Optional<StringView> generator_brand) GeneratorObject::GeneratorObject(Realm& realm, Object* prototype, NonnullOwnPtr<ExecutionContext> context, Optional<StringView> generator_brand)
: Object(ConstructWithPrototypeTag::Tag, prototype) : Object(realm, prototype)
, m_execution_context(move(context)) , m_execution_context(move(context))
, m_generator_brand(move(generator_brand)) , m_generator_brand(move(generator_brand))
{ {

View file

@ -46,7 +46,7 @@ public:
void set_generator_state(GeneratorState generator_state) { m_generator_state = generator_state; } void set_generator_state(GeneratorState generator_state) { m_generator_state = generator_state; }
protected: protected:
GeneratorObject(Realm&, Object& prototype, NonnullOwnPtr<ExecutionContext>, Optional<StringView> generator_brand = {}); GeneratorObject(Realm&, Object* prototype, NonnullOwnPtr<ExecutionContext>, Optional<StringView> generator_brand = {});
ThrowCompletionOr<GeneratorState> validate(VM&, Optional<StringView> const& generator_brand); ThrowCompletionOr<GeneratorState> validate(VM&, Optional<StringView> const& generator_brand);
virtual ThrowCompletionOr<IterationResult> execute(VM&, JS::Completion const& completion); virtual ThrowCompletionOr<IterationResult> execute(VM&, JS::Completion const& completion);

View file

@ -19,7 +19,7 @@ ThrowCompletionOr<GC::Ref<IteratorHelper>> IteratorHelper::create(Realm& realm,
} }
IteratorHelper::IteratorHelper(Realm& realm, Object& prototype, GC::Ref<IteratorRecord> underlying_iterator, GC::Ref<Closure> closure, GC::Ptr<AbruptClosure> abrupt_closure) IteratorHelper::IteratorHelper(Realm& realm, Object& prototype, GC::Ref<IteratorRecord> underlying_iterator, GC::Ref<Closure> closure, GC::Ptr<AbruptClosure> abrupt_closure)
: GeneratorObject(realm, prototype, realm.vm().running_execution_context().copy(), "Iterator Helper"sv) : GeneratorObject(realm, &prototype, realm.vm().running_execution_context().copy(), "Iterator Helper"sv)
, m_underlying_iterator(move(underlying_iterator)) , m_underlying_iterator(move(underlying_iterator))
, m_closure(closure) , m_closure(closure)
, m_abrupt_closure(abrupt_closure) , m_abrupt_closure(abrupt_closure)