Parcourir la source

LibJS: Move builtin prototypes to the global object

This moves us towards being able to run JavaScript in different global
objects without allocating a separate GC heap.
Andreas Kling il y a 5 ans
Parent
commit
fca08bd000
40 fichiers modifiés avec 131 ajouts et 101 suppressions
  1. 0 26
      Libraries/LibJS/Interpreter.cpp
  2. 1 11
      Libraries/LibJS/Interpreter.h
  3. 1 1
      Libraries/LibJS/Runtime/Array.cpp
  4. 3 2
      Libraries/LibJS/Runtime/ArrayConstructor.cpp
  5. 2 1
      Libraries/LibJS/Runtime/ArrayPrototype.cpp
  6. 3 2
      Libraries/LibJS/Runtime/BooleanConstructor.cpp
  7. 1 1
      Libraries/LibJS/Runtime/BooleanObject.cpp
  8. 2 1
      Libraries/LibJS/Runtime/BooleanPrototype.cpp
  9. 2 1
      Libraries/LibJS/Runtime/ConsoleObject.cpp
  10. 1 1
      Libraries/LibJS/Runtime/Date.cpp
  11. 3 2
      Libraries/LibJS/Runtime/DateConstructor.cpp
  12. 2 1
      Libraries/LibJS/Runtime/DatePrototype.cpp
  13. 2 3
      Libraries/LibJS/Runtime/Error.cpp
  14. 5 4
      Libraries/LibJS/Runtime/ErrorConstructor.cpp
  15. 3 2
      Libraries/LibJS/Runtime/ErrorPrototype.cpp
  16. 3 2
      Libraries/LibJS/Runtime/FunctionConstructor.cpp
  17. 2 1
      Libraries/LibJS/Runtime/FunctionPrototype.cpp
  18. 39 10
      Libraries/LibJS/Runtime/GlobalObject.cpp
  19. 7 3
      Libraries/LibJS/Runtime/GlobalObject.h
  20. 2 1
      Libraries/LibJS/Runtime/MathObject.cpp
  21. 2 2
      Libraries/LibJS/Runtime/NativeFunction.cpp
  22. 3 2
      Libraries/LibJS/Runtime/NumberConstructor.cpp
  23. 1 2
      Libraries/LibJS/Runtime/NumberObject.cpp
  24. 2 1
      Libraries/LibJS/Runtime/NumberPrototype.cpp
  25. 2 2
      Libraries/LibJS/Runtime/Object.cpp
  26. 3 2
      Libraries/LibJS/Runtime/ObjectConstructor.cpp
  27. 1 2
      Libraries/LibJS/Runtime/ScriptFunction.cpp
  28. 3 2
      Libraries/LibJS/Runtime/StringConstructor.cpp
  29. 1 2
      Libraries/LibJS/Runtime/StringObject.cpp
  30. 2 1
      Libraries/LibJS/Runtime/StringPrototype.cpp
  31. 2 1
      Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp
  32. 2 1
      Libraries/LibWeb/Bindings/EventListenerWrapper.cpp
  33. 2 1
      Libraries/LibWeb/Bindings/EventTargetWrapper.cpp
  34. 2 1
      Libraries/LibWeb/Bindings/EventWrapper.cpp
  35. 2 1
      Libraries/LibWeb/Bindings/NavigatorObject.cpp
  36. 6 0
      Libraries/LibWeb/Bindings/WindowObject.cpp
  37. 1 0
      Libraries/LibWeb/Bindings/WindowObject.h
  38. 2 1
      Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp
  39. 2 1
      Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp
  40. 6 0
      Userland/js.cpp

+ 0 - 26
Libraries/LibJS/Interpreter.cpp

@@ -27,20 +27,12 @@
 #include <AK/Badge.h>
 #include <LibJS/AST.h>
 #include <LibJS/Interpreter.h>
-#include <LibJS/Runtime/ArrayPrototype.h>
-#include <LibJS/Runtime/BooleanPrototype.h>
-#include <LibJS/Runtime/DatePrototype.h>
 #include <LibJS/Runtime/Error.h>
-#include <LibJS/Runtime/ErrorPrototype.h>
-#include <LibJS/Runtime/FunctionPrototype.h>
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/LexicalEnvironment.h>
 #include <LibJS/Runtime/NativeFunction.h>
-#include <LibJS/Runtime/NumberPrototype.h>
 #include <LibJS/Runtime/Object.h>
-#include <LibJS/Runtime/ObjectPrototype.h>
 #include <LibJS/Runtime/Shape.h>
-#include <LibJS/Runtime/StringPrototype.h>
 #include <LibJS/Runtime/Value.h>
 
 namespace JS {
@@ -49,19 +41,6 @@ Interpreter::Interpreter()
     : m_heap(*this)
 {
     m_empty_object_shape = heap().allocate<Shape>();
-
-    // These are done first since other prototypes depend on their presence.
-    m_object_prototype = heap().allocate<ObjectPrototype>();
-    m_function_prototype = heap().allocate<FunctionPrototype>();
-
-    static_cast<FunctionPrototype*>(m_function_prototype)->initialize();
-    static_cast<ObjectPrototype*>(m_object_prototype)->initialize();
-
-#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
-    if (!m_##snake_name##_prototype)                                          \
-        m_##snake_name##_prototype = heap().allocate<PrototypeName>();
-    JS_ENUMERATE_BUILTIN_TYPES
-#undef __JS_ENUMERATE
 }
 
 Interpreter::~Interpreter()
@@ -186,11 +165,6 @@ void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots)
     roots.set(m_global_object);
     roots.set(m_exception);
 
-#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
-    roots.set(m_##snake_name##_prototype);
-    JS_ENUMERATE_BUILTIN_TYPES
-#undef __JS_ENUMERATE
-
     if (m_last_value.is_cell())
         roots.set(m_last_value.as_cell());
 

+ 1 - 11
Libraries/LibJS/Interpreter.h

@@ -74,6 +74,7 @@ public:
     {
         auto interpreter = adopt_own(*new Interpreter);
         interpreter->m_global_object = interpreter->heap().allocate<GlobalObjectType>(forward<Args>(args)...);
+        static_cast<GlobalObjectType*>(interpreter->m_global_object)->initialize();
         return interpreter;
     }
 
@@ -140,11 +141,6 @@ public:
 
     Shape* empty_object_shape() { return m_empty_object_shape; }
 
-#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
-    Object* snake_name##_prototype() { return m_##snake_name##_prototype; }
-    JS_ENUMERATE_BUILTIN_TYPES
-#undef __JS_ENUMERATE
-
     Exception* exception()
     {
         return m_exception;
@@ -176,12 +172,6 @@ private:
     Vector<CallFrame> m_call_stack;
 
     Shape* m_empty_object_shape { nullptr };
-
-#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
-    Object* m_##snake_name##_prototype { nullptr };
-    JS_ENUMERATE_BUILTIN_TYPES
-#undef __JS_ENUMERATE
-
     Object* m_global_object { nullptr };
 
     Exception* m_exception { nullptr };

+ 1 - 1
Libraries/LibJS/Runtime/Array.cpp

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

+ 3 - 2
Libraries/LibJS/Runtime/ArrayConstructor.cpp

@@ -29,14 +29,15 @@
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Array.h>
 #include <LibJS/Runtime/ArrayConstructor.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/Shape.h>
 
 namespace JS {
 
 ArrayConstructor::ArrayConstructor()
-    : NativeFunction("Array", *interpreter().function_prototype())
+    : NativeFunction("Array", *interpreter().global_object().function_prototype())
 {
-    put("prototype", interpreter().array_prototype());
+    put("prototype", interpreter().global_object().array_prototype());
     put("length", Value(1));
 }
 

+ 2 - 1
Libraries/LibJS/Runtime/ArrayPrototype.cpp

@@ -33,12 +33,13 @@
 #include <LibJS/Runtime/ArrayPrototype.h>
 #include <LibJS/Runtime/Error.h>
 #include <LibJS/Runtime/Function.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/Value.h>
 
 namespace JS {
 
 ArrayPrototype::ArrayPrototype()
-    : Object(interpreter().object_prototype())
+    : Object(interpreter().global_object().object_prototype())
 {
     put_native_function("filter", filter, 1);
     put_native_function("forEach", for_each, 1);

+ 3 - 2
Libraries/LibJS/Runtime/BooleanConstructor.cpp

@@ -29,13 +29,14 @@
 #include <LibJS/Runtime/BooleanConstructor.h>
 #include <LibJS/Runtime/BooleanObject.h>
 #include <LibJS/Runtime/BooleanPrototype.h>
+#include <LibJS/Runtime/GlobalObject.h>
 
 namespace JS {
 
 BooleanConstructor::BooleanConstructor()
-    : NativeFunction("Boolean", *interpreter().function_prototype())
+    : NativeFunction("Boolean", *interpreter().global_object().function_prototype())
 {
-    put("prototype", Value(interpreter().boolean_prototype()));
+    put("prototype", Value(interpreter().global_object().boolean_prototype()));
     put("length", Value(1));
 }
 

+ 1 - 1
Libraries/LibJS/Runtime/BooleanObject.cpp

@@ -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, *interpreter.boolean_prototype());
+    return interpreter.heap().allocate<BooleanObject>(value, *global_object.boolean_prototype());
 }
 
 BooleanObject::BooleanObject(bool value, Object& prototype)

+ 2 - 1
Libraries/LibJS/Runtime/BooleanPrototype.cpp

@@ -28,11 +28,12 @@
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/BooleanPrototype.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
 
 namespace JS {
 
 BooleanPrototype::BooleanPrototype()
-    : BooleanObject(false, *interpreter().object_prototype())
+    : BooleanObject(false, *interpreter().global_object().object_prototype())
 {
     put_native_function("toString", to_string);
     put_native_function("valueOf", value_of);

+ 2 - 1
Libraries/LibJS/Runtime/ConsoleObject.cpp

@@ -29,6 +29,7 @@
 #include <AK/Function.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/ConsoleObject.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <stdio.h>
 
 namespace JS {
@@ -44,7 +45,7 @@ static void print_args(Interpreter& interpreter)
 }
 
 ConsoleObject::ConsoleObject()
-    : Object(interpreter().object_prototype())
+    : Object(interpreter().global_object().object_prototype())
 {
     put_native_function("log", log);
     put_native_function("debug", debug);

+ 1 - 1
Libraries/LibJS/Runtime/Date.cpp

@@ -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.interpreter().date_prototype());
+    return global_object.heap().allocate<Date>(datetime, milliseconds, *global_object.date_prototype());
 }
 
 Date::Date(Core::DateTime datetime, u16 milliseconds, Object& prototype)

+ 3 - 2
Libraries/LibJS/Runtime/DateConstructor.cpp

@@ -28,15 +28,16 @@
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Date.h>
 #include <LibJS/Runtime/DateConstructor.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <sys/time.h>
 #include <time.h>
 
 namespace JS {
 
 DateConstructor::DateConstructor()
-    : NativeFunction("Date", *interpreter().function_prototype())
+    : NativeFunction("Date", *interpreter().global_object().function_prototype())
 {
-    put("prototype", interpreter().date_prototype());
+    put("prototype", interpreter().global_object().date_prototype());
     put("length", Value(7));
 
     put_native_function("now", now);

+ 2 - 1
Libraries/LibJS/Runtime/DatePrototype.cpp

@@ -31,6 +31,7 @@
 #include <LibJS/Runtime/Date.h>
 #include <LibJS/Runtime/DatePrototype.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/Value.h>
 
 namespace JS {
@@ -48,7 +49,7 @@ static Date* this_date_from_interpreter(Interpreter& interpreter)
 }
 
 DatePrototype::DatePrototype()
-    : Object(interpreter().object_prototype())
+    : Object(interpreter().global_object().object_prototype())
 {
     put_native_function("getDate", get_date);
     put_native_function("getDay", get_day);

+ 2 - 3
Libraries/LibJS/Runtime/Error.cpp

@@ -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, *interpreter.error_prototype());
+    return interpreter.heap().allocate<Error>(name, message, *global_object.error_prototype());
 }
 
 Error::Error(const FlyString& name, const String& message, Object& prototype)
@@ -51,8 +51,7 @@ Error::~Error()
 #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName)                          \
     ClassName* ClassName::create(GlobalObject& global_object, const String& message)                   \
     {                                                                                                  \
-        auto& interpreter = global_object.interpreter();                                               \
-        return interpreter.heap().allocate<ClassName>(message, *interpreter.snake_name##_prototype()); \
+        return global_object.heap().allocate<ClassName>(message, *global_object.snake_name##_prototype()); \
     }                                                                                                  \
     ClassName::ClassName(const String& message, Object& prototype)                                     \
         : Error(#ClassName, message, prototype)                                                        \

+ 5 - 4
Libraries/LibJS/Runtime/ErrorConstructor.cpp

@@ -27,13 +27,14 @@
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Error.h>
 #include <LibJS/Runtime/ErrorConstructor.h>
+#include <LibJS/Runtime/GlobalObject.h>
 
 namespace JS {
 
 ErrorConstructor::ErrorConstructor()
-    : NativeFunction("Error", *interpreter().function_prototype())
+    : NativeFunction("Error", *interpreter().global_object().function_prototype())
 {
-    put("prototype", interpreter().error_prototype());
+    put("prototype", interpreter().global_object().error_prototype());
     put("length", Value(1));
 }
 
@@ -56,9 +57,9 @@ Value ErrorConstructor::construct(Interpreter& interpreter)
 
 #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName)                                        \
     ConstructorName::ConstructorName()                                                                               \
-        : NativeFunction(*interpreter().function_prototype())                                                        \
+        : NativeFunction(*interpreter().global_object().function_prototype())                                        \
     {                                                                                                                \
-        put("prototype", interpreter().snake_name##_prototype());                                                    \
+        put("prototype", interpreter().global_object().snake_name##_prototype());                                    \
         put("length", Value(1));                                                                                     \
     }                                                                                                                \
     ConstructorName::~ConstructorName() {}                                                                           \

+ 3 - 2
Libraries/LibJS/Runtime/ErrorPrototype.cpp

@@ -29,13 +29,14 @@
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Error.h>
 #include <LibJS/Runtime/ErrorPrototype.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/PrimitiveString.h>
 #include <LibJS/Runtime/Value.h>
 
 namespace JS {
 
 ErrorPrototype::ErrorPrototype()
-    : Object(interpreter().object_prototype())
+    : Object(interpreter().global_object().object_prototype())
 {
     put_native_property("name", name_getter, name_setter);
     put_native_property("message", message_getter, nullptr);
@@ -104,7 +105,7 @@ Value ErrorPrototype::to_string(Interpreter& interpreter)
 
 #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
     PrototypeName::PrototypeName()                                            \
-        : Object(interpreter().error_prototype())                             \
+        : Object(interpreter().global_object().error_prototype())             \
     {                                                                         \
     }                                                                         \
     PrototypeName::~PrototypeName() {}                                        \

+ 3 - 2
Libraries/LibJS/Runtime/FunctionConstructor.cpp

@@ -30,14 +30,15 @@
 #include <LibJS/Parser.h>
 #include <LibJS/Runtime/Error.h>
 #include <LibJS/Runtime/FunctionConstructor.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/ScriptFunction.h>
 
 namespace JS {
 
 FunctionConstructor::FunctionConstructor()
-    : NativeFunction("Function", *interpreter().function_prototype())
+    : NativeFunction("Function", *interpreter().global_object().function_prototype())
 {
-    put("prototype", interpreter().function_prototype());
+    put("prototype", interpreter().global_object().function_prototype());
     put("length", Value(1));
 }
 

+ 2 - 1
Libraries/LibJS/Runtime/FunctionPrototype.cpp

@@ -31,12 +31,13 @@
 #include <LibJS/Runtime/Error.h>
 #include <LibJS/Runtime/Function.h>
 #include <LibJS/Runtime/FunctionPrototype.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/ScriptFunction.h>
 
 namespace JS {
 
 FunctionPrototype::FunctionPrototype()
-    : Object(interpreter().object_prototype())
+    : Object(interpreter().global_object().object_prototype())
 {
 }
 

+ 39 - 10
Libraries/LibJS/Runtime/GlobalObject.cpp

@@ -29,17 +29,29 @@
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/ArrayConstructor.h>
+#include <LibJS/Runtime/ArrayPrototype.h>
 #include <LibJS/Runtime/BooleanConstructor.h>
+#include <LibJS/Runtime/BooleanPrototype.h>
 #include <LibJS/Runtime/ConsoleObject.h>
 #include <LibJS/Runtime/DateConstructor.h>
+#include <LibJS/Runtime/DatePrototype.h>
+#include <LibJS/Runtime/Error.h>
 #include <LibJS/Runtime/ErrorConstructor.h>
+#include <LibJS/Runtime/ErrorPrototype.h>
 #include <LibJS/Runtime/FunctionConstructor.h>
+#include <LibJS/Runtime/FunctionPrototype.h>
 #include <LibJS/Runtime/GlobalObject.h>
+#include <LibJS/Runtime/LexicalEnvironment.h>
 #include <LibJS/Runtime/MathObject.h>
 #include <LibJS/Runtime/NativeFunction.h>
 #include <LibJS/Runtime/NumberConstructor.h>
+#include <LibJS/Runtime/NumberPrototype.h>
+#include <LibJS/Runtime/Object.h>
 #include <LibJS/Runtime/ObjectConstructor.h>
+#include <LibJS/Runtime/ObjectPrototype.h>
+#include <LibJS/Runtime/Shape.h>
 #include <LibJS/Runtime/StringConstructor.h>
+#include <LibJS/Runtime/StringPrototype.h>
 #include <LibJS/Runtime/Value.h>
 
 namespace JS {
@@ -53,8 +65,25 @@ void GlobalObject::add_constructor(const FlyString& property_name, ConstructorTy
 }
 
 GlobalObject::GlobalObject()
-    : Object(interpreter().object_prototype())
+    : Object(nullptr)
 {
+}
+
+void GlobalObject::initialize()
+{
+    // These are done first since other prototypes depend on their presence.
+    m_object_prototype = heap().allocate<ObjectPrototype>();
+    m_function_prototype = heap().allocate<FunctionPrototype>();
+
+    static_cast<FunctionPrototype*>(m_function_prototype)->initialize();
+    static_cast<ObjectPrototype*>(m_object_prototype)->initialize();
+
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
+    if (!m_##snake_name##_prototype)                                          \
+        m_##snake_name##_prototype = heap().allocate<PrototypeName>();
+    JS_ENUMERATE_BUILTIN_TYPES
+#undef __JS_ENUMERATE
+
     put_native_function("gc", gc);
     put_native_function("isNaN", is_nan, 1);
 
@@ -67,17 +96,17 @@ GlobalObject::GlobalObject()
     put("console", heap().allocate<ConsoleObject>());
     put("Math", heap().allocate<MathObject>());
 
-    add_constructor("Array", m_array_constructor, *interpreter().array_prototype());
-    add_constructor("Boolean", m_boolean_constructor, *interpreter().boolean_prototype());
-    add_constructor("Date", m_date_constructor, *interpreter().date_prototype());
-    add_constructor("Error", m_error_constructor, *interpreter().error_prototype());
-    add_constructor("Function", m_function_constructor, *interpreter().function_prototype());
-    add_constructor("Number", m_number_constructor, *interpreter().number_prototype());
-    add_constructor("Object", m_object_constructor, *interpreter().object_prototype());
-    add_constructor("String", m_string_constructor, *interpreter().string_prototype());
+    add_constructor("Array", m_array_constructor, *m_array_prototype);
+    add_constructor("Boolean", m_boolean_constructor, *m_boolean_prototype);
+    add_constructor("Date", m_date_constructor, *m_date_prototype);
+    add_constructor("Error", m_error_constructor, *m_error_prototype);
+    add_constructor("Function", m_function_constructor, *m_function_prototype);
+    add_constructor("Number", m_number_constructor, *m_number_prototype);
+    add_constructor("Object", m_object_constructor, *m_object_prototype);
+    add_constructor("String", m_string_constructor, *m_string_prototype);
 
 #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
-    add_constructor(#ClassName, m_##snake_name##_constructor, *interpreter().snake_name##_prototype());
+    add_constructor(#ClassName, m_##snake_name##_constructor, *m_##snake_name##_prototype);
     JS_ENUMERATE_ERROR_SUBCLASSES
 #undef __JS_ENUMERATE
 }

+ 7 - 3
Libraries/LibJS/Runtime/GlobalObject.h

@@ -33,10 +33,13 @@ namespace JS {
 class GlobalObject : public Object {
 public:
     explicit GlobalObject();
+    virtual void initialize();
+
     virtual ~GlobalObject() override;
 
-#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
-    ConstructorName* snake_name##_constructor() { return m_##snake_name##_constructor; }
+#define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName)            \
+    ConstructorName* snake_name##_constructor() { return m_##snake_name##_constructor; } \
+    Object* snake_name##_prototype() { return m_##snake_name##_prototype; }
     JS_ENUMERATE_BUILTIN_TYPES
 #undef __JS_ENUMERATE
 
@@ -53,7 +56,8 @@ private:
     void add_constructor(const FlyString& property_name, ConstructorType*&, Object& prototype);
 
 #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
-    ConstructorName* m_##snake_name##_constructor { nullptr };
+    ConstructorName* m_##snake_name##_constructor { nullptr };                \
+    Object* m_##snake_name##_prototype { nullptr };
     JS_ENUMERATE_BUILTIN_TYPES
 #undef __JS_ENUMERATE
 };

+ 2 - 1
Libraries/LibJS/Runtime/MathObject.cpp

@@ -27,13 +27,14 @@
 #include <AK/FlyString.h>
 #include <AK/Function.h>
 #include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/MathObject.h>
 #include <math.h>
 
 namespace JS {
 
 MathObject::MathObject()
-    : Object(interpreter().object_prototype())
+    : Object(interpreter().global_object().object_prototype())
 {
     put_native_function("abs", abs, 1);
     put_native_function("random", random);

+ 2 - 2
Libraries/LibJS/Runtime/NativeFunction.cpp

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

+ 3 - 2
Libraries/LibJS/Runtime/NumberConstructor.cpp

@@ -26,6 +26,7 @@
 
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/NumberConstructor.h>
 #include <LibJS/Runtime/NumberObject.h>
 #include <math.h>
@@ -37,11 +38,11 @@
 namespace JS {
 
 NumberConstructor::NumberConstructor()
-    : NativeFunction("Number", *interpreter().function_prototype())
+    : NativeFunction("Number", *interpreter().global_object().function_prototype())
 {
     put_native_function("isSafeInteger", is_safe_integer, 1);
 
-    put("prototype", interpreter().number_prototype());
+    put("prototype", interpreter().global_object().number_prototype());
     put("length", Value(1));
     put("EPSILON", Value(EPSILON));
     put("MAX_SAFE_INTEGER", Value(MAX_SAFE_INTEGER));

+ 1 - 2
Libraries/LibJS/Runtime/NumberObject.cpp

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

+ 2 - 1
Libraries/LibJS/Runtime/NumberPrototype.cpp

@@ -25,12 +25,13 @@
  */
 
 #include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/NumberPrototype.h>
 
 namespace JS {
 
 NumberPrototype::NumberPrototype()
-    : NumberObject(0, *interpreter().object_prototype())
+    : NumberObject(0, *interpreter().global_object().object_prototype())
 {
 }
 

+ 2 - 2
Libraries/LibJS/Runtime/Object.cpp

@@ -38,9 +38,9 @@
 
 namespace JS {
 
-Object* Object::create_empty(Interpreter& interpreter, GlobalObject&)
+Object* Object::create_empty(Interpreter&, GlobalObject& global_object)
 {
-    return interpreter.heap().allocate<Object>(interpreter.object_prototype());
+    return global_object.heap().allocate<Object>(global_object.object_prototype());
 }
 
 Object::Object(Object* prototype)

+ 3 - 2
Libraries/LibJS/Runtime/ObjectConstructor.cpp

@@ -29,15 +29,16 @@
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Array.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/ObjectConstructor.h>
 #include <LibJS/Runtime/Shape.h>
 
 namespace JS {
 
 ObjectConstructor::ObjectConstructor()
-    : NativeFunction("Object", *interpreter().function_prototype())
+    : NativeFunction("Object", *interpreter().global_object().function_prototype())
 {
-    put("prototype", interpreter().object_prototype());
+    put("prototype", interpreter().global_object().object_prototype());
 
     put_native_function("defineProperty", define_property, 3);
     put_native_function("getOwnPropertyDescriptor", get_own_property_descriptor, 2);

+ 1 - 2
Libraries/LibJS/Runtime/ScriptFunction.cpp

@@ -36,8 +36,7 @@ namespace JS {
 
 ScriptFunction* ScriptFunction::create(GlobalObject& global_object, const FlyString& name, const Statement& body, Vector<FlyString> parameters, LexicalEnvironment* parent_environment)
 {
-    auto& interpreter = global_object.interpreter();
-    return interpreter.heap().allocate<ScriptFunction>(name, body, move(parameters), parent_environment, *interpreter.function_prototype());
+    return global_object.heap().allocate<ScriptFunction>(name, body, move(parameters), parent_environment, *global_object.function_prototype());
 }
 
 ScriptFunction::ScriptFunction(const FlyString& name, const Statement& body, Vector<FlyString> parameters, LexicalEnvironment* parent_environment, Object& prototype)

+ 3 - 2
Libraries/LibJS/Runtime/StringConstructor.cpp

@@ -26,6 +26,7 @@
 
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/StringConstructor.h>
 #include <LibJS/Runtime/StringObject.h>
 #include <math.h>
@@ -33,9 +34,9 @@
 namespace JS {
 
 StringConstructor::StringConstructor()
-    : NativeFunction("String", *interpreter().function_prototype())
+    : NativeFunction("String", *interpreter().global_object().function_prototype())
 {
-    put("prototype", interpreter().string_prototype());
+    put("prototype", interpreter().global_object().string_prototype());
     put("length", Value(1));
 }
 

+ 1 - 2
Libraries/LibJS/Runtime/StringObject.cpp

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

+ 2 - 1
Libraries/LibJS/Runtime/StringPrototype.cpp

@@ -29,6 +29,7 @@
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/PrimitiveString.h>
 #include <LibJS/Runtime/StringObject.h>
 #include <LibJS/Runtime/StringPrototype.h>
@@ -38,7 +39,7 @@
 namespace JS {
 
 StringPrototype::StringPrototype()
-    : StringObject(*js_string(interpreter(), String::empty()), *interpreter().object_prototype())
+    : StringObject(*js_string(interpreter(), String::empty()), *interpreter().global_object().object_prototype())
 {
     put_native_property("length", length_getter, nullptr);
     put_native_function("charAt", char_at, 1);

+ 2 - 1
Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp

@@ -28,6 +28,7 @@
 #include <AK/Function.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/PrimitiveString.h>
 #include <LibJS/Runtime/Value.h>
 #include <LibWeb/Bindings/CanvasRenderingContext2DWrapper.h>
@@ -44,7 +45,7 @@ CanvasRenderingContext2DWrapper* wrap(JS::Heap& heap, CanvasRenderingContext2D&
 }
 
 CanvasRenderingContext2DWrapper::CanvasRenderingContext2DWrapper(CanvasRenderingContext2D& impl)
-    : Wrapper(*interpreter().object_prototype())
+    : Wrapper(*interpreter().global_object().object_prototype())
     , m_impl(impl)
 {
     put_native_property("fillStyle", fill_style_getter, fill_style_setter);

+ 2 - 1
Libraries/LibWeb/Bindings/EventListenerWrapper.cpp

@@ -26,6 +26,7 @@
 
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Function.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibWeb/Bindings/EventListenerWrapper.h>
 #include <LibWeb/DOM/EventListener.h>
 
@@ -33,7 +34,7 @@ namespace Web {
 namespace Bindings {
 
 EventListenerWrapper::EventListenerWrapper(EventListener& impl)
-    : Wrapper(*interpreter().object_prototype())
+    : Wrapper(*interpreter().global_object().object_prototype())
     , m_impl(impl)
 {
 }

+ 2 - 1
Libraries/LibWeb/Bindings/EventTargetWrapper.cpp

@@ -28,6 +28,7 @@
 #include <AK/Function.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Function.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibWeb/Bindings/EventListenerWrapper.h>
 #include <LibWeb/Bindings/EventTargetWrapper.h>
 #include <LibWeb/DOM/EventListener.h>
@@ -37,7 +38,7 @@ namespace Web {
 namespace Bindings {
 
 EventTargetWrapper::EventTargetWrapper(EventTarget& impl)
-    : Wrapper(*interpreter().object_prototype())
+    : Wrapper(*interpreter().global_object().object_prototype())
     , m_impl(impl)
 {
     put_native_function("addEventListener", add_event_listener, 2);

+ 2 - 1
Libraries/LibWeb/Bindings/EventWrapper.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibWeb/Bindings/EventWrapper.h>
 #include <LibWeb/Bindings/MouseEventWrapper.h>
 #include <LibWeb/DOM/MouseEvent.h>
@@ -40,7 +41,7 @@ EventWrapper* wrap(JS::Heap& heap, Event& event)
 }
 
 EventWrapper::EventWrapper(Event& event)
-    : Wrapper(*interpreter().object_prototype())
+    : Wrapper(*interpreter().global_object().object_prototype())
     , m_event(event)
 {
 }

+ 2 - 1
Libraries/LibWeb/Bindings/NavigatorObject.cpp

@@ -26,13 +26,14 @@
 
 #include <AK/FlyString.h>
 #include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibWeb/Bindings/NavigatorObject.h>
 
 namespace Web {
 namespace Bindings {
 
 NavigatorObject::NavigatorObject()
-    : Object(interpreter().object_prototype())
+    : Object(interpreter().global_object().object_prototype())
 {
     put("appCodeName", js_string(heap(), "Mozilla"));
     put("appName", js_string(heap(), "Netscape"));

+ 6 - 0
Libraries/LibWeb/Bindings/WindowObject.cpp

@@ -43,6 +43,12 @@ namespace Bindings {
 WindowObject::WindowObject(Window& impl)
     : m_impl(impl)
 {
+}
+
+void WindowObject::initialize()
+{
+    GlobalObject::initialize();
+
     put("window", this);
     put_native_property("document", document_getter, document_setter);
     put_native_function("alert", alert);

+ 1 - 0
Libraries/LibWeb/Bindings/WindowObject.h

@@ -35,6 +35,7 @@ namespace Bindings {
 class WindowObject final : public JS::GlobalObject {
 public:
     explicit WindowObject(Window&);
+    virtual void initialize() override;
     virtual ~WindowObject() override;
 
     Window& impl() { return *m_impl; }

+ 2 - 1
Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp

@@ -26,6 +26,7 @@
 
 #include <LibJS/Heap/Heap.h>
 #include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibWeb/Bindings/WindowObject.h>
 #include <LibWeb/Bindings/XMLHttpRequestConstructor.h>
 #include <LibWeb/Bindings/XMLHttpRequestWrapper.h>
@@ -35,7 +36,7 @@ namespace Web {
 namespace Bindings {
 
 XMLHttpRequestConstructor::XMLHttpRequestConstructor()
-    : NativeFunction(*interpreter().function_prototype())
+    : NativeFunction(*interpreter().global_object().function_prototype())
 {
     put("length", JS::Value(1));
 }

+ 2 - 1
Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp

@@ -27,6 +27,7 @@
 #include <AK/Function.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
 #include <LibWeb/Bindings/XMLHttpRequestPrototype.h>
 #include <LibWeb/Bindings/XMLHttpRequestWrapper.h>
 #include <LibWeb/DOM/XMLHttpRequest.h>
@@ -35,7 +36,7 @@ namespace Web {
 namespace Bindings {
 
 XMLHttpRequestPrototype::XMLHttpRequestPrototype()
-    : Object(interpreter().object_prototype())
+    : Object(interpreter().global_object().object_prototype())
 {
     put_native_function("open", open, 2);
     put_native_function("send", send, 0);

+ 6 - 0
Userland/js.cpp

@@ -50,6 +50,7 @@ Vector<String> repl_statements;
 class ReplObject : public JS::GlobalObject {
 public:
     ReplObject();
+    virtual void initialize() override;
     virtual ~ReplObject() override;
 
     static JS::Value load_file(JS::Interpreter&);
@@ -270,6 +271,11 @@ bool write_to_file(const StringView& path)
 
 ReplObject::ReplObject()
 {
+}
+
+void ReplObject::initialize()
+{
+    GlobalObject::initialize();
     put_native_function("exit", exit_interpreter);
     put_native_function("help", repl_help);
     put_native_function("load", load_file, 1);