Browse Source

LibJS+LibWeb: Pass prototype to Object constructor

Everyone who constructs an Object must now pass a prototype object when
applicable. There's still a fair amount of code that passes something
fetched from the Interpreter, but this brings us closer to being able
to detach prototypes from Interpreter eventually.
Andreas Kling 5 years ago
parent
commit
bc1ece7f37
30 changed files with 60 additions and 28 deletions
  1. 2 2
      Libraries/LibJS/AST.cpp
  2. 2 2
      Libraries/LibJS/Runtime/Array.cpp
  3. 1 0
      Libraries/LibJS/Runtime/ArrayPrototype.cpp
  4. 2 2
      Libraries/LibJS/Runtime/BooleanObject.cpp
  5. 1 0
      Libraries/LibJS/Runtime/ConsoleObject.cpp
  6. 2 1
      Libraries/LibJS/Runtime/Date.cpp
  7. 1 0
      Libraries/LibJS/Runtime/DatePrototype.cpp
  8. 2 1
      Libraries/LibJS/Runtime/Error.cpp
  9. 2 1
      Libraries/LibJS/Runtime/ErrorPrototype.cpp
  10. 1 1
      Libraries/LibJS/Runtime/Function.cpp
  11. 1 0
      Libraries/LibJS/Runtime/FunctionPrototype.cpp
  12. 1 0
      Libraries/LibJS/Runtime/GlobalObject.cpp
  13. 1 0
      Libraries/LibJS/Runtime/MathObject.cpp
  14. 2 1
      Libraries/LibJS/Runtime/NativeProperty.cpp
  15. 2 2
      Libraries/LibJS/Runtime/NumberObject.cpp
  16. 9 2
      Libraries/LibJS/Runtime/Object.cpp
  17. 3 1
      Libraries/LibJS/Runtime/Object.h
  18. 2 2
      Libraries/LibJS/Runtime/ObjectConstructor.cpp
  19. 1 1
      Libraries/LibJS/Runtime/ObjectPrototype.cpp
  20. 1 1
      Libraries/LibJS/Runtime/ScriptFunction.cpp
  21. 2 2
      Libraries/LibJS/Runtime/StringObject.cpp
  22. 2 1
      Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.cpp
  23. 1 1
      Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h
  24. 3 1
      Libraries/LibWeb/Bindings/EventListenerWrapper.cpp
  25. 2 1
      Libraries/LibWeb/Bindings/EventTargetWrapper.cpp
  26. 3 1
      Libraries/LibWeb/Bindings/EventWrapper.cpp
  27. 2 0
      Libraries/LibWeb/Bindings/NavigatorObject.cpp
  28. 4 1
      Libraries/LibWeb/Bindings/Wrapper.h
  29. 1 0
      Libraries/LibWeb/Bindings/XMLHttpRequestConstructor.cpp
  30. 1 0
      Libraries/LibWeb/Bindings/XMLHttpRequestPrototype.cpp

+ 2 - 2
Libraries/LibJS/AST.cpp

@@ -124,7 +124,7 @@ Value CallExpression::execute(Interpreter& interpreter) const
     Object* new_object = nullptr;
     Value result;
     if (is_new_expression()) {
-        new_object = interpreter.heap().allocate<Object>();
+        new_object = Object::create_empty(interpreter, interpreter.global_object());
         auto prototype = function.get("prototype");
         if (prototype.has_value() && prototype.value().is_object())
             new_object->set_prototype(&prototype.value().as_object());
@@ -901,7 +901,7 @@ void ExpressionStatement::dump(int indent) const
 
 Value ObjectExpression::execute(Interpreter& interpreter) const
 {
-    auto object = interpreter.heap().allocate<Object>();
+    auto* object = Object::create_empty(interpreter, interpreter.global_object());
     for (auto it : m_properties) {
         auto value = it.value->execute(interpreter);
         if (interpreter.exception())

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

@@ -27,9 +27,9 @@
 #include <AK/Function.h>
 #include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Array.h>
-#include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/ArrayPrototype.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/GlobalObject.h>
 
 namespace JS {
 
@@ -40,8 +40,8 @@ Array* Array::create(GlobalObject& global_object)
 }
 
 Array::Array(Object& prototype)
+    : Object(&prototype)
 {
-    set_prototype(&prototype);
     put_native_property("length", length_getter, length_setter);
 }
 

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

@@ -38,6 +38,7 @@
 namespace JS {
 
 ArrayPrototype::ArrayPrototype()
+    : Object(interpreter().object_prototype())
 {
     put_native_function("filter", filter, 1);
     put_native_function("forEach", for_each, 1);

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

@@ -37,9 +37,9 @@ BooleanObject* BooleanObject::create(GlobalObject& global_object, bool value)
 }
 
 BooleanObject::BooleanObject(bool value, Object& prototype)
-    : m_value(value)
+    : Object(&prototype)
+    , m_value(value)
 {
-    set_prototype(&prototype);
 }
 
 BooleanObject::~BooleanObject()

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

@@ -44,6 +44,7 @@ static void print_args(Interpreter& interpreter)
 }
 
 ConsoleObject::ConsoleObject()
+    : Object(interpreter().object_prototype())
 {
     put_native_function("log", log);
     put_native_function("debug", debug);

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

@@ -38,7 +38,8 @@ Date* Date::create(GlobalObject& global_object, Core::DateTime datetime, u16 mil
 }
 
 Date::Date(Core::DateTime datetime, u16 milliseconds, Object& prototype)
-    : m_datetime(datetime)
+    : Object(&prototype)
+    , m_datetime(datetime)
     , m_milliseconds(milliseconds)
 {
     set_prototype(&prototype);

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

@@ -48,6 +48,7 @@ static Date* this_date_from_interpreter(Interpreter& interpreter)
 }
 
 DatePrototype::DatePrototype()
+    : Object(interpreter().object_prototype())
 {
     put_native_function("getDate", get_date);
     put_native_function("getDay", get_day);

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

@@ -37,7 +37,8 @@ Error* Error::create(GlobalObject& global_object, const FlyString& name, const S
 }
 
 Error::Error(const FlyString& name, const String& message, Object& prototype)
-    : m_name(name)
+    : Object(&prototype)
+    , m_name(name)
     , m_message(message)
 {
     set_prototype(&prototype);

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

@@ -35,6 +35,7 @@
 namespace JS {
 
 ErrorPrototype::ErrorPrototype()
+    : Object(interpreter().object_prototype())
 {
     put_native_property("name", name_getter, name_setter);
     put_native_property("message", message_getter, nullptr);
@@ -103,8 +104,8 @@ Value ErrorPrototype::to_string(Interpreter& interpreter)
 
 #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName) \
     PrototypeName::PrototypeName()                                            \
+        : Object(interpreter().error_prototype())                             \
     {                                                                         \
-        set_prototype(interpreter().error_prototype());                       \
     }                                                                         \
     PrototypeName::~PrototypeName() {}                                        \
     const char* PrototypeName::class_name() const { return #PrototypeName; }

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

@@ -30,8 +30,8 @@
 namespace JS {
 
 Function::Function(Object& prototype)
+    : Object(&prototype)
 {
-    set_prototype(&prototype);
 }
 
 Function::~Function()

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

@@ -36,6 +36,7 @@
 namespace JS {
 
 FunctionPrototype::FunctionPrototype()
+    : Object(interpreter().object_prototype())
 {
 }
 

+ 1 - 0
Libraries/LibJS/Runtime/GlobalObject.cpp

@@ -53,6 +53,7 @@ void GlobalObject::add_constructor(const FlyString& property_name, ConstructorTy
 }
 
 GlobalObject::GlobalObject()
+    : Object(interpreter().object_prototype())
 {
     put_native_function("gc", gc);
     put_native_function("isNaN", is_nan, 1);

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

@@ -33,6 +33,7 @@
 namespace JS {
 
 MathObject::MathObject()
+    : Object(interpreter().object_prototype())
 {
     put_native_function("abs", abs, 1);
     put_native_function("random", random);

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

@@ -30,7 +30,8 @@
 namespace JS {
 
 NativeProperty::NativeProperty(AK::Function<Value(Interpreter&)> getter, AK::Function<void(Interpreter&, Value)> setter)
-    : m_getter(move(getter))
+    : Object(nullptr)
+    , m_getter(move(getter))
     , m_setter(move(setter))
 {
 }

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

@@ -40,9 +40,9 @@ NumberObject* NumberObject::create(GlobalObject& global_object, double value)
 }
 
 NumberObject::NumberObject(double value, Object& prototype)
-    : m_value(value)
+    : Object(&prototype)
+    , m_value(value)
 {
-    set_prototype(&prototype);
 }
 
 NumberObject::~NumberObject()

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

@@ -38,10 +38,15 @@
 
 namespace JS {
 
-Object::Object()
+Object* Object::create_empty(Interpreter& interpreter, GlobalObject&)
+{
+    return interpreter.heap().allocate<Object>(interpreter.object_prototype());
+}
+
+Object::Object(Object* prototype)
 {
     m_shape = interpreter().empty_object_shape();
-    m_shape->set_prototype_without_transition(interpreter().object_prototype());
+    set_prototype(prototype);
 }
 
 Object::~Object()
@@ -60,6 +65,8 @@ const Object* Object::prototype() const
 
 void Object::set_prototype(Object* new_prototype)
 {
+    if (prototype() == new_prototype)
+        return;
     m_shape = m_shape->create_prototype_transition(new_prototype);
 }
 

+ 3 - 1
Libraries/LibJS/Runtime/Object.h

@@ -38,7 +38,9 @@ namespace JS {
 
 class Object : public Cell {
 public:
-    Object();
+    static Object* create_empty(Interpreter&, GlobalObject&);
+
+    explicit Object(Object* prototype);
     virtual ~Object();
 
     Shape& shape() { return *m_shape; }

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

@@ -52,7 +52,7 @@ ObjectConstructor::~ObjectConstructor()
 
 Value ObjectConstructor::call(Interpreter& interpreter)
 {
-    return interpreter.heap().allocate<Object>();
+    return Object::create_empty(interpreter, interpreter.global_object());
 }
 
 Value ObjectConstructor::construct(Interpreter& interpreter)
@@ -109,7 +109,7 @@ Value ObjectConstructor::get_own_property_descriptor(Interpreter& interpreter)
     auto metadata = object.shape().lookup(interpreter.argument(1).to_string());
     if (!metadata.has_value())
         return js_undefined();
-    auto* descriptor = interpreter.heap().allocate<Object>();
+    auto* descriptor = Object::create_empty(interpreter, interpreter.global_object());
     descriptor->put("configurable", Value(!!(metadata.value().attributes & Attribute::Configurable)));
     descriptor->put("enumerable", Value(!!(metadata.value().attributes & Attribute::Enumerable)));
     descriptor->put("writable", Value(!!(metadata.value().attributes & Attribute::Writable)));

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

@@ -34,8 +34,8 @@
 namespace JS {
 
 ObjectPrototype::ObjectPrototype()
+    : Object(nullptr)
 {
-    set_prototype(nullptr);
 }
 
 void ObjectPrototype::initialize()

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

@@ -47,7 +47,7 @@ ScriptFunction::ScriptFunction(const FlyString& name, const Statement& body, Vec
     , m_parameters(move(parameters))
     , m_parent_environment(parent_environment)
 {
-    put("prototype", heap().allocate<Object>());
+    put("prototype", Object::create_empty(interpreter(), interpreter().global_object()));
     put_native_property("length", length_getter, length_setter);
 }
 

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

@@ -41,9 +41,9 @@ StringObject* StringObject::create(GlobalObject& global_object, PrimitiveString&
 }
 
 StringObject::StringObject(PrimitiveString& string, Object& prototype)
-    : m_string(string)
+    : Object(&prototype)
+    , m_string(string)
 {
-    set_prototype(&prototype);
 }
 
 StringObject::~StringObject()

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

@@ -44,7 +44,8 @@ CanvasRenderingContext2DWrapper* wrap(JS::Heap& heap, CanvasRenderingContext2D&
 }
 
 CanvasRenderingContext2DWrapper::CanvasRenderingContext2DWrapper(CanvasRenderingContext2D& impl)
-    : m_impl(impl)
+    : Wrapper(*interpreter().object_prototype())
+    , m_impl(impl)
 {
     put_native_property("fillStyle", fill_style_getter, fill_style_setter);
     put_native_function("fillRect", fill_rect, 4);

+ 1 - 1
Libraries/LibWeb/Bindings/CanvasRenderingContext2DWrapper.h

@@ -31,7 +31,7 @@
 namespace Web {
 namespace Bindings {
 
-class CanvasRenderingContext2DWrapper : public Wrapper {
+class CanvasRenderingContext2DWrapper final : public Wrapper {
 public:
     explicit CanvasRenderingContext2DWrapper(CanvasRenderingContext2D&);
     virtual ~CanvasRenderingContext2DWrapper() override;

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

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <LibJS/Interpreter.h>
 #include <LibJS/Runtime/Function.h>
 #include <LibWeb/Bindings/EventListenerWrapper.h>
 #include <LibWeb/DOM/EventListener.h>
@@ -32,7 +33,8 @@ namespace Web {
 namespace Bindings {
 
 EventListenerWrapper::EventListenerWrapper(EventListener& impl)
-    : m_impl(impl)
+    : Wrapper(*interpreter().object_prototype())
+    , m_impl(impl)
 {
 }
 

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

@@ -37,7 +37,8 @@ namespace Web {
 namespace Bindings {
 
 EventTargetWrapper::EventTargetWrapper(EventTarget& impl)
-    : m_impl(impl)
+    : Wrapper(*interpreter().object_prototype())
+    , m_impl(impl)
 {
     put_native_function("addEventListener", add_event_listener, 2);
 }

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

@@ -24,6 +24,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <LibJS/Interpreter.h>
 #include <LibWeb/Bindings/EventWrapper.h>
 #include <LibWeb/Bindings/MouseEventWrapper.h>
 #include <LibWeb/DOM/MouseEvent.h>
@@ -39,7 +40,8 @@ EventWrapper* wrap(JS::Heap& heap, Event& event)
 }
 
 EventWrapper::EventWrapper(Event& event)
-    : m_event(event)
+    : Wrapper(*interpreter().object_prototype())
+    , m_event(event)
 {
 }
 

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

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

+ 4 - 1
Libraries/LibWeb/Bindings/Wrapper.h

@@ -38,7 +38,10 @@ class Wrapper
     : public JS::Object
     , public Weakable<Wrapper> {
 protected:
-    explicit Wrapper() {}
+    explicit Wrapper(Object& prototype)
+        : Object(&prototype)
+    {
+    }
 };
 
 }

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

@@ -35,6 +35,7 @@ namespace Web {
 namespace Bindings {
 
 XMLHttpRequestConstructor::XMLHttpRequestConstructor()
+    : NativeFunction(*interpreter().function_prototype())
 {
     put("length", JS::Value(1));
 }

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

@@ -35,6 +35,7 @@ namespace Web {
 namespace Bindings {
 
 XMLHttpRequestPrototype::XMLHttpRequestPrototype()
+    : Object(interpreter().object_prototype())
 {
     put_native_function("open", open, 2);
     put_native_function("send", send, 0);