1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 13: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();
template<typename T, typename... Args>
T* allocate(Args&&... args)
T* allocate_without_global_object(Args&&... args)
{
auto* memory = allocate_cell(sizeof(T));
new (memory) T(forward<Args>(args)...);
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 {
CollectGarbage,
CollectEverything,

View file

@ -59,7 +59,7 @@ Value Interpreter::run(GlobalObject& global_object, const Statement& statement,
CallFrame global_call_frame;
global_call_frame.this_value = &global_object;
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));
}
}
@ -126,7 +126,7 @@ void Interpreter::enter_scope(const ScopeNode& scope_node, ArgumentVector argume
bool pushed_lexical_environment = false;
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;
pushed_lexical_environment = true;
}

View file

@ -78,7 +78,7 @@ public:
static NonnullOwnPtr<Interpreter> create(Args&&... args)
{
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();
return interpreter;
}
@ -173,7 +173,7 @@ public:
Value throw_exception(Exception*);
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>

View file

@ -37,7 +37,7 @@ class Accessor final : public Cell {
public:
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)

View file

@ -36,7 +36,7 @@ namespace JS {
Array* Array::create(GlobalObject& global_object)
{
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)

View file

@ -36,10 +36,20 @@
namespace JS {
ArrayConstructor::ArrayConstructor()
: NativeFunction("Array", *interpreter().global_object().function_prototype())
ArrayConstructor::ArrayConstructor(GlobalObject& global_object)
: 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);
u8 attr = Attribute::Writable | Attribute::Configurable;
@ -47,10 +57,6 @@ ArrayConstructor::ArrayConstructor()
define_native_function("of", of, 0, attr);
}
ArrayConstructor::~ArrayConstructor()
{
}
Value ArrayConstructor::call(Interpreter& interpreter)
{
if (interpreter.argument_count() <= 0)

View file

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

View file

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

View file

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

View file

@ -42,7 +42,7 @@ BigInt::~BigInt()
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)

View file

@ -34,10 +34,14 @@
namespace JS {
BigIntConstructor::BigIntConstructor()
: NativeFunction("BigInt", *interpreter().global_object().function_prototype())
BigIntConstructor::BigIntConstructor(GlobalObject& global_object)
: 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);
u8 attr = Attribute::Writable | Attribute::Configurable;

View file

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

View file

@ -33,7 +33,7 @@ namespace JS {
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)

View file

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

View file

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

View file

@ -33,10 +33,14 @@
namespace JS {
BooleanConstructor::BooleanConstructor()
: NativeFunction("Boolean", *interpreter().global_object().function_prototype())
BooleanConstructor::BooleanConstructor(GlobalObject& global_object)
: 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);
}

View file

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

View file

@ -33,7 +33,7 @@ namespace JS {
BooleanObject* BooleanObject::create(GlobalObject& global_object, bool value)
{
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)

View file

@ -32,8 +32,12 @@
namespace JS {
BooleanPrototype::BooleanPrototype()
: BooleanObject(false, *interpreter().global_object().object_prototype())
BooleanPrototype::BooleanPrototype(GlobalObject& global_object)
: 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("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable);

View file

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

View file

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

View file

@ -34,7 +34,7 @@ namespace JS {
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)

View file

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

View file

@ -32,7 +32,8 @@ namespace JS {
class DateConstructor final : public NativeFunction {
public:
DateConstructor();
explicit DateConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~DateConstructor() 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);
}
DatePrototype::DatePrototype()
: Object(interpreter().global_object().object_prototype())
DatePrototype::DatePrototype(GlobalObject& global_object)
: Object(global_object.object_prototype())
{
}
void DatePrototype::initialize(Interpreter&, GlobalObject&)
{
u8 attr = Attribute::Writable | Attribute::Configurable;
define_native_function("getDate", get_date, 0, attr);

View file

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

View file

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

View file

@ -31,10 +31,14 @@
namespace JS {
ErrorConstructor::ErrorConstructor()
: NativeFunction("Error", *interpreter().global_object().function_prototype())
ErrorConstructor::ErrorConstructor(GlobalObject& global_object)
: 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);
}
@ -59,10 +63,13 @@ Value ErrorConstructor::construct(Interpreter& interpreter)
}
#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
ConstructorName::ConstructorName() \
: NativeFunction(*interpreter().global_object().function_prototype()) \
ConstructorName::ConstructorName(GlobalObject& global_object) \
: 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); \
} \
ConstructorName::~ConstructorName() { } \

View file

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

View file

@ -35,8 +35,12 @@
namespace JS {
ErrorPrototype::ErrorPrototype()
: Object(interpreter().global_object().object_prototype())
ErrorPrototype::ErrorPrototype(GlobalObject& global_object)
: Object(global_object.object_prototype())
{
}
void ErrorPrototype::initialize(Interpreter&, GlobalObject&)
{
u8 attr = Attribute::Writable | Attribute::Configurable;
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) \
PrototypeName::PrototypeName() \
: Object(interpreter().global_object().error_prototype()) \
PrototypeName::PrototypeName(GlobalObject& global_object) \
: Object(global_object.error_prototype()) \
{ \
} \
PrototypeName::~PrototypeName() { } \

View file

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

View file

@ -82,7 +82,7 @@ BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments)
auto all_bound_arguments = bound_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)

View file

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

View file

@ -35,10 +35,14 @@
namespace JS {
FunctionConstructor::FunctionConstructor()
: NativeFunction("Function", *interpreter().global_object().function_prototype())
FunctionConstructor::FunctionConstructor(GlobalObject& global_object)
: 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);
}

View file

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

View file

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

View file

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

View file

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

View file

@ -72,7 +72,7 @@ private:
template<typename ConstructorType>
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);
if (interpreter().exception())
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)
{
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)

View file

@ -36,6 +36,7 @@ public:
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);
virtual void initialize(Interpreter&, GlobalObject&) override { }
virtual ~NativeFunction() override;
virtual Value call(Interpreter&) override;

View file

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

View file

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

View file

@ -35,7 +35,7 @@ namespace JS {
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)

View file

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

View file

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

View file

@ -82,7 +82,7 @@ PropertyDescriptor PropertyDescriptor::from_dictionary(Interpreter& interpreter,
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)
@ -92,10 +92,14 @@ Object::Object(Object* prototype)
set_prototype(prototype);
} else {
// 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()
{
}
@ -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)
{
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)

View file

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

View file

@ -35,10 +35,14 @@
namespace JS {
ObjectConstructor::ObjectConstructor()
: NativeFunction("Object", *interpreter().global_object().function_prototype())
ObjectConstructor::ObjectConstructor(GlobalObject& global_object)
: 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);
u8 attr = Attribute::Writable | Attribute::Configurable;

View file

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

View file

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

View file

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

View file

@ -41,7 +41,7 @@ PrimitiveString::~PrimitiveString()
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)

View file

@ -33,10 +33,14 @@
namespace JS {
ProxyConstructor::ProxyConstructor()
: NativeFunction("Proxy", *interpreter().global_object().function_prototype())
ProxyConstructor::ProxyConstructor(GlobalObject& global_object)
: 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);
}

View file

@ -32,7 +32,8 @@ namespace JS {
class ProxyConstructor final : public NativeFunction {
public:
ProxyConstructor();
explicit ProxyConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~ProxyConstructor() 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)
{
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)

View file

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

View file

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

View file

@ -32,10 +32,14 @@
namespace JS {
RegExpConstructor::RegExpConstructor()
: NativeFunction("RegExp", *interpreter().global_object().function_prototype())
RegExpConstructor::RegExpConstructor(GlobalObject& global_object)
: 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);
}

View file

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

View file

@ -37,7 +37,7 @@ namespace JS {
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)

View file

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

View file

@ -32,7 +32,7 @@ namespace JS {
class RegExpPrototype final : public RegExpObject {
public:
RegExpPrototype();
explicit RegExpPrototype(GlobalObject&);
virtual ~RegExpPrototype() override;
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)
{
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)
@ -93,7 +93,7 @@ LexicalEnvironment* ScriptFunction::create_environment()
}
if (variables.is_empty())
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)

View file

@ -32,7 +32,7 @@ namespace JS {
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_prototype = m_prototype;
ensure_property_table();
@ -46,7 +46,7 @@ Shape* Shape::create_put_transition(const FlyString& property_name, PropertyAttr
TransitionKey key { property_name, attributes };
if (auto* existing_shape = m_forward_transitions.get(key).value_or(nullptr))
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);
return new_shape;
}
@ -56,14 +56,14 @@ Shape* Shape::create_configure_transition(const FlyString& property_name, Proper
TransitionKey key { property_name, attributes };
if (auto* existing_shape = m_forward_transitions.get(key).value_or(nullptr))
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);
return new_shape;
}
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)

View file

@ -35,10 +35,14 @@
namespace JS {
StringConstructor::StringConstructor()
: NativeFunction("String", *interpreter().global_object().function_prototype())
StringConstructor::StringConstructor(GlobalObject& global_object)
: 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);
u8 attr = Attribute::Writable | Attribute::Configurable;

View file

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

View file

@ -36,7 +36,7 @@ namespace JS {
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)

View file

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

View file

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

View file

@ -42,7 +42,7 @@ Symbol::~Symbol()
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)

View file

@ -32,16 +32,20 @@
namespace JS {
SymbolConstructor::SymbolConstructor()
: NativeFunction("Symbol", *interpreter().global_object().function_prototype())
SymbolConstructor::SymbolConstructor(GlobalObject& global_object)
: 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_native_function("for", 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("asyncIterator", SymbolObject::well_known_async_terator(), 0);

View file

@ -32,7 +32,8 @@ namespace JS {
class SymbolConstructor final : public NativeFunction {
public:
SymbolConstructor();
explicit SymbolConstructor(GlobalObject&);
virtual void initialize(Interpreter&, GlobalObject&) override;
virtual ~SymbolConstructor() 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)
{
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)

View file

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

View file

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

View file

@ -35,7 +35,7 @@ namespace JS {
Uint8ClampedArray* Uint8ClampedArray::create(GlobalObject& global_object, u32 length)
{
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)

View file

@ -60,11 +60,11 @@ void WindowObject::initialize()
define_native_function("requestAnimationFrame", request_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("location", heap().allocate<LocationObject>(), 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>(*this), JS::Attribute::Enumerable | JS::Attribute::Configurable);
m_xhr_prototype = heap().allocate<XMLHttpRequestPrototype>();
m_xhr_constructor = heap().allocate<XMLHttpRequestConstructor>();
m_xhr_prototype = heap().allocate<XMLHttpRequestPrototype>(*this, *this);
m_xhr_constructor = heap().allocate<XMLHttpRequestConstructor>(*this, *this);
m_xhr_constructor->define_property("prototype", m_xhr_prototype, 0);
add_constructor("XMLHttpRequest", m_xhr_constructor, *m_xhr_prototype);
}

View file

@ -28,6 +28,7 @@
#include <AK/WeakPtr.h>
#include <LibJS/Heap/Heap.h>
#include <LibJS/Interpreter.h>
#include <LibWeb/Forward.h>
namespace Web {
@ -49,7 +50,7 @@ template<class NativeObject>
inline Wrapper* wrap_impl(JS::Heap& heap, NativeObject& native_object)
{
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();
}

View file

@ -36,8 +36,12 @@
namespace Web {
namespace Bindings {
XMLHttpRequestConstructor::XMLHttpRequestConstructor()
: NativeFunction(*interpreter().global_object().function_prototype())
XMLHttpRequestConstructor::XMLHttpRequestConstructor(JS::GlobalObject& global_object)
: NativeFunction(*global_object.function_prototype())
{
}
void XMLHttpRequestConstructor::initialize(JS::Interpreter&, JS::GlobalObject&)
{
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)
{
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 {
public:
XMLHttpRequestConstructor();
explicit XMLHttpRequestConstructor(JS::GlobalObject&);
virtual void initialize(JS::Interpreter&, JS::GlobalObject&) override;
virtual ~XMLHttpRequestConstructor() override;
virtual JS::Value call(JS::Interpreter&) override;

View file

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

View file

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