1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:38:11 +00:00

LibJS: Move native objects towards two-pass construction

To make sure that everything is set up correctly in objects before we
start adding properties to them, we split cell allocation into 3 steps:

1. Allocate a cell of appropriate size from the Heap
2. Call the C++ constructor on the cell
3. Call initialize() on the constructed object

The job of initialize() is to define all the initial properties.
Doing it in a second pass guarantees that the Object has a valid Shape
and can find its own GlobalObject.
This commit is contained in:
Andreas Kling 2020-06-20 15:40:48 +02:00
parent e4add19915
commit 64513f3c23
83 changed files with 295 additions and 167 deletions

View file

@ -46,13 +46,23 @@ public:
~Heap(); ~Heap();
template<typename T, typename... Args> template<typename T, typename... Args>
T* allocate(Args&&... args) T* allocate_without_global_object(Args&&... args)
{ {
auto* memory = allocate_cell(sizeof(T)); auto* memory = allocate_cell(sizeof(T));
new (memory) T(forward<Args>(args)...); new (memory) T(forward<Args>(args)...);
return static_cast<T*>(memory); return static_cast<T*>(memory);
} }
template<typename T, typename... Args>
T* allocate(GlobalObject& global_object, Args&&... args)
{
auto* memory = allocate_cell(sizeof(T));
new (memory) T(forward<Args>(args)...);
auto* cell = static_cast<T*>(memory);
cell->initialize(m_interpreter, global_object);
return cell;
}
enum class CollectionType { enum class CollectionType {
CollectGarbage, CollectGarbage,
CollectEverything, CollectEverything,

View file

@ -59,7 +59,7 @@ Value Interpreter::run(GlobalObject& global_object, const Statement& statement,
CallFrame global_call_frame; CallFrame global_call_frame;
global_call_frame.this_value = &global_object; global_call_frame.this_value = &global_object;
global_call_frame.function_name = "(global execution context)"; global_call_frame.function_name = "(global execution context)";
global_call_frame.environment = heap().allocate<LexicalEnvironment>(); global_call_frame.environment = heap().allocate<LexicalEnvironment>(global_object);
m_call_stack.append(move(global_call_frame)); m_call_stack.append(move(global_call_frame));
} }
} }
@ -126,7 +126,7 @@ void Interpreter::enter_scope(const ScopeNode& scope_node, ArgumentVector argume
bool pushed_lexical_environment = false; bool pushed_lexical_environment = false;
if (!scope_variables_with_declaration_kind.is_empty()) { if (!scope_variables_with_declaration_kind.is_empty()) {
auto* block_lexical_environment = heap().allocate<LexicalEnvironment>(move(scope_variables_with_declaration_kind), current_environment()); auto* block_lexical_environment = heap().allocate<LexicalEnvironment>(global_object, move(scope_variables_with_declaration_kind), current_environment());
m_call_stack.last().environment = block_lexical_environment; m_call_stack.last().environment = block_lexical_environment;
pushed_lexical_environment = true; pushed_lexical_environment = true;
} }

View file

@ -78,7 +78,7 @@ public:
static NonnullOwnPtr<Interpreter> create(Args&&... args) static NonnullOwnPtr<Interpreter> create(Args&&... args)
{ {
auto interpreter = adopt_own(*new Interpreter); auto interpreter = adopt_own(*new Interpreter);
interpreter->m_global_object = interpreter->heap().allocate<GlobalObjectType>(forward<Args>(args)...); interpreter->m_global_object = interpreter->heap().allocate_without_global_object<GlobalObjectType>(forward<Args>(args)...);
static_cast<GlobalObjectType*>(interpreter->m_global_object)->initialize(); static_cast<GlobalObjectType*>(interpreter->m_global_object)->initialize();
return interpreter; return interpreter;
} }
@ -173,7 +173,7 @@ public:
Value throw_exception(Exception*); Value throw_exception(Exception*);
Value throw_exception(Value value) Value throw_exception(Value value)
{ {
return throw_exception(heap().allocate<Exception>(value)); return throw_exception(heap().allocate<Exception>(global_object(), value));
} }
template<typename T, typename... Args> template<typename T, typename... Args>

View file

@ -37,7 +37,7 @@ class Accessor final : public Cell {
public: public:
static Accessor* create(Interpreter& interpreter, Function* getter, Function* setter) static Accessor* create(Interpreter& interpreter, Function* getter, Function* setter)
{ {
return interpreter.heap().allocate<Accessor>(getter, setter); return interpreter.heap().allocate<Accessor>(interpreter.global_object(), getter, setter);
} }
Accessor(Function* getter, Function* setter) Accessor(Function* getter, Function* setter)

View file

@ -36,7 +36,7 @@ namespace JS {
Array* Array::create(GlobalObject& global_object) Array* Array::create(GlobalObject& global_object)
{ {
auto& interpreter = global_object.interpreter(); auto& interpreter = global_object.interpreter();
return interpreter.heap().allocate<Array>(*global_object.array_prototype()); return interpreter.heap().allocate<Array>(global_object, *global_object.array_prototype());
} }
Array::Array(Object& prototype) Array::Array(Object& prototype)

View file

@ -36,10 +36,20 @@
namespace JS { namespace JS {
ArrayConstructor::ArrayConstructor() ArrayConstructor::ArrayConstructor(GlobalObject& global_object)
: NativeFunction("Array", *interpreter().global_object().function_prototype()) : NativeFunction("Array", *global_object.function_prototype())
{ {
define_property("prototype", interpreter().global_object().array_prototype(), 0); }
ArrayConstructor::~ArrayConstructor()
{
}
void ArrayConstructor::initialize(Interpreter& interpreter, GlobalObject& global_object)
{
NativeFunction::initialize(interpreter, global_object);
define_property("prototype", global_object.array_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property("length", Value(1), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
@ -47,10 +57,6 @@ ArrayConstructor::ArrayConstructor()
define_native_function("of", of, 0, attr); define_native_function("of", of, 0, attr);
} }
ArrayConstructor::~ArrayConstructor()
{
}
Value ArrayConstructor::call(Interpreter& interpreter) Value ArrayConstructor::call(Interpreter& interpreter)
{ {
if (interpreter.argument_count() <= 0) if (interpreter.argument_count() <= 0)

View file

@ -32,7 +32,8 @@ namespace JS {
class ArrayConstructor final : public NativeFunction { class ArrayConstructor final : public NativeFunction {
public: public:
ArrayConstructor(); explicit ArrayConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ArrayConstructor() override; virtual ~ArrayConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -41,8 +41,12 @@
namespace JS { namespace JS {
ArrayPrototype::ArrayPrototype() ArrayPrototype::ArrayPrototype(GlobalObject& global_object)
: Object(interpreter().global_object().object_prototype()) : Object(global_object.object_prototype())
{
}
void ArrayPrototype::initialize(Interpreter&, GlobalObject&)
{ {
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;

View file

@ -33,7 +33,8 @@ namespace JS {
class ArrayPrototype final : public Object { class ArrayPrototype final : public Object {
public: public:
ArrayPrototype(); ArrayPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ArrayPrototype() override; virtual ~ArrayPrototype() override;
private: private:

View file

@ -42,7 +42,7 @@ BigInt::~BigInt()
BigInt* js_bigint(Heap& heap, Crypto::SignedBigInteger big_integer) BigInt* js_bigint(Heap& heap, Crypto::SignedBigInteger big_integer)
{ {
return heap.allocate<BigInt>(move(big_integer)); return heap.allocate<BigInt>(heap.interpreter().global_object(), move(big_integer));
} }
BigInt* js_bigint(Interpreter& interpreter, Crypto::SignedBigInteger big_integer) BigInt* js_bigint(Interpreter& interpreter, Crypto::SignedBigInteger big_integer)

View file

@ -34,10 +34,14 @@
namespace JS { namespace JS {
BigIntConstructor::BigIntConstructor() BigIntConstructor::BigIntConstructor(GlobalObject& global_object)
: NativeFunction("BigInt", *interpreter().global_object().function_prototype()) : NativeFunction("BigInt", *global_object.function_prototype())
{ {
define_property("prototype", interpreter().global_object().bigint_prototype(), 0); }
void BigIntConstructor::initialize(Interpreter&, GlobalObject& global_object)
{
define_property("prototype", global_object.bigint_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property("length", Value(1), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;

View file

@ -32,7 +32,8 @@ namespace JS {
class BigIntConstructor final : public NativeFunction { class BigIntConstructor final : public NativeFunction {
public: public:
BigIntConstructor(); explicit BigIntConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~BigIntConstructor() override; virtual ~BigIntConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -33,7 +33,7 @@ namespace JS {
BigIntObject* BigIntObject::create(GlobalObject& global_object, BigInt& bigint) BigIntObject* BigIntObject::create(GlobalObject& global_object, BigInt& bigint)
{ {
return global_object.heap().allocate<BigIntObject>(bigint, *global_object.bigint_prototype()); return global_object.heap().allocate<BigIntObject>(global_object, bigint, *global_object.bigint_prototype());
} }
BigIntObject::BigIntObject(BigInt& bigint, Object& prototype) BigIntObject::BigIntObject(BigInt& bigint, Object& prototype)

View file

@ -32,8 +32,12 @@
namespace JS { namespace JS {
BigIntPrototype::BigIntPrototype() BigIntPrototype::BigIntPrototype(GlobalObject& global_object)
: Object(interpreter().global_object().object_prototype()) : Object(global_object.object_prototype())
{
}
void BigIntPrototype::initialize(Interpreter&, GlobalObject&)
{ {
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("toString", to_string, 0, attr); define_native_function("toString", to_string, 0, attr);

View file

@ -32,7 +32,8 @@ namespace JS {
class BigIntPrototype final : public Object { class BigIntPrototype final : public Object {
public: public:
BigIntPrototype(); explicit BigIntPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~BigIntPrototype() override; virtual ~BigIntPrototype() override;
private: private:

View file

@ -33,10 +33,14 @@
namespace JS { namespace JS {
BooleanConstructor::BooleanConstructor() BooleanConstructor::BooleanConstructor(GlobalObject& global_object)
: NativeFunction("Boolean", *interpreter().global_object().function_prototype()) : NativeFunction("Boolean", *global_object.function_prototype())
{ {
define_property("prototype", Value(interpreter().global_object().boolean_prototype()), 0); }
void BooleanConstructor::initialize(Interpreter&, GlobalObject& global_object)
{
define_property("prototype", Value(global_object.boolean_prototype()), 0);
define_property("length", Value(1), Attribute::Configurable); define_property("length", Value(1), Attribute::Configurable);
} }

View file

@ -32,7 +32,8 @@ namespace JS {
class BooleanConstructor final : public NativeFunction { class BooleanConstructor final : public NativeFunction {
public: public:
BooleanConstructor(); explicit BooleanConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~BooleanConstructor() override; virtual ~BooleanConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -33,7 +33,7 @@ namespace JS {
BooleanObject* BooleanObject::create(GlobalObject& global_object, bool value) BooleanObject* BooleanObject::create(GlobalObject& global_object, bool value)
{ {
auto& interpreter = global_object.interpreter(); auto& interpreter = global_object.interpreter();
return interpreter.heap().allocate<BooleanObject>(value, *global_object.boolean_prototype()); return interpreter.heap().allocate<BooleanObject>(global_object, value, *global_object.boolean_prototype());
} }
BooleanObject::BooleanObject(bool value, Object& prototype) BooleanObject::BooleanObject(bool value, Object& prototype)

View file

@ -32,8 +32,12 @@
namespace JS { namespace JS {
BooleanPrototype::BooleanPrototype() BooleanPrototype::BooleanPrototype(GlobalObject& global_object)
: BooleanObject(false, *interpreter().global_object().object_prototype()) : BooleanObject(false, *global_object.object_prototype())
{
}
void BooleanPrototype::initialize(Interpreter&, GlobalObject&)
{ {
define_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable); define_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable);
define_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable); define_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable);

View file

@ -32,7 +32,8 @@ namespace JS {
class BooleanPrototype final : public BooleanObject { class BooleanPrototype final : public BooleanObject {
public: public:
BooleanPrototype(); explicit BooleanPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~BooleanPrototype() override; virtual ~BooleanPrototype() override;
private: private:

View file

@ -37,7 +37,8 @@ class Cell {
AK_MAKE_NONMOVABLE(Cell); AK_MAKE_NONMOVABLE(Cell);
public: public:
virtual ~Cell() {} virtual void initialize(Interpreter&, GlobalObject&) { }
virtual ~Cell() { }
bool is_marked() const { return m_mark; } bool is_marked() const { return m_mark; }
void set_marked(bool b) { m_mark = b; } void set_marked(bool b) { m_mark = b; }
@ -56,14 +57,14 @@ public:
virtual void visit_impl(Cell*) = 0; virtual void visit_impl(Cell*) = 0;
}; };
virtual void visit_children(Visitor&) {} virtual void visit_children(Visitor&) { }
Heap& heap() const; Heap& heap() const;
Interpreter& interpreter(); Interpreter& interpreter();
Interpreter& interpreter() const; Interpreter& interpreter() const;
protected: protected:
Cell() {} Cell() { }
private: private:
bool m_mark { false }; bool m_mark { false };

View file

@ -34,7 +34,7 @@ namespace JS {
Date* Date::create(GlobalObject& global_object, Core::DateTime datetime, u16 milliseconds) Date* Date::create(GlobalObject& global_object, Core::DateTime datetime, u16 milliseconds)
{ {
return global_object.heap().allocate<Date>(datetime, milliseconds, *global_object.date_prototype()); return global_object.heap().allocate<Date>(global_object, datetime, milliseconds, *global_object.date_prototype());
} }
Date::Date(Core::DateTime datetime, u16 milliseconds, Object& prototype) Date::Date(Core::DateTime datetime, u16 milliseconds, Object& prototype)

View file

@ -34,8 +34,12 @@
namespace JS { namespace JS {
DateConstructor::DateConstructor() DateConstructor::DateConstructor(GlobalObject& global_object)
: NativeFunction("Date", *interpreter().global_object().function_prototype()) : NativeFunction("Date", *global_object.function_prototype())
{
}
void DateConstructor::initialize(Interpreter&, GlobalObject&)
{ {
define_property("prototype", interpreter().global_object().date_prototype(), 0); define_property("prototype", interpreter().global_object().date_prototype(), 0);
define_property("length", Value(7), Attribute::Configurable); define_property("length", Value(7), Attribute::Configurable);

View file

@ -32,7 +32,8 @@ namespace JS {
class DateConstructor final : public NativeFunction { class DateConstructor final : public NativeFunction {
public: public:
DateConstructor(); explicit DateConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~DateConstructor() override; virtual ~DateConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -48,8 +48,12 @@ static Date* this_date_from_interpreter(Interpreter& interpreter)
return static_cast<Date*>(this_object); return static_cast<Date*>(this_object);
} }
DatePrototype::DatePrototype() DatePrototype::DatePrototype(GlobalObject& global_object)
: Object(interpreter().global_object().object_prototype()) : Object(global_object.object_prototype())
{
}
void DatePrototype::initialize(Interpreter&, GlobalObject&)
{ {
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("getDate", get_date, 0, attr); define_native_function("getDate", get_date, 0, attr);

View file

@ -32,7 +32,8 @@ namespace JS {
class DatePrototype final : public Object { class DatePrototype final : public Object {
public: public:
DatePrototype(); explicit DatePrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~DatePrototype() override; virtual ~DatePrototype() override;
private: private:

View file

@ -33,7 +33,7 @@ namespace JS {
Error* Error::create(GlobalObject& global_object, const FlyString& name, const String& message) Error* Error::create(GlobalObject& global_object, const FlyString& name, const String& message)
{ {
auto& interpreter = global_object.interpreter(); auto& interpreter = global_object.interpreter();
return interpreter.heap().allocate<Error>(name, message, *global_object.error_prototype()); return interpreter.heap().allocate<Error>(global_object, name, message, *global_object.error_prototype());
} }
Error::Error(const FlyString& name, const String& message, Object& prototype) Error::Error(const FlyString& name, const String& message, Object& prototype)
@ -47,16 +47,16 @@ Error::~Error()
{ {
} }
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \ #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
ClassName* ClassName::create(GlobalObject& global_object, const String& message) \ ClassName* ClassName::create(GlobalObject& global_object, const String& message) \
{ \ { \
return global_object.heap().allocate<ClassName>(message, *global_object.snake_name##_prototype()); \ return global_object.heap().allocate<ClassName>(global_object, message, *global_object.snake_name##_prototype()); \
} \ } \
ClassName::ClassName(const String& message, Object& prototype) \ ClassName::ClassName(const String& message, Object& prototype) \
: Error(#ClassName, message, prototype) \ : Error(#ClassName, message, prototype) \
{ \ { \
} \ } \
ClassName::~ClassName() { } \ ClassName::~ClassName() { } \
const char* ClassName::class_name() const { return #ClassName; } const char* ClassName::class_name() const { return #ClassName; }
JS_ENUMERATE_ERROR_SUBCLASSES JS_ENUMERATE_ERROR_SUBCLASSES

View file

@ -31,10 +31,14 @@
namespace JS { namespace JS {
ErrorConstructor::ErrorConstructor() ErrorConstructor::ErrorConstructor(GlobalObject& global_object)
: NativeFunction("Error", *interpreter().global_object().function_prototype()) : NativeFunction("Error", *global_object.function_prototype())
{ {
define_property("prototype", interpreter().global_object().error_prototype(), 0); }
void ErrorConstructor::initialize(Interpreter&, GlobalObject& global_object)
{
define_property("prototype", global_object.error_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property("length", Value(1), Attribute::Configurable);
} }
@ -59,10 +63,13 @@ Value ErrorConstructor::construct(Interpreter& interpreter)
} }
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \ #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
ConstructorName::ConstructorName() \ ConstructorName::ConstructorName(GlobalObject& global_object) \
: NativeFunction(*interpreter().global_object().function_prototype()) \ : NativeFunction(*global_object.function_prototype()) \
{ \ { \
define_property("prototype", interpreter().global_object().snake_name##_prototype(), 0); \ } \
void ConstructorName::initialize(Interpreter&, GlobalObject& global_object) \
{ \
define_property("prototype", global_object.snake_name##_prototype(), 0); \
define_property("length", Value(1), Attribute::Configurable); \ define_property("length", Value(1), Attribute::Configurable); \
} \ } \
ConstructorName::~ConstructorName() { } \ ConstructorName::~ConstructorName() { } \

View file

@ -33,7 +33,8 @@ namespace JS {
class ErrorConstructor final : public NativeFunction { class ErrorConstructor final : public NativeFunction {
public: public:
ErrorConstructor(); explicit ErrorConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ErrorConstructor() override; virtual ~ErrorConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;
@ -47,7 +48,8 @@ private:
#define DECLARE_ERROR_SUBCLASS_CONSTRUCTOR(ClassName, snake_name, PrototypeName, ConstructorName) \ #define DECLARE_ERROR_SUBCLASS_CONSTRUCTOR(ClassName, snake_name, PrototypeName, ConstructorName) \
class ConstructorName final : public NativeFunction { \ class ConstructorName final : public NativeFunction { \
public: \ public: \
ConstructorName(); \ explicit ConstructorName(GlobalObject&); \
virtual void initialize(Interpreter&, GlobalObject&) override; \
virtual ~ConstructorName() override; \ virtual ~ConstructorName() override; \
virtual Value call(Interpreter&) override; \ virtual Value call(Interpreter&) override; \
virtual Value construct(Interpreter&) override; \ virtual Value construct(Interpreter&) override; \

View file

@ -35,8 +35,12 @@
namespace JS { namespace JS {
ErrorPrototype::ErrorPrototype() ErrorPrototype::ErrorPrototype(GlobalObject& global_object)
: Object(interpreter().global_object().object_prototype()) : Object(global_object.object_prototype())
{
}
void ErrorPrototype::initialize(Interpreter&, GlobalObject&)
{ {
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_property("name", name_getter, name_setter, attr); define_native_property("name", name_getter, name_setter, attr);
@ -117,8 +121,8 @@ JS_DEFINE_NATIVE_FUNCTION(ErrorPrototype::to_string)
} }
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \ #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
PrototypeName::PrototypeName() \ PrototypeName::PrototypeName(GlobalObject& global_object) \
: Object(interpreter().global_object().error_prototype()) \ : Object(global_object.error_prototype()) \
{ \ { \
} \ } \
PrototypeName::~PrototypeName() { } \ PrototypeName::~PrototypeName() { } \

View file

@ -32,7 +32,8 @@ namespace JS {
class ErrorPrototype final : public Object { class ErrorPrototype final : public Object {
public: public:
ErrorPrototype(); explicit ErrorPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ErrorPrototype() override; virtual ~ErrorPrototype() override;
private: private:
@ -49,7 +50,8 @@ private:
#define DECLARE_ERROR_SUBCLASS_PROTOTYPE(ClassName, snake_name, PrototypeName, ConstructorName) \ #define DECLARE_ERROR_SUBCLASS_PROTOTYPE(ClassName, snake_name, PrototypeName, ConstructorName) \
class PrototypeName final : public Object { \ class PrototypeName final : public Object { \
public: \ public: \
PrototypeName(); \ explicit PrototypeName(GlobalObject&); \
virtual void initialize(Interpreter&, GlobalObject&) override { } \
virtual ~PrototypeName() override; \ virtual ~PrototypeName() override; \
\ \
private: \ private: \

View file

@ -82,7 +82,7 @@ BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments)
auto all_bound_arguments = bound_arguments(); auto all_bound_arguments = bound_arguments();
all_bound_arguments.append(move(arguments)); all_bound_arguments.append(move(arguments));
return interpreter().heap().allocate<BoundFunction>(target_function, bound_this_object, move(all_bound_arguments), computed_length, constructor_prototype); return interpreter().heap().allocate<BoundFunction>(global_object(), target_function, bound_this_object, move(all_bound_arguments), computed_length, constructor_prototype);
} }
void Function::visit_children(Visitor& visitor) void Function::visit_children(Visitor& visitor)

View file

@ -34,6 +34,7 @@ namespace JS {
class Function : public Object { class Function : public Object {
public: public:
virtual ~Function(); virtual ~Function();
virtual void initialize(Interpreter&, GlobalObject&) override { }
virtual Value call(Interpreter&) = 0; virtual Value call(Interpreter&) = 0;
virtual Value construct(Interpreter&) = 0; virtual Value construct(Interpreter&) = 0;

View file

@ -35,10 +35,14 @@
namespace JS { namespace JS {
FunctionConstructor::FunctionConstructor() FunctionConstructor::FunctionConstructor(GlobalObject& global_object)
: NativeFunction("Function", *interpreter().global_object().function_prototype()) : NativeFunction("Function", *global_object.function_prototype())
{ {
define_property("prototype", interpreter().global_object().function_prototype(), 0); }
void FunctionConstructor::initialize(Interpreter&, GlobalObject& global_object)
{
define_property("prototype", global_object.function_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property("length", Value(1), Attribute::Configurable);
} }

View file

@ -32,7 +32,8 @@ namespace JS {
class FunctionConstructor final : public NativeFunction { class FunctionConstructor final : public NativeFunction {
public: public:
FunctionConstructor(); explicit FunctionConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~FunctionConstructor() override; virtual ~FunctionConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -38,12 +38,12 @@
namespace JS { namespace JS {
FunctionPrototype::FunctionPrototype() FunctionPrototype::FunctionPrototype(GlobalObject& global_object)
: Object(interpreter().global_object().object_prototype()) : Object(global_object.object_prototype())
{ {
} }
void FunctionPrototype::initialize() void FunctionPrototype::initialize(Interpreter&, GlobalObject&)
{ {
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("apply", apply, 2, attr); define_native_function("apply", apply, 2, attr);

View file

@ -32,9 +32,8 @@ namespace JS {
class FunctionPrototype final : public Object { class FunctionPrototype final : public Object {
public: public:
FunctionPrototype(); explicit FunctionPrototype(GlobalObject&);
void initialize(); virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~FunctionPrototype() override; virtual ~FunctionPrototype() override;
private: private:

View file

@ -71,16 +71,16 @@ GlobalObject::GlobalObject()
void GlobalObject::initialize() void GlobalObject::initialize()
{ {
// These are done first since other prototypes depend on their presence. // These are done first since other prototypes depend on their presence.
m_empty_object_shape = heap().allocate<Shape>(*this); m_empty_object_shape = heap().allocate<Shape>(*this, *this);
m_object_prototype = heap().allocate<ObjectPrototype>(); m_object_prototype = heap().allocate_without_global_object<ObjectPrototype>(*this);
m_function_prototype = heap().allocate<FunctionPrototype>(); m_function_prototype = heap().allocate_without_global_object<FunctionPrototype>(*this);
static_cast<FunctionPrototype*>(m_function_prototype)->initialize(); static_cast<FunctionPrototype*>(m_function_prototype)->initialize(heap().interpreter(), *this);
static_cast<ObjectPrototype*>(m_object_prototype)->initialize(); static_cast<ObjectPrototype*>(m_object_prototype)->initialize(heap().interpreter(), *this);
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \ #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
if (!m_##snake_name##_prototype) \ if (!m_##snake_name##_prototype) \
m_##snake_name##_prototype = heap().allocate<PrototypeName>(); m_##snake_name##_prototype = heap().allocate<PrototypeName>(*this, *this);
JS_ENUMERATE_BUILTIN_TYPES JS_ENUMERATE_BUILTIN_TYPES
#undef __JS_ENUMERATE #undef __JS_ENUMERATE
@ -95,10 +95,10 @@ void GlobalObject::initialize()
define_property("undefined", js_undefined(), 0); define_property("undefined", js_undefined(), 0);
define_property("globalThis", this, attr); define_property("globalThis", this, attr);
define_property("console", heap().allocate<ConsoleObject>(), attr); define_property("console", heap().allocate<ConsoleObject>(*this), attr);
define_property("Math", heap().allocate<MathObject>(), attr); define_property("Math", heap().allocate<MathObject>(*this), attr);
define_property("JSON", heap().allocate<JSONObject>(), attr); define_property("JSON", heap().allocate<JSONObject>(*this), attr);
define_property("Reflect", heap().allocate<ReflectObject>(), attr); define_property("Reflect", heap().allocate<ReflectObject>(*this), attr);
add_constructor("Array", m_array_constructor, *m_array_prototype); add_constructor("Array", m_array_constructor, *m_array_prototype);
add_constructor("BigInt", m_bigint_constructor, *m_bigint_prototype); add_constructor("BigInt", m_bigint_constructor, *m_bigint_prototype);

View file

@ -72,7 +72,7 @@ private:
template<typename ConstructorType> template<typename ConstructorType>
inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object& prototype) inline void GlobalObject::add_constructor(const FlyString& property_name, ConstructorType*& constructor, Object& prototype)
{ {
constructor = heap().allocate<ConstructorType>(); constructor = heap().allocate<ConstructorType>(*this, *this);
constructor->define_property("name", js_string(heap(), property_name), Attribute::Configurable); constructor->define_property("name", js_string(heap(), property_name), Attribute::Configurable);
if (interpreter().exception()) if (interpreter().exception())
return; return;

View file

@ -33,7 +33,7 @@ namespace JS {
NativeFunction* NativeFunction::create(Interpreter&, GlobalObject& global_object, const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)> function) NativeFunction* NativeFunction::create(Interpreter&, GlobalObject& global_object, const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)> function)
{ {
return global_object.heap().allocate<NativeFunction>(name, move(function), *global_object.function_prototype()); return global_object.heap().allocate<NativeFunction>(global_object, name, move(function), *global_object.function_prototype());
} }
NativeFunction::NativeFunction(Object& prototype) NativeFunction::NativeFunction(Object& prototype)

View file

@ -36,6 +36,7 @@ public:
static NativeFunction* create(Interpreter&, GlobalObject&, const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)>); static NativeFunction* create(Interpreter&, GlobalObject&, const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)>);
explicit NativeFunction(const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)>, Object& prototype); explicit NativeFunction(const FlyString& name, AK::Function<Value(Interpreter&, GlobalObject&)>, Object& prototype);
virtual void initialize(Interpreter&, GlobalObject&) override { }
virtual ~NativeFunction() override; virtual ~NativeFunction() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -37,8 +37,12 @@
namespace JS { namespace JS {
NumberConstructor::NumberConstructor() NumberConstructor::NumberConstructor(GlobalObject& global_object)
: NativeFunction("Number", *interpreter().global_object().function_prototype()) : NativeFunction("Number", *global_object.function_prototype())
{
}
void NumberConstructor::initialize(Interpreter&, GlobalObject&)
{ {
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("isFinite", is_finite, 1, attr); define_native_function("isFinite", is_finite, 1, attr);

View file

@ -32,7 +32,8 @@ namespace JS {
class NumberConstructor final : public NativeFunction { class NumberConstructor final : public NativeFunction {
public: public:
NumberConstructor(); explicit NumberConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~NumberConstructor() override; virtual ~NumberConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -35,7 +35,7 @@ namespace JS {
NumberObject* NumberObject::create(GlobalObject& global_object, double value) NumberObject* NumberObject::create(GlobalObject& global_object, double value)
{ {
return global_object.heap().allocate<NumberObject>(value, *global_object.number_prototype()); return global_object.heap().allocate<NumberObject>(global_object, value, *global_object.number_prototype());
} }
NumberObject::NumberObject(double value, Object& prototype) NumberObject::NumberObject(double value, Object& prototype)

View file

@ -30,8 +30,8 @@
namespace JS { namespace JS {
NumberPrototype::NumberPrototype() NumberPrototype::NumberPrototype(GlobalObject& global_object)
: NumberObject(0, *interpreter().global_object().object_prototype()) : NumberObject(0, *global_object.object_prototype())
{ {
} }

View file

@ -32,7 +32,7 @@ namespace JS {
class NumberPrototype final : public NumberObject { class NumberPrototype final : public NumberObject {
public: public:
NumberPrototype(); explicit NumberPrototype(GlobalObject&);
virtual ~NumberPrototype() override; virtual ~NumberPrototype() override;
private: private:

View file

@ -82,7 +82,7 @@ PropertyDescriptor PropertyDescriptor::from_dictionary(Interpreter& interpreter,
Object* Object::create_empty(Interpreter&, GlobalObject& global_object) Object* Object::create_empty(Interpreter&, GlobalObject& global_object)
{ {
return global_object.heap().allocate<Object>(global_object.object_prototype()); return global_object.heap().allocate<Object>(global_object, global_object.object_prototype());
} }
Object::Object(Object* prototype) Object::Object(Object* prototype)
@ -92,10 +92,14 @@ Object::Object(Object* prototype)
set_prototype(prototype); set_prototype(prototype);
} else { } else {
// This is the global object // This is the global object
m_shape = interpreter().heap().allocate<Shape>(static_cast<GlobalObject&>(*this)); m_shape = interpreter().heap().allocate<Shape>(static_cast<GlobalObject&>(*this), static_cast<GlobalObject&>(*this));
} }
} }
void Object::initialize(Interpreter&, GlobalObject&)
{
}
Object::~Object() Object::~Object()
{ {
} }
@ -694,7 +698,7 @@ bool Object::define_native_function(const FlyString& property_name, AK::Function
bool Object::define_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter, PropertyAttributes attribute) bool Object::define_native_property(const FlyString& property_name, AK::Function<Value(Interpreter&, GlobalObject&)> getter, AK::Function<void(Interpreter&, GlobalObject&, Value)> setter, PropertyAttributes attribute)
{ {
return define_property(property_name, heap().allocate<NativeProperty>(move(getter), move(setter)), attribute); return define_property(property_name, heap().allocate<NativeProperty>(global_object(), move(getter), move(setter)), attribute);
} }
void Object::visit_children(Cell::Visitor& visitor) void Object::visit_children(Cell::Visitor& visitor)

View file

@ -57,6 +57,7 @@ public:
static Object* create_empty(Interpreter&, GlobalObject&); static Object* create_empty(Interpreter&, GlobalObject&);
explicit Object(Object* prototype); explicit Object(Object* prototype);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~Object(); virtual ~Object();
enum class GetOwnPropertyMode { enum class GetOwnPropertyMode {

View file

@ -35,10 +35,14 @@
namespace JS { namespace JS {
ObjectConstructor::ObjectConstructor() ObjectConstructor::ObjectConstructor(GlobalObject& global_object)
: NativeFunction("Object", *interpreter().global_object().function_prototype()) : NativeFunction("Object", *global_object.function_prototype())
{ {
define_property("prototype", interpreter().global_object().object_prototype(), 0); }
void ObjectConstructor::initialize(Interpreter&, GlobalObject& global_object)
{
define_property("prototype", global_object.object_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property("length", Value(1), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;

View file

@ -32,7 +32,8 @@ namespace JS {
class ObjectConstructor final : public NativeFunction { class ObjectConstructor final : public NativeFunction {
public: public:
ObjectConstructor(); explicit ObjectConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ObjectConstructor() override; virtual ~ObjectConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -34,12 +34,12 @@
namespace JS { namespace JS {
ObjectPrototype::ObjectPrototype() ObjectPrototype::ObjectPrototype(GlobalObject&)
: Object(nullptr) : Object(nullptr)
{ {
} }
void ObjectPrototype::initialize() void ObjectPrototype::initialize(Interpreter&, GlobalObject&)
{ {
// This must be called after the constructor has returned, so that the below code // This must be called after the constructor has returned, so that the below code
// can find the ObjectPrototype through normal paths. // can find the ObjectPrototype through normal paths.

View file

@ -32,9 +32,8 @@ namespace JS {
class ObjectPrototype final : public Object { class ObjectPrototype final : public Object {
public: public:
ObjectPrototype(); explicit ObjectPrototype(GlobalObject&);
void initialize(); virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ObjectPrototype() override; virtual ~ObjectPrototype() override;
// public to serve as intrinsic function %Object.prototype.toString% // public to serve as intrinsic function %Object.prototype.toString%

View file

@ -41,7 +41,7 @@ PrimitiveString::~PrimitiveString()
PrimitiveString* js_string(Heap& heap, String string) PrimitiveString* js_string(Heap& heap, String string)
{ {
return heap.allocate<PrimitiveString>(move(string)); return heap.allocate<PrimitiveString>(heap.interpreter().global_object(), move(string));
} }
PrimitiveString* js_string(Interpreter& interpreter, String string) PrimitiveString* js_string(Interpreter& interpreter, String string)

View file

@ -33,10 +33,14 @@
namespace JS { namespace JS {
ProxyConstructor::ProxyConstructor() ProxyConstructor::ProxyConstructor(GlobalObject& global_object)
: NativeFunction("Proxy", *interpreter().global_object().function_prototype()) : NativeFunction("Proxy", *global_object.function_prototype())
{ {
define_property("prototype", interpreter().global_object().proxy_prototype(), 0); }
void ProxyConstructor::initialize(Interpreter&, GlobalObject& global_object)
{
define_property("prototype", global_object.proxy_prototype(), 0);
define_property("length", Value(2), Attribute::Configurable); define_property("length", Value(2), Attribute::Configurable);
} }

View file

@ -32,7 +32,8 @@ namespace JS {
class ProxyConstructor final : public NativeFunction { class ProxyConstructor final : public NativeFunction {
public: public:
ProxyConstructor(); explicit ProxyConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ProxyConstructor() override; virtual ~ProxyConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -59,7 +59,7 @@ bool static is_compatible_property_descriptor(Interpreter& interpreter, bool is_
ProxyObject* ProxyObject::create(GlobalObject& global_object, Object& target, Object& handler) ProxyObject* ProxyObject::create(GlobalObject& global_object, Object& target, Object& handler)
{ {
return global_object.heap().allocate<ProxyObject>(target, handler, *global_object.proxy_prototype()); return global_object.heap().allocate<ProxyObject>(global_object, target, handler, *global_object.proxy_prototype());
} }
ProxyObject::ProxyObject(Object& target, Object& handler, Object& prototype) ProxyObject::ProxyObject(Object& target, Object& handler, Object& prototype)

View file

@ -34,8 +34,8 @@
namespace JS { namespace JS {
ProxyPrototype::ProxyPrototype() ProxyPrototype::ProxyPrototype(GlobalObject& global_object)
: Object(interpreter().global_object().object_prototype()) : Object(global_object.object_prototype())
{ {
} }

View file

@ -32,7 +32,7 @@ namespace JS {
class ProxyPrototype final : public Object { class ProxyPrototype final : public Object {
public: public:
ProxyPrototype(); explicit ProxyPrototype(GlobalObject&);
virtual ~ProxyPrototype() override; virtual ~ProxyPrototype() override;
private: private:

View file

@ -32,10 +32,14 @@
namespace JS { namespace JS {
RegExpConstructor::RegExpConstructor() RegExpConstructor::RegExpConstructor(GlobalObject& global_object)
: NativeFunction("RegExp", *interpreter().global_object().function_prototype()) : NativeFunction("RegExp", *global_object.function_prototype())
{ {
define_property("prototype", interpreter().global_object().regexp_prototype(), 0); }
void RegExpConstructor::initialize(Interpreter&, GlobalObject& global_object)
{
define_property("prototype", global_object.regexp_prototype(), 0);
define_property("length", Value(2), Attribute::Configurable); define_property("length", Value(2), Attribute::Configurable);
} }

View file

@ -32,7 +32,8 @@ namespace JS {
class RegExpConstructor final : public NativeFunction { class RegExpConstructor final : public NativeFunction {
public: public:
RegExpConstructor(); explicit RegExpConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~RegExpConstructor() override; virtual ~RegExpConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -37,7 +37,7 @@ namespace JS {
RegExpObject* RegExpObject::create(GlobalObject& global_object, String content, String flags) RegExpObject* RegExpObject::create(GlobalObject& global_object, String content, String flags)
{ {
return global_object.heap().allocate<RegExpObject>(content, flags, *global_object.regexp_prototype()); return global_object.heap().allocate<RegExpObject>(global_object, content, flags, *global_object.regexp_prototype());
} }
RegExpObject::RegExpObject(String content, String flags, Object& prototype) RegExpObject::RegExpObject(String content, String flags, Object& prototype)

View file

@ -35,8 +35,8 @@
namespace JS { namespace JS {
RegExpPrototype::RegExpPrototype() RegExpPrototype::RegExpPrototype(GlobalObject& global_object)
: RegExpObject({}, {}, *interpreter().global_object().object_prototype()) : RegExpObject({}, {}, *global_object.object_prototype())
{ {
} }

View file

@ -32,7 +32,7 @@ namespace JS {
class RegExpPrototype final : public RegExpObject { class RegExpPrototype final : public RegExpObject {
public: public:
RegExpPrototype(); explicit RegExpPrototype(GlobalObject&);
virtual ~RegExpPrototype() override; virtual ~RegExpPrototype() override;
private: private:

View file

@ -49,7 +49,7 @@ static ScriptFunction* script_function_from(Interpreter& interpreter)
ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, LexicalEnvironment* parent_environment, bool is_arrow_function) ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, LexicalEnvironment* parent_environment, bool is_arrow_function)
{ {
return global_object.heap().allocate<ScriptFunction>(name, body, move(parameters), m_function_length, parent_environment, *global_object.function_prototype(), is_arrow_function); return global_object.heap().allocate<ScriptFunction>(global_object, name, body, move(parameters), m_function_length, parent_environment, *global_object.function_prototype(), is_arrow_function);
} }
ScriptFunction::ScriptFunction(const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, LexicalEnvironment* parent_environment, Object& prototype, bool is_arrow_function) ScriptFunction::ScriptFunction(const FlyString& name, const Statement& body, Vector<FunctionNode::Parameter> parameters, i32 m_function_length, LexicalEnvironment* parent_environment, Object& prototype, bool is_arrow_function)
@ -93,7 +93,7 @@ LexicalEnvironment* ScriptFunction::create_environment()
} }
if (variables.is_empty()) if (variables.is_empty())
return m_parent_environment; return m_parent_environment;
return heap().allocate<LexicalEnvironment>(move(variables), m_parent_environment); return heap().allocate<LexicalEnvironment>(global_object(), move(variables), m_parent_environment);
} }
Value ScriptFunction::call(Interpreter& interpreter) Value ScriptFunction::call(Interpreter& interpreter)

View file

@ -32,7 +32,7 @@ namespace JS {
Shape* Shape::create_unique_clone() const Shape* Shape::create_unique_clone() const
{ {
auto* new_shape = heap().allocate<Shape>(m_global_object); auto* new_shape = heap().allocate<Shape>(m_global_object, m_global_object);
new_shape->m_unique = true; new_shape->m_unique = true;
new_shape->m_prototype = m_prototype; new_shape->m_prototype = m_prototype;
ensure_property_table(); ensure_property_table();
@ -46,7 +46,7 @@ Shape* Shape::create_put_transition(const FlyString& property_name, PropertyAttr
TransitionKey key { property_name, attributes }; TransitionKey key { property_name, attributes };
if (auto* existing_shape = m_forward_transitions.get(key).value_or(nullptr)) if (auto* existing_shape = m_forward_transitions.get(key).value_or(nullptr))
return existing_shape; return existing_shape;
auto* new_shape = heap().allocate<Shape>(*this, property_name, attributes, TransitionType::Put); auto* new_shape = heap().allocate<Shape>(m_global_object, *this, property_name, attributes, TransitionType::Put);
m_forward_transitions.set(key, new_shape); m_forward_transitions.set(key, new_shape);
return new_shape; return new_shape;
} }
@ -56,14 +56,14 @@ Shape* Shape::create_configure_transition(const FlyString& property_name, Proper
TransitionKey key { property_name, attributes }; TransitionKey key { property_name, attributes };
if (auto* existing_shape = m_forward_transitions.get(key).value_or(nullptr)) if (auto* existing_shape = m_forward_transitions.get(key).value_or(nullptr))
return existing_shape; return existing_shape;
auto* new_shape = heap().allocate<Shape>(*this, property_name, attributes, TransitionType::Configure); auto* new_shape = heap().allocate<Shape>(m_global_object, *this, property_name, attributes, TransitionType::Configure);
m_forward_transitions.set(key, new_shape); m_forward_transitions.set(key, new_shape);
return new_shape; return new_shape;
} }
Shape* Shape::create_prototype_transition(Object* new_prototype) Shape* Shape::create_prototype_transition(Object* new_prototype)
{ {
return heap().allocate<Shape>(*this, new_prototype); return heap().allocate<Shape>(m_global_object, *this, new_prototype);
} }
Shape::Shape(GlobalObject& global_object) Shape::Shape(GlobalObject& global_object)

View file

@ -35,10 +35,14 @@
namespace JS { namespace JS {
StringConstructor::StringConstructor() StringConstructor::StringConstructor(GlobalObject& global_object)
: NativeFunction("String", *interpreter().global_object().function_prototype()) : NativeFunction("String", *global_object.function_prototype())
{ {
define_property("prototype", interpreter().global_object().string_prototype(), 0); }
void StringConstructor::initialize(Interpreter&, GlobalObject& global_object)
{
define_property("prototype", global_object.string_prototype(), 0);
define_property("length", Value(1), Attribute::Configurable); define_property("length", Value(1), Attribute::Configurable);
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;

View file

@ -32,7 +32,8 @@ namespace JS {
class StringConstructor final : public NativeFunction { class StringConstructor final : public NativeFunction {
public: public:
StringConstructor(); explicit StringConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~StringConstructor() override; virtual ~StringConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -36,7 +36,7 @@ namespace JS {
StringObject* StringObject::create(GlobalObject& global_object, PrimitiveString& primitive_string) StringObject* StringObject::create(GlobalObject& global_object, PrimitiveString& primitive_string)
{ {
return global_object.heap().allocate<StringObject>(primitive_string, *global_object.string_prototype()); return global_object.heap().allocate<StringObject>(global_object, primitive_string, *global_object.string_prototype());
} }
StringObject::StringObject(PrimitiveString& string, Object& prototype) StringObject::StringObject(PrimitiveString& string, Object& prototype)

View file

@ -59,8 +59,12 @@ static String string_from(Interpreter& interpreter)
return Value(this_object).to_string(interpreter); return Value(this_object).to_string(interpreter);
} }
StringPrototype::StringPrototype() StringPrototype::StringPrototype(GlobalObject& global_object)
: StringObject(*js_string(interpreter(), String::empty()), *interpreter().global_object().object_prototype()) : StringObject(*js_string(interpreter(), String::empty()), *global_object.object_prototype())
{
}
void StringPrototype::initialize(Interpreter&, GlobalObject&)
{ {
u8 attr = Attribute::Writable | Attribute::Configurable; u8 attr = Attribute::Writable | Attribute::Configurable;

View file

@ -32,7 +32,8 @@ namespace JS {
class StringPrototype final : public StringObject { class StringPrototype final : public StringObject {
public: public:
StringPrototype(); explicit StringPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~StringPrototype() override; virtual ~StringPrototype() override;
private: private:

View file

@ -42,7 +42,7 @@ Symbol::~Symbol()
Symbol* js_symbol(Heap& heap, String description, bool is_global) Symbol* js_symbol(Heap& heap, String description, bool is_global)
{ {
return heap.allocate<Symbol>(move(description), is_global); return heap.allocate<Symbol>(heap.interpreter().global_object(), move(description), is_global);
} }
Symbol* js_symbol(Interpreter& interpreter, String description, bool is_global) Symbol* js_symbol(Interpreter& interpreter, String description, bool is_global)

View file

@ -32,16 +32,20 @@
namespace JS { namespace JS {
SymbolConstructor::SymbolConstructor() SymbolConstructor::SymbolConstructor(GlobalObject& global_object)
: NativeFunction("Symbol", *interpreter().global_object().function_prototype()) : NativeFunction("Symbol", *global_object.function_prototype())
{ {
define_property("prototype", interpreter().global_object().symbol_prototype(), 0); }
void SymbolConstructor::initialize(Interpreter& interpreter, GlobalObject& global_object)
{
define_property("prototype", global_object.symbol_prototype(), 0);
define_property("length", Value(0), Attribute::Configurable); define_property("length", Value(0), Attribute::Configurable);
define_native_function("for", for_, 1, Attribute::Writable | Attribute::Configurable); define_native_function("for", for_, 1, Attribute::Writable | Attribute::Configurable);
define_native_function("keyFor", key_for, 1, Attribute::Writable | Attribute::Configurable); define_native_function("keyFor", key_for, 1, Attribute::Writable | Attribute::Configurable);
SymbolObject::initialize_well_known_symbols(interpreter()); SymbolObject::initialize_well_known_symbols(interpreter);
define_property("iterator", SymbolObject::well_known_iterator(), 0); define_property("iterator", SymbolObject::well_known_iterator(), 0);
define_property("asyncIterator", SymbolObject::well_known_async_terator(), 0); define_property("asyncIterator", SymbolObject::well_known_async_terator(), 0);

View file

@ -32,7 +32,8 @@ namespace JS {
class SymbolConstructor final : public NativeFunction { class SymbolConstructor final : public NativeFunction {
public: public:
SymbolConstructor(); explicit SymbolConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~SymbolConstructor() override; virtual ~SymbolConstructor() override;
virtual Value call(Interpreter&) override; virtual Value call(Interpreter&) override;

View file

@ -52,7 +52,7 @@ Value SymbolObject::s_well_known_to_string_tag;
SymbolObject* SymbolObject::create(GlobalObject& global_object, Symbol& primitive_symbol) SymbolObject* SymbolObject::create(GlobalObject& global_object, Symbol& primitive_symbol)
{ {
return global_object.heap().allocate<SymbolObject>(primitive_symbol, *global_object.symbol_prototype()); return global_object.heap().allocate<SymbolObject>(global_object, primitive_symbol, *global_object.symbol_prototype());
} }
SymbolObject::SymbolObject(Symbol& symbol, Object& prototype) SymbolObject::SymbolObject(Symbol& symbol, Object& prototype)

View file

@ -39,8 +39,12 @@
namespace JS { namespace JS {
SymbolPrototype::SymbolPrototype() SymbolPrototype::SymbolPrototype(GlobalObject& global_object)
: Object(interpreter().global_object().object_prototype()) : Object(global_object.object_prototype())
{
}
void SymbolPrototype::initialize(Interpreter&, GlobalObject&)
{ {
define_native_property("description", description_getter, nullptr, Attribute::Configurable); define_native_property("description", description_getter, nullptr, Attribute::Configurable);
@ -88,5 +92,4 @@ JS_DEFINE_NATIVE_FUNCTION(SymbolPrototype::value_of)
return {}; return {};
return this_object->value_of(); return this_object->value_of();
} }
} }

View file

@ -32,7 +32,8 @@ namespace JS {
class SymbolPrototype final : public Object { class SymbolPrototype final : public Object {
public: public:
SymbolPrototype(); explicit SymbolPrototype(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~SymbolPrototype() override; virtual ~SymbolPrototype() override;
private: private:

View file

@ -35,7 +35,7 @@ namespace JS {
Uint8ClampedArray* Uint8ClampedArray::create(GlobalObject& global_object, u32 length) Uint8ClampedArray* Uint8ClampedArray::create(GlobalObject& global_object, u32 length)
{ {
auto& interpreter = global_object.interpreter(); auto& interpreter = global_object.interpreter();
return interpreter.heap().allocate<Uint8ClampedArray>(length, *global_object.array_prototype()); return interpreter.heap().allocate<Uint8ClampedArray>(global_object, length, *global_object.array_prototype());
} }
Uint8ClampedArray::Uint8ClampedArray(u32 length, Object& prototype) Uint8ClampedArray::Uint8ClampedArray(u32 length, Object& prototype)

View file

@ -60,11 +60,11 @@ void WindowObject::initialize()
define_native_function("requestAnimationFrame", request_animation_frame, 1); define_native_function("requestAnimationFrame", request_animation_frame, 1);
define_native_function("cancelAnimationFrame", cancel_animation_frame, 1); define_native_function("cancelAnimationFrame", cancel_animation_frame, 1);
define_property("navigator", heap().allocate<NavigatorObject>(), JS::Attribute::Enumerable | JS::Attribute::Configurable); define_property("navigator", heap().allocate<NavigatorObject>(*this), JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_property("location", heap().allocate<LocationObject>(), JS::Attribute::Enumerable | JS::Attribute::Configurable); define_property("location", heap().allocate<LocationObject>(*this), JS::Attribute::Enumerable | JS::Attribute::Configurable);
m_xhr_prototype = heap().allocate<XMLHttpRequestPrototype>(); m_xhr_prototype = heap().allocate<XMLHttpRequestPrototype>(*this, *this);
m_xhr_constructor = heap().allocate<XMLHttpRequestConstructor>(); m_xhr_constructor = heap().allocate<XMLHttpRequestConstructor>(*this, *this);
m_xhr_constructor->define_property("prototype", m_xhr_prototype, 0); m_xhr_constructor->define_property("prototype", m_xhr_prototype, 0);
add_constructor("XMLHttpRequest", m_xhr_constructor, *m_xhr_prototype); add_constructor("XMLHttpRequest", m_xhr_constructor, *m_xhr_prototype);
} }

View file

@ -28,6 +28,7 @@
#include <AK/WeakPtr.h> #include <AK/WeakPtr.h>
#include <LibJS/Heap/Heap.h> #include <LibJS/Heap/Heap.h>
#include <LibJS/Interpreter.h>
#include <LibWeb/Forward.h> #include <LibWeb/Forward.h>
namespace Web { namespace Web {
@ -49,7 +50,7 @@ template<class NativeObject>
inline Wrapper* wrap_impl(JS::Heap& heap, NativeObject& native_object) inline Wrapper* wrap_impl(JS::Heap& heap, NativeObject& native_object)
{ {
if (!native_object.wrapper()) if (!native_object.wrapper())
native_object.set_wrapper(*heap.allocate<typename NativeObject::WrapperType>(native_object)); native_object.set_wrapper(*heap.allocate<typename NativeObject::WrapperType>(heap.interpreter().global_object(), native_object));
return native_object.wrapper(); return native_object.wrapper();
} }

View file

@ -36,8 +36,12 @@
namespace Web { namespace Web {
namespace Bindings { namespace Bindings {
XMLHttpRequestConstructor::XMLHttpRequestConstructor() XMLHttpRequestConstructor::XMLHttpRequestConstructor(JS::GlobalObject& global_object)
: NativeFunction(*interpreter().global_object().function_prototype()) : NativeFunction(*global_object.function_prototype())
{
}
void XMLHttpRequestConstructor::initialize(JS::Interpreter&, JS::GlobalObject&)
{ {
define_property("length", JS::Value(1), JS::Attribute::Configurable); define_property("length", JS::Value(1), JS::Attribute::Configurable);
@ -60,7 +64,7 @@ JS::Value XMLHttpRequestConstructor::call(JS::Interpreter& interpreter)
JS::Value XMLHttpRequestConstructor::construct(JS::Interpreter& interpreter) JS::Value XMLHttpRequestConstructor::construct(JS::Interpreter& interpreter)
{ {
auto& window = static_cast<WindowObject&>(global_object()); auto& window = static_cast<WindowObject&>(global_object());
return interpreter.heap().allocate<XMLHttpRequestWrapper>(XMLHttpRequest::create(window.impl())); return interpreter.heap().allocate<XMLHttpRequestWrapper>(window, XMLHttpRequest::create(window.impl()));
} }
} }

View file

@ -33,7 +33,8 @@ namespace Bindings {
class XMLHttpRequestConstructor final : public JS::NativeFunction { class XMLHttpRequestConstructor final : public JS::NativeFunction {
public: public:
XMLHttpRequestConstructor(); explicit XMLHttpRequestConstructor(JS::GlobalObject&);
virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;
virtual ~XMLHttpRequestConstructor() override; virtual ~XMLHttpRequestConstructor() override;
virtual JS::Value call(JS::Interpreter&) override; virtual JS::Value call(JS::Interpreter&) override;

View file

@ -35,8 +35,12 @@
namespace Web { namespace Web {
namespace Bindings { namespace Bindings {
XMLHttpRequestPrototype::XMLHttpRequestPrototype() XMLHttpRequestPrototype::XMLHttpRequestPrototype(JS::GlobalObject& global_object)
: Object(interpreter().global_object().object_prototype()) : Object(global_object.object_prototype())
{
}
void XMLHttpRequestPrototype::initialize(JS::Interpreter&, JS::GlobalObject&)
{ {
define_native_function("open", open, 2); define_native_function("open", open, 2);
define_native_function("send", send, 0); define_native_function("send", send, 0);

View file

@ -33,7 +33,8 @@ namespace Bindings {
class XMLHttpRequestPrototype final : public JS::Object { class XMLHttpRequestPrototype final : public JS::Object {
public: public:
XMLHttpRequestPrototype(); explicit XMLHttpRequestPrototype(JS::GlobalObject&);
virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;
virtual ~XMLHttpRequestPrototype() override; virtual ~XMLHttpRequestPrototype() override;
private: private: