mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:07: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/Function.cpp
|
||||
Runtime/FunctionPrototype.cpp
|
||||
Runtime/GeneratorFunctionConstructor.cpp
|
||||
Runtime/GeneratorFunctionPrototype.cpp
|
||||
Runtime/GeneratorObject.cpp
|
||||
Runtime/GeneratorObjectPrototype.cpp
|
||||
Runtime/GlobalObject.cpp
|
||||
Runtime/IndexedProperties.cpp
|
||||
Runtime/IteratorOperations.cpp
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
__JS_ENUMERATE(Error, error, ErrorPrototype, ErrorConstructor, void) \
|
||||
__JS_ENUMERATE(FinalizationRegistry, finalization_registry, FinalizationRegistryPrototype, FinalizationRegistryConstructor, 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(NumberObject, number, NumberPrototype, NumberConstructor, void) \
|
||||
__JS_ENUMERATE(Object, object, ObjectPrototype, ObjectConstructor, void) \
|
||||
|
@ -159,6 +160,9 @@ struct PromiseCapability;
|
|||
class ProxyObject;
|
||||
class ProxyConstructor;
|
||||
|
||||
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct constructor
|
||||
class GeneratorObjectPrototype;
|
||||
|
||||
class TypedArrayConstructor;
|
||||
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()
|
||||
{
|
||||
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&)
|
||||
{
|
||||
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/Interpreter.h>
|
||||
#include <LibJS/Runtime/GeneratorObject.h>
|
||||
#include <LibJS/Runtime/GeneratorObjectPrototype.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
|
||||
namespace JS {
|
||||
|
||||
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_scope = generating_scope;
|
||||
object->m_frame = move(frame);
|
||||
|
@ -22,21 +28,13 @@ GeneratorObject* GeneratorObject::create(GlobalObject& global_object, Value init
|
|||
return object;
|
||||
}
|
||||
|
||||
GeneratorObject::GeneratorObject(GlobalObject& global_object)
|
||||
: Object(*global_object.object_prototype())
|
||||
GeneratorObject::GeneratorObject(GlobalObject&, 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()
|
||||
|
@ -52,18 +50,6 @@ void GeneratorObject::visit_edges(Cell::Visitor& visitor)
|
|||
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)
|
||||
{
|
||||
auto bytecode_interpreter = Bytecode::Interpreter::current();
|
||||
|
@ -138,29 +124,4 @@ Value GeneratorObject::next_impl(VM& vm, GlobalObject& global_object, Optional<V
|
|||
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:
|
||||
static GeneratorObject* create(GlobalObject&, Value, ScriptFunction*, ScopeObject*, Bytecode::RegisterWindow);
|
||||
explicit GeneratorObject(GlobalObject&);
|
||||
GeneratorObject(GlobalObject&, Object& prototype);
|
||||
virtual void initialize(GlobalObject&) override;
|
||||
virtual ~GeneratorObject() 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:
|
||||
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 };
|
||||
ScriptFunction* m_generating_function { nullptr };
|
||||
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/FunctionConstructor.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/IteratorPrototype.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.
|
||||
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) \
|
||||
if (!m_##snake_name##_prototype) \
|
||||
m_##snake_name##_prototype = heap().allocate<ClassName##Prototype>(*this, *this);
|
||||
JS_ENUMERATE_ITERATOR_PROTOTYPES
|
||||
#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;
|
||||
define_native_function(vm.names.gc, gc, 0, 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_TYPED_ARRAYS
|
||||
#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()
|
||||
|
@ -193,6 +206,7 @@ void GlobalObject::visit_edges(Visitor& visitor)
|
|||
visitor.visit(m_new_object_shape);
|
||||
visitor.visit(m_new_script_function_prototype_object_shape);
|
||||
visitor.visit(m_proxy_constructor);
|
||||
visitor.visit(m_generator_object_prototype);
|
||||
|
||||
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \
|
||||
visitor.visit(m_##snake_name##_constructor); \
|
||||
|
|
|
@ -37,6 +37,9 @@ public:
|
|||
// Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype
|
||||
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) \
|
||||
ConstructorName* snake_name##_constructor() { return m_##snake_name##_constructor; } \
|
||||
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
|
||||
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) \
|
||||
ConstructorName* m_##snake_name##_constructor { nullptr }; \
|
||||
Object* m_##snake_name##_prototype { nullptr };
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <LibJS/Runtime/Array.h>
|
||||
#include <LibJS/Runtime/Error.h>
|
||||
#include <LibJS/Runtime/GeneratorObject.h>
|
||||
#include <LibJS/Runtime/GeneratorObjectPrototype.h>
|
||||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/NativeFunction.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)
|
||||
{
|
||||
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)
|
||||
|
@ -57,8 +67,16 @@ void ScriptFunction::initialize(GlobalObject& global_object)
|
|||
auto& vm = this->vm();
|
||||
Function::initialize(global_object);
|
||||
if (!m_is_arrow_function) {
|
||||
Object* 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);
|
||||
auto* prototype = vm.heap().allocate<Object>(global_object, *global_object.new_script_function_prototype_object_shape());
|
||||
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_native_property(vm.names.length, length_getter, {}, Attribute::Configurable);
|
||||
|
@ -205,7 +223,7 @@ Value ScriptFunction::call()
|
|||
|
||||
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);
|
||||
return {};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue