mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:27:35 +00:00
LibJS: Add the remaining generator objects
- %GeneratorFunction% - %GeneratorFunction.prototype% - %GeneratorFunction.prototype.prototype% - %Generator%.prototype
This commit is contained in:
parent
b205c9814a
commit
22b17219ff
14 changed files with 302 additions and 67 deletions
|
@ -59,7 +59,10 @@ set(SOURCES
|
||||||
Runtime/FunctionConstructor.cpp
|
Runtime/FunctionConstructor.cpp
|
||||||
Runtime/Function.cpp
|
Runtime/Function.cpp
|
||||||
Runtime/FunctionPrototype.cpp
|
Runtime/FunctionPrototype.cpp
|
||||||
|
Runtime/GeneratorFunctionConstructor.cpp
|
||||||
|
Runtime/GeneratorFunctionPrototype.cpp
|
||||||
Runtime/GeneratorObject.cpp
|
Runtime/GeneratorObject.cpp
|
||||||
|
Runtime/GeneratorObjectPrototype.cpp
|
||||||
Runtime/GlobalObject.cpp
|
Runtime/GlobalObject.cpp
|
||||||
Runtime/IndexedProperties.cpp
|
Runtime/IndexedProperties.cpp
|
||||||
Runtime/IteratorOperations.cpp
|
Runtime/IteratorOperations.cpp
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
__JS_ENUMERATE(Error, error, ErrorPrototype, ErrorConstructor, void) \
|
__JS_ENUMERATE(Error, error, ErrorPrototype, ErrorConstructor, void) \
|
||||||
__JS_ENUMERATE(FinalizationRegistry, finalization_registry, FinalizationRegistryPrototype, FinalizationRegistryConstructor, void) \
|
__JS_ENUMERATE(FinalizationRegistry, finalization_registry, FinalizationRegistryPrototype, FinalizationRegistryConstructor, void) \
|
||||||
__JS_ENUMERATE(Function, function, FunctionPrototype, FunctionConstructor, void) \
|
__JS_ENUMERATE(Function, function, FunctionPrototype, FunctionConstructor, void) \
|
||||||
|
__JS_ENUMERATE(GeneratorFunction, generator_function, GeneratorFunctionPrototype, GeneratorFunctionConstructor, void) \
|
||||||
__JS_ENUMERATE(Map, map, MapPrototype, MapConstructor, void) \
|
__JS_ENUMERATE(Map, map, MapPrototype, MapConstructor, void) \
|
||||||
__JS_ENUMERATE(NumberObject, number, NumberPrototype, NumberConstructor, void) \
|
__JS_ENUMERATE(NumberObject, number, NumberPrototype, NumberConstructor, void) \
|
||||||
__JS_ENUMERATE(Object, object, ObjectPrototype, ObjectConstructor, void) \
|
__JS_ENUMERATE(Object, object, ObjectPrototype, ObjectConstructor, void) \
|
||||||
|
@ -159,6 +160,9 @@ struct PromiseCapability;
|
||||||
class ProxyObject;
|
class ProxyObject;
|
||||||
class ProxyConstructor;
|
class ProxyConstructor;
|
||||||
|
|
||||||
|
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct constructor
|
||||||
|
class GeneratorObjectPrototype;
|
||||||
|
|
||||||
class TypedArrayConstructor;
|
class TypedArrayConstructor;
|
||||||
class TypedArrayPrototype;
|
class TypedArrayPrototype;
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,13 @@ FunctionConstructor::~FunctionConstructor()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
||||||
Value FunctionConstructor::call()
|
Value FunctionConstructor::call()
|
||||||
{
|
{
|
||||||
return construct(*this);
|
return construct(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 20.2.1.1 Function ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-function-p1-p2-pn-body
|
||||||
Value FunctionConstructor::construct(Function&)
|
Value FunctionConstructor::construct(Function&)
|
||||||
{
|
{
|
||||||
auto& vm = this->vm();
|
auto& vm = this->vm();
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/FunctionConstructor.h>
|
||||||
|
#include <LibJS/Runtime/Function.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorFunctionConstructor.h>
|
||||||
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
GeneratorFunctionConstructor::GeneratorFunctionConstructor(GlobalObject& global_object)
|
||||||
|
: NativeFunction(*static_cast<Object*>(global_object.function_constructor()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneratorFunctionConstructor::initialize(GlobalObject& global_object)
|
||||||
|
{
|
||||||
|
auto& vm = this->vm();
|
||||||
|
NativeFunction::initialize(global_object);
|
||||||
|
|
||||||
|
// 27.3.2.1 GeneratorFunction.length, https://tc39.es/ecma262/#sec-generatorfunction.length
|
||||||
|
define_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||||
|
// 27.3.2.2 GeneratorFunction.prototype, https://tc39.es/ecma262/#sec-generatorfunction.length
|
||||||
|
define_property(vm.names.prototype, global_object.generator_function_prototype(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratorFunctionConstructor::~GeneratorFunctionConstructor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// 27.3.1.1 GeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-generatorfunction
|
||||||
|
Value GeneratorFunctionConstructor::call()
|
||||||
|
{
|
||||||
|
return construct(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 27.3.1.1 GeneratorFunction ( p1, p2, … , pn, body ), https://tc39.es/ecma262/#sec-generatorfunction
|
||||||
|
Value GeneratorFunctionConstructor::construct(Function&)
|
||||||
|
{
|
||||||
|
TODO();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/NativeFunction.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
// 27.3.1 %GeneratorFunction%, https://tc39.es/ecma262/#sec-generatorfunction-constructor
|
||||||
|
class GeneratorFunctionConstructor final : public NativeFunction {
|
||||||
|
JS_OBJECT(GeneratorFunctionConstructor, NativeFunction);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GeneratorFunctionConstructor(GlobalObject&);
|
||||||
|
virtual void initialize(GlobalObject&) override;
|
||||||
|
virtual ~GeneratorFunctionConstructor() override;
|
||||||
|
|
||||||
|
virtual Value call() override;
|
||||||
|
virtual Value construct(Function& new_target) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/GeneratorFunctionConstructor.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorFunctionPrototype.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorObjectPrototype.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
GeneratorFunctionPrototype::GeneratorFunctionPrototype(GlobalObject& global_object)
|
||||||
|
: Object(*global_object.function_prototype())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneratorFunctionPrototype::initialize(GlobalObject& global_object)
|
||||||
|
{
|
||||||
|
auto& vm = this->vm();
|
||||||
|
Object::initialize(global_object);
|
||||||
|
|
||||||
|
// 27.3.3.2 %GeneratorFunction.prototype% prototype, https://tc39.es/ecma262/#sec-generatorfunction.prototype.prototype
|
||||||
|
define_property(vm.names.prototype, global_object.generator_object_prototype(), Attribute::Configurable);
|
||||||
|
// 27.3.3.3 %GeneratorFunction.prototype% [ @@toStringTag ], https://tc39.es/ecma262/#sec-generatorfunction.prototype-@@tostringtag
|
||||||
|
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm, "GeneratorFunction"), Attribute::Configurable);
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratorFunctionPrototype::~GeneratorFunctionPrototype()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/Function.h>
|
||||||
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
// 27.3.3 %GeneratorFunction.prototype%, https://tc39.es/ecma262/#sec-properties-of-the-generatorfunction-prototype-object
|
||||||
|
class GeneratorFunctionPrototype final : public Object {
|
||||||
|
JS_OBJECT(GeneratorFunctionPrototype, Object);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GeneratorFunctionPrototype(GlobalObject&);
|
||||||
|
virtual void initialize(GlobalObject&) override;
|
||||||
|
virtual ~GeneratorFunctionPrototype() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -8,13 +8,19 @@
|
||||||
#include <LibJS/Bytecode/Generator.h>
|
#include <LibJS/Bytecode/Generator.h>
|
||||||
#include <LibJS/Bytecode/Interpreter.h>
|
#include <LibJS/Bytecode/Interpreter.h>
|
||||||
#include <LibJS/Runtime/GeneratorObject.h>
|
#include <LibJS/Runtime/GeneratorObject.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorObjectPrototype.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
GeneratorObject* GeneratorObject::create(GlobalObject& global_object, Value initial_value, ScriptFunction* generating_function, ScopeObject* generating_scope, Bytecode::RegisterWindow frame)
|
GeneratorObject* GeneratorObject::create(GlobalObject& global_object, Value initial_value, ScriptFunction* generating_function, ScopeObject* generating_scope, Bytecode::RegisterWindow frame)
|
||||||
{
|
{
|
||||||
auto object = global_object.heap().allocate<GeneratorObject>(global_object, global_object);
|
// This is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
|
||||||
|
auto generating_function_proto_property = generating_function->get(global_object.vm().names.prototype).to_object(global_object);
|
||||||
|
if (!generating_function_proto_property)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
auto object = global_object.heap().allocate<GeneratorObject>(global_object, global_object, *generating_function_proto_property);
|
||||||
object->m_generating_function = generating_function;
|
object->m_generating_function = generating_function;
|
||||||
object->m_scope = generating_scope;
|
object->m_scope = generating_scope;
|
||||||
object->m_frame = move(frame);
|
object->m_frame = move(frame);
|
||||||
|
@ -22,21 +28,13 @@ GeneratorObject* GeneratorObject::create(GlobalObject& global_object, Value init
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneratorObject::GeneratorObject(GlobalObject& global_object)
|
GeneratorObject::GeneratorObject(GlobalObject&, Object& prototype)
|
||||||
: Object(*global_object.object_prototype())
|
: Object(prototype)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneratorObject::initialize(GlobalObject& global_object)
|
void GeneratorObject::initialize(GlobalObject&)
|
||||||
{
|
{
|
||||||
// FIXME: These should be on a separate Generator prototype object!
|
|
||||||
// https://tc39.es/ecma262/#sec-generator-objects
|
|
||||||
|
|
||||||
auto& vm = this->vm();
|
|
||||||
Object::initialize(global_object);
|
|
||||||
define_native_function(vm.names.next, next);
|
|
||||||
define_native_function(vm.names.return_, return_);
|
|
||||||
define_native_function(vm.names.throw_, throw_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneratorObject::~GeneratorObject()
|
GeneratorObject::~GeneratorObject()
|
||||||
|
@ -52,18 +50,6 @@ void GeneratorObject::visit_edges(Cell::Visitor& visitor)
|
||||||
visitor.visit(&m_previous_value.as_object());
|
visitor.visit(&m_previous_value.as_object());
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneratorObject* GeneratorObject::typed_this(VM& vm, GlobalObject& global_object)
|
|
||||||
{
|
|
||||||
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
|
||||||
if (!this_object)
|
|
||||||
return {};
|
|
||||||
if (!is<GeneratorObject>(this_object)) {
|
|
||||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Generator");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return static_cast<GeneratorObject*>(this_object);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value GeneratorObject::next_impl(VM& vm, GlobalObject& global_object, Optional<Value> value_to_throw)
|
Value GeneratorObject::next_impl(VM& vm, GlobalObject& global_object, Optional<Value> value_to_throw)
|
||||||
{
|
{
|
||||||
auto bytecode_interpreter = Bytecode::Interpreter::current();
|
auto bytecode_interpreter = Bytecode::Interpreter::current();
|
||||||
|
@ -138,29 +124,4 @@ Value GeneratorObject::next_impl(VM& vm, GlobalObject& global_object, Optional<V
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_DEFINE_NATIVE_FUNCTION(GeneratorObject::next)
|
|
||||||
{
|
|
||||||
auto object = typed_this(vm, global_object);
|
|
||||||
if (!object)
|
|
||||||
return {};
|
|
||||||
return object->next_impl(vm, global_object, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_DEFINE_NATIVE_FUNCTION(GeneratorObject::return_)
|
|
||||||
{
|
|
||||||
auto object = typed_this(vm, global_object);
|
|
||||||
if (!object)
|
|
||||||
return {};
|
|
||||||
object->m_done = true;
|
|
||||||
return object->next_impl(vm, global_object, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_DEFINE_NATIVE_FUNCTION(GeneratorObject::throw_)
|
|
||||||
{
|
|
||||||
auto object = typed_this(vm, global_object);
|
|
||||||
if (!object)
|
|
||||||
return {};
|
|
||||||
return object->next_impl(vm, global_object, vm.argument(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,20 +16,15 @@ class GeneratorObject final : public Object {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static GeneratorObject* create(GlobalObject&, Value, ScriptFunction*, ScopeObject*, Bytecode::RegisterWindow);
|
static GeneratorObject* create(GlobalObject&, Value, ScriptFunction*, ScopeObject*, Bytecode::RegisterWindow);
|
||||||
explicit GeneratorObject(GlobalObject&);
|
GeneratorObject(GlobalObject&, Object& prototype);
|
||||||
virtual void initialize(GlobalObject&) override;
|
virtual void initialize(GlobalObject&) override;
|
||||||
virtual ~GeneratorObject() override;
|
virtual ~GeneratorObject() override;
|
||||||
void visit_edges(Cell::Visitor&) override;
|
void visit_edges(Cell::Visitor&) override;
|
||||||
|
|
||||||
static GeneratorObject* typed_this(VM&, GlobalObject&);
|
Value next_impl(VM&, GlobalObject&, Optional<Value> value_to_throw);
|
||||||
|
void set_done() { m_done = true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JS_DECLARE_NATIVE_FUNCTION(next);
|
|
||||||
JS_DECLARE_NATIVE_FUNCTION(return_);
|
|
||||||
JS_DECLARE_NATIVE_FUNCTION(throw_);
|
|
||||||
|
|
||||||
Value next_impl(VM&, GlobalObject&, Optional<Value> value_to_throw);
|
|
||||||
|
|
||||||
ScopeObject* m_scope { nullptr };
|
ScopeObject* m_scope { nullptr };
|
||||||
ScriptFunction* m_generating_function { nullptr };
|
ScriptFunction* m_generating_function { nullptr };
|
||||||
Value m_previous_value;
|
Value m_previous_value;
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Bytecode/Interpreter.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorObject.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorObjectPrototype.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
static GeneratorObject* typed_this(VM& vm, GlobalObject& global_object)
|
||||||
|
{
|
||||||
|
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
||||||
|
if (!this_object)
|
||||||
|
return {};
|
||||||
|
if (!is<GeneratorObject>(this_object)) {
|
||||||
|
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Generator");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return static_cast<GeneratorObject*>(this_object);
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratorObjectPrototype::GeneratorObjectPrototype(GlobalObject& global_object)
|
||||||
|
: Object(*global_object.iterator_prototype())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void GeneratorObjectPrototype::initialize(GlobalObject& global_object)
|
||||||
|
{
|
||||||
|
auto& vm = this->vm();
|
||||||
|
Object::initialize(global_object);
|
||||||
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
|
define_native_function(vm.names.next, next, 1, attr);
|
||||||
|
define_native_function(vm.names.return_, return_, 1, attr);
|
||||||
|
define_native_function(vm.names.throw_, throw_, 1, attr);
|
||||||
|
|
||||||
|
// 27.5.1.5 Generator.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-generator.prototype-@@tostringtag
|
||||||
|
define_property(vm.well_known_symbol_to_string_tag(), js_string(vm, "Generator"), Attribute::Configurable);
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneratorObjectPrototype::~GeneratorObjectPrototype()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// 27.5.1.2 Generator.prototype.next ( value ), https://tc39.es/ecma262/#sec-generator.prototype.next
|
||||||
|
JS_DEFINE_NATIVE_FUNCTION(GeneratorObjectPrototype::next)
|
||||||
|
{
|
||||||
|
auto generator_object = typed_this(vm, global_object);
|
||||||
|
if (!generator_object)
|
||||||
|
return {};
|
||||||
|
return generator_object->next_impl(vm, global_object, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 27.5.1.3 Generator.prototype.next ( value ), https://tc39.es/ecma262/#sec-generator.prototype.return
|
||||||
|
JS_DEFINE_NATIVE_FUNCTION(GeneratorObjectPrototype::return_)
|
||||||
|
{
|
||||||
|
auto generator_object = typed_this(vm, global_object);
|
||||||
|
if (!generator_object)
|
||||||
|
return {};
|
||||||
|
generator_object->set_done();
|
||||||
|
return generator_object->next_impl(vm, global_object, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 27.5.1.4 Generator.prototype.next ( value ), https://tc39.es/ecma262/#sec-generator.prototype.throw
|
||||||
|
JS_DEFINE_NATIVE_FUNCTION(GeneratorObjectPrototype::throw_)
|
||||||
|
{
|
||||||
|
auto generator_object = typed_this(vm, global_object);
|
||||||
|
if (!generator_object)
|
||||||
|
return {};
|
||||||
|
return generator_object->next_impl(vm, global_object, vm.argument(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
Userland/Libraries/LibJS/Runtime/GeneratorObjectPrototype.h
Normal file
28
Userland/Libraries/LibJS/Runtime/GeneratorObjectPrototype.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
// 27.5.1 %GeneratorFunction.prototype.prototype%, https://tc39.es/ecma262/#sec-properties-of-generator-prototype
|
||||||
|
class GeneratorObjectPrototype final : public Object {
|
||||||
|
JS_OBJECT(GeneratorObjectPrototype, Object);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GeneratorObjectPrototype(GlobalObject&);
|
||||||
|
virtual void initialize(GlobalObject&) override;
|
||||||
|
virtual ~GeneratorObjectPrototype() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
JS_DECLARE_NATIVE_FUNCTION(next);
|
||||||
|
JS_DECLARE_NATIVE_FUNCTION(return_);
|
||||||
|
JS_DECLARE_NATIVE_FUNCTION(throw_);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -37,6 +37,9 @@
|
||||||
#include <LibJS/Runtime/FinalizationRegistryPrototype.h>
|
#include <LibJS/Runtime/FinalizationRegistryPrototype.h>
|
||||||
#include <LibJS/Runtime/FunctionConstructor.h>
|
#include <LibJS/Runtime/FunctionConstructor.h>
|
||||||
#include <LibJS/Runtime/FunctionPrototype.h>
|
#include <LibJS/Runtime/FunctionPrototype.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorFunctionConstructor.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorFunctionPrototype.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorObjectPrototype.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/IteratorPrototype.h>
|
#include <LibJS/Runtime/IteratorPrototype.h>
|
||||||
#include <LibJS/Runtime/JSONObject.h>
|
#include <LibJS/Runtime/JSONObject.h>
|
||||||
|
@ -110,18 +113,23 @@ void GlobalObject::initialize_global_object()
|
||||||
// This must be initialized before allocating AggregateErrorPrototype, which uses ErrorPrototype as its prototype.
|
// This must be initialized before allocating AggregateErrorPrototype, which uses ErrorPrototype as its prototype.
|
||||||
m_error_prototype = heap().allocate<ErrorPrototype>(*this, *this);
|
m_error_prototype = heap().allocate<ErrorPrototype>(*this, *this);
|
||||||
|
|
||||||
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
|
||||||
if (!m_##snake_name##_prototype) \
|
|
||||||
m_##snake_name##_prototype = heap().allocate<PrototypeName>(*this, *this);
|
|
||||||
JS_ENUMERATE_BUILTIN_TYPES
|
|
||||||
#undef __JS_ENUMERATE
|
|
||||||
|
|
||||||
#define __JS_ENUMERATE(ClassName, snake_name) \
|
#define __JS_ENUMERATE(ClassName, snake_name) \
|
||||||
if (!m_##snake_name##_prototype) \
|
if (!m_##snake_name##_prototype) \
|
||||||
m_##snake_name##_prototype = heap().allocate<ClassName##Prototype>(*this, *this);
|
m_##snake_name##_prototype = heap().allocate<ClassName##Prototype>(*this, *this);
|
||||||
JS_ENUMERATE_ITERATOR_PROTOTYPES
|
JS_ENUMERATE_ITERATOR_PROTOTYPES
|
||||||
#undef __JS_ENUMERATE
|
#undef __JS_ENUMERATE
|
||||||
|
|
||||||
|
// %GeneratorFunction.prototype.prototype% must be initialized separately as it has no
|
||||||
|
// companion constructor
|
||||||
|
m_generator_object_prototype = heap().allocate<GeneratorObjectPrototype>(*this, *this);
|
||||||
|
m_generator_object_prototype->define_property(vm.names.constructor, m_generator_function_constructor, Attribute::Configurable);
|
||||||
|
|
||||||
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||||
|
if (!m_##snake_name##_prototype) \
|
||||||
|
m_##snake_name##_prototype = heap().allocate<PrototypeName>(*this, *this);
|
||||||
|
JS_ENUMERATE_BUILTIN_TYPES
|
||||||
|
#undef __JS_ENUMERATE
|
||||||
|
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
define_native_function(vm.names.gc, gc, 0, attr);
|
define_native_function(vm.names.gc, gc, 0, attr);
|
||||||
define_native_function(vm.names.isNaN, is_nan, 1, attr);
|
define_native_function(vm.names.isNaN, is_nan, 1, attr);
|
||||||
|
@ -179,6 +187,11 @@ void GlobalObject::initialize_global_object()
|
||||||
JS_ENUMERATE_NATIVE_ERRORS
|
JS_ENUMERATE_NATIVE_ERRORS
|
||||||
JS_ENUMERATE_TYPED_ARRAYS
|
JS_ENUMERATE_TYPED_ARRAYS
|
||||||
#undef __JS_ENUMERATE
|
#undef __JS_ENUMERATE
|
||||||
|
|
||||||
|
// The generator constructor cannot be initialized with add_constructor as it has no global binding
|
||||||
|
m_generator_function_constructor = heap().allocate<GeneratorFunctionConstructor>(*this, *this);
|
||||||
|
// 27.3.3.1 GeneratorFunction.prototype.constructor, https://tc39.es/ecma262/#sec-generatorfunction.prototype.constructor
|
||||||
|
m_generator_function_prototype->define_property(vm.names.constructor, m_generator_function_constructor, Attribute::Configurable);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalObject::~GlobalObject()
|
GlobalObject::~GlobalObject()
|
||||||
|
@ -193,6 +206,7 @@ void GlobalObject::visit_edges(Visitor& visitor)
|
||||||
visitor.visit(m_new_object_shape);
|
visitor.visit(m_new_object_shape);
|
||||||
visitor.visit(m_new_script_function_prototype_object_shape);
|
visitor.visit(m_new_script_function_prototype_object_shape);
|
||||||
visitor.visit(m_proxy_constructor);
|
visitor.visit(m_proxy_constructor);
|
||||||
|
visitor.visit(m_generator_object_prototype);
|
||||||
|
|
||||||
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||||
visitor.visit(m_##snake_name##_constructor); \
|
visitor.visit(m_##snake_name##_constructor); \
|
||||||
|
|
|
@ -37,6 +37,9 @@ public:
|
||||||
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype
|
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype
|
||||||
ProxyConstructor* proxy_constructor() { return m_proxy_constructor; }
|
ProxyConstructor* proxy_constructor() { return m_proxy_constructor; }
|
||||||
|
|
||||||
|
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct constructor
|
||||||
|
GeneratorObjectPrototype* generator_object_prototype() { return m_generator_object_prototype; }
|
||||||
|
|
||||||
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||||
ConstructorName* snake_name##_constructor() { return m_##snake_name##_constructor; } \
|
ConstructorName* snake_name##_constructor() { return m_##snake_name##_constructor; } \
|
||||||
Object* snake_name##_prototype() { return m_##snake_name##_prototype; }
|
Object* snake_name##_prototype() { return m_##snake_name##_prototype; }
|
||||||
|
@ -81,6 +84,9 @@ private:
|
||||||
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype
|
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype
|
||||||
ProxyConstructor* m_proxy_constructor { nullptr };
|
ProxyConstructor* m_proxy_constructor { nullptr };
|
||||||
|
|
||||||
|
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct constructor
|
||||||
|
GeneratorObjectPrototype* m_generator_object_prototype { nullptr };
|
||||||
|
|
||||||
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||||
ConstructorName* m_##snake_name##_constructor { nullptr }; \
|
ConstructorName* m_##snake_name##_constructor { nullptr }; \
|
||||||
Object* m_##snake_name##_prototype { nullptr };
|
Object* m_##snake_name##_prototype { nullptr };
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <LibJS/Runtime/Array.h>
|
#include <LibJS/Runtime/Array.h>
|
||||||
#include <LibJS/Runtime/Error.h>
|
#include <LibJS/Runtime/Error.h>
|
||||||
#include <LibJS/Runtime/GeneratorObject.h>
|
#include <LibJS/Runtime/GeneratorObject.h>
|
||||||
|
#include <LibJS/Runtime/GeneratorObjectPrototype.h>
|
||||||
#include <LibJS/Runtime/GlobalObject.h>
|
#include <LibJS/Runtime/GlobalObject.h>
|
||||||
#include <LibJS/Runtime/NativeFunction.h>
|
#include <LibJS/Runtime/NativeFunction.h>
|
||||||
#include <LibJS/Runtime/ScriptFunction.h>
|
#include <LibJS/Runtime/ScriptFunction.h>
|
||||||
|
@ -36,7 +37,16 @@ static ScriptFunction* typed_this(VM& vm, GlobalObject& global_object)
|
||||||
|
|
||||||
ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, FunctionKind kind, bool is_strict, bool is_arrow_function)
|
ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, FunctionKind kind, bool is_strict, bool is_arrow_function)
|
||||||
{
|
{
|
||||||
return global_object.heap().allocate<ScriptFunction>(global_object, global_object, name, body, move(parameters), m_function_length, parent_scope, *global_object.function_prototype(), kind, is_strict, is_arrow_function);
|
Object* prototype = nullptr;
|
||||||
|
switch (kind) {
|
||||||
|
case FunctionKind::Regular:
|
||||||
|
prototype = global_object.function_prototype();
|
||||||
|
break;
|
||||||
|
case FunctionKind::Generator:
|
||||||
|
prototype = global_object.generator_function_prototype();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return global_object.heap().allocate<ScriptFunction>(global_object, global_object, name, body, move(parameters), m_function_length, parent_scope, *prototype, kind, is_strict, is_arrow_function);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptFunction::ScriptFunction(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, Object& prototype, FunctionKind kind, bool is_strict, bool is_arrow_function)
|
ScriptFunction::ScriptFunction(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, ScopeObject* parent_scope, Object& prototype, FunctionKind kind, bool is_strict, bool is_arrow_function)
|
||||||
|
@ -57,8 +67,16 @@ void ScriptFunction::initialize(GlobalObject& global_object)
|
||||||
auto& vm = this->vm();
|
auto& vm = this->vm();
|
||||||
Function::initialize(global_object);
|
Function::initialize(global_object);
|
||||||
if (!m_is_arrow_function) {
|
if (!m_is_arrow_function) {
|
||||||
Object* prototype = vm.heap().allocate<Object>(global_object, *global_object.new_script_function_prototype_object_shape());
|
auto* prototype = vm.heap().allocate<Object>(global_object, *global_object.new_script_function_prototype_object_shape());
|
||||||
prototype->define_property(vm.names.constructor, this, Attribute::Writable | Attribute::Configurable);
|
switch (m_kind) {
|
||||||
|
case FunctionKind::Regular:
|
||||||
|
prototype->define_property(vm.names.constructor, this, Attribute::Writable | Attribute::Configurable);
|
||||||
|
break;
|
||||||
|
case FunctionKind::Generator:
|
||||||
|
// prototype is "g1.prototype" in figure-2 (https://tc39.es/ecma262/img/figure-2.png)
|
||||||
|
prototype->set_prototype(global_object.generator_object_prototype());
|
||||||
|
break;
|
||||||
|
}
|
||||||
define_property(vm.names.prototype, prototype, Attribute::Writable);
|
define_property(vm.names.prototype, prototype, Attribute::Writable);
|
||||||
}
|
}
|
||||||
define_native_property(vm.names.length, length_getter, {}, Attribute::Configurable);
|
define_native_property(vm.names.length, length_getter, {}, Attribute::Configurable);
|
||||||
|
@ -205,7 +223,7 @@ Value ScriptFunction::call()
|
||||||
|
|
||||||
Value ScriptFunction::construct(Function&)
|
Value ScriptFunction::construct(Function&)
|
||||||
{
|
{
|
||||||
if (m_is_arrow_function) {
|
if (m_is_arrow_function || m_kind == FunctionKind::Generator) {
|
||||||
vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, m_name);
|
vm().throw_exception<TypeError>(global_object(), ErrorType::NotAConstructor, m_name);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue