Bladeren bron

LibJS: Make Value::as_object() return Object&

Let's move towards using references over pointers in LibJS as well.
I had originally steered away from it because that's how I've seen
things done in other engines. But this is not the other engines. :^)
Andreas Kling 5 jaren geleden
bovenliggende
commit
1549c5c48b

+ 9 - 9
Libraries/LibJS/AST.cpp

@@ -90,16 +90,16 @@ Value CallExpression::execute(Interpreter& interpreter) const
 
     if (is_new_expression()) {
         if (!callee.is_object()
-            || !callee.as_object()->is_function()
-            || (callee.as_object()->is_native_function()
-                && !static_cast<NativeFunction*>(callee.as_object())->has_constructor()))
+            || !callee.as_object().is_function()
+            || (callee.as_object().is_native_function()
+                && !static_cast<NativeFunction&>(callee.as_object()).has_constructor()))
             return interpreter.throw_exception<Error>("TypeError", String::format("%s is not a constructor", callee.to_string().characters()));
     }
 
-    if (!callee.is_object() || !callee.as_object()->is_function())
+    if (!callee.is_object() || !callee.as_object().is_function())
         return interpreter.throw_exception<Error>("TypeError", String::format("%s is not a function", callee.to_string().characters()));
 
-    auto* function = static_cast<Function*>(callee.as_object());
+    auto& function = static_cast<Function&>(callee.as_object());
 
     auto& call_frame = interpreter.push_call_frame();
     for (size_t i = 0; i < m_arguments.size(); ++i) {
@@ -115,14 +115,14 @@ Value CallExpression::execute(Interpreter& interpreter) const
     Value result;
     if (is_new_expression()) {
         new_object = interpreter.heap().allocate<Object>();
-        auto prototype = function->get("prototype");
+        auto prototype = function.get("prototype");
         if (prototype.has_value() && prototype.value().is_object())
-            new_object->set_prototype(prototype.value().as_object());
+            new_object->set_prototype(&prototype.value().as_object());
         call_frame.this_value = new_object;
-        result = function->construct(interpreter);
+        result = function.construct(interpreter);
     } else {
         call_frame.this_value = this_value;
-        result = function->call(interpreter);
+        result = function.call(interpreter);
     }
 
     interpreter.pop_call_frame();

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

@@ -47,10 +47,10 @@ DateConstructor::~DateConstructor()
 
 Value DateConstructor::call(Interpreter& interpreter)
 {
-    auto* date = static_cast<Date*>(construct(interpreter).as_object());
-    if (!date)
+    auto date = construct(interpreter);
+    if (!date.is_object())
         return {};
-    return js_string(interpreter.heap(), date->string());
+    return js_string(interpreter.heap(), static_cast<Date&>(date.as_object()).string());
 }
 
 Value DateConstructor::construct(Interpreter& interpreter)

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

@@ -56,8 +56,8 @@ bool Object::has_prototype(const Object* prototype) const
 Optional<Value> Object::get_own_property(const Object& this_object, const FlyString& property_name) const
 {
     auto value_here = m_properties.get(property_name);
-    if (value_here.has_value() && value_here.value().is_object() && value_here.value().as_object()->is_native_property()) {
-        auto& native_property = static_cast<const NativeProperty&>(*value_here.value().as_object());
+    if (value_here.has_value() && value_here.value().is_object() && value_here.value().as_object().is_native_property()) {
+        auto& native_property = static_cast<const NativeProperty&>(value_here.value().as_object());
         auto& interpreter = const_cast<Object*>(this)->interpreter();
         auto& call_frame = interpreter.push_call_frame();
         call_frame.this_value = const_cast<Object*>(&this_object);
@@ -71,8 +71,8 @@ Optional<Value> Object::get_own_property(const Object& this_object, const FlyStr
 bool Object::put_own_property(Object& this_object, const FlyString& property_name, Value value)
 {
     auto value_here = m_properties.get(property_name);
-    if (value_here.has_value() && value_here.value().is_object() && value_here.value().as_object()->is_native_property()) {
-        auto& native_property = static_cast<NativeProperty&>(*value_here.value().as_object());
+    if (value_here.has_value() && value_here.value().is_object() && value_here.value().as_object().is_native_property()) {
+        auto& native_property = static_cast<NativeProperty&>(value_here.value().as_object());
         auto& interpreter = const_cast<Object*>(this)->interpreter();
         auto& call_frame = interpreter.push_call_frame();
         call_frame.this_value = &this_object;
@@ -103,8 +103,8 @@ void Object::put(const FlyString& property_name, Value value)
     while (object) {
         auto value_here = object->m_properties.get(property_name);
         if (value_here.has_value()) {
-            if (value_here.value().is_object() && value_here.value().as_object()->is_native_property()) {
-                auto& native_property = static_cast<NativeProperty&>(*value_here.value().as_object());
+            if (value_here.value().is_object() && value_here.value().as_object().is_native_property()) {
+                auto& native_property = static_cast<NativeProperty&>(value_here.value().as_object());
                 auto& interpreter = const_cast<Object*>(this)->interpreter();
                 auto& call_frame = interpreter.push_call_frame();
                 call_frame.this_value = this;

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

@@ -92,7 +92,7 @@ Value ObjectConstructor::set_prototype_of(Interpreter& interpreter)
     auto* object = interpreter.call_frame().arguments[0].to_object(interpreter.heap());
     if (interpreter.exception())
         return {};
-    object->set_prototype(const_cast<Object*>(interpreter.call_frame().arguments[1].as_object()));
+    object->set_prototype(&const_cast<Object&>(interpreter.call_frame().arguments[1].as_object()));
     return {};
 }
 

+ 10 - 10
Libraries/LibJS/Runtime/Value.cpp

@@ -39,7 +39,7 @@ namespace JS {
 
 bool Value::is_array() const
 {
-    return is_object() && as_object()->is_array();
+    return is_object() && as_object().is_array();
 }
 
 String Value::to_string() const
@@ -64,7 +64,7 @@ String Value::to_string() const
     }
 
     if (is_object())
-        return as_object()->to_primitive(Object::PreferredType::String).to_string();
+        return as_object().to_primitive(Object::PreferredType::String).to_string();
 
     if (is_string())
         return m_value.as_string->string();
@@ -94,7 +94,7 @@ bool Value::to_boolean() const
 Object* Value::to_object(Heap& heap) const
 {
     if (is_object())
-        return const_cast<Object*>(as_object());
+        return &const_cast<Object&>(as_object());
 
     if (is_string())
         return heap.allocate<StringObject>(m_value.as_string);
@@ -241,7 +241,7 @@ Value typed_eq(Value lhs, Value rhs)
     case Value::Type::Boolean:
         return Value(lhs.as_bool() == rhs.as_bool());
     case Value::Type::Object:
-        return Value(lhs.as_object() == rhs.as_object());
+        return Value(&lhs.as_object() == &rhs.as_object());
     }
 
     ASSERT_NOT_REACHED();
@@ -256,16 +256,16 @@ Value eq(Value lhs, Value rhs)
         return Value(true);
 
     if (lhs.is_object() && rhs.is_boolean())
-        return eq(lhs.as_object()->to_primitive(), rhs.to_number());
+        return eq(lhs.as_object().to_primitive(), rhs.to_number());
 
     if (lhs.is_boolean() && rhs.is_object())
-        return eq(lhs.to_number(), rhs.as_object()->to_primitive());
+        return eq(lhs.to_number(), rhs.as_object().to_primitive());
 
     if (lhs.is_object())
-        return eq(lhs.as_object()->to_primitive(), rhs);
+        return eq(lhs.as_object().to_primitive(), rhs);
 
     if (rhs.is_object())
-        return eq(lhs, rhs.as_object()->to_primitive());
+        return eq(lhs, rhs.as_object().to_primitive());
 
     if (lhs.is_number() || rhs.is_number())
         return Value(lhs.to_number().as_double() == rhs.to_number().as_double());
@@ -281,11 +281,11 @@ Value instance_of(Value lhs, Value rhs)
     if (!lhs.is_object() || !rhs.is_object())
         return Value(false);
 
-    auto constructor_prototype_property = rhs.as_object()->get("prototype");
+    auto constructor_prototype_property = rhs.as_object().get("prototype");
     if (!constructor_prototype_property.has_value() || !constructor_prototype_property.value().is_object())
         return Value(false);
 
-    return Value(lhs.as_object()->has_prototype(constructor_prototype_property.value().as_object()));
+    return Value(lhs.as_object().has_prototype(&constructor_prototype_property.value().as_object()));
 }
 
 const LogStream& operator<<(const LogStream& stream, const Value& value)

+ 4 - 4
Libraries/LibJS/Runtime/Value.h

@@ -109,16 +109,16 @@ public:
         return m_value.as_bool;
     }
 
-    Object* as_object()
+    Object& as_object()
     {
         ASSERT(type() == Type::Object);
-        return m_value.as_object;
+        return *m_value.as_object;
     }
 
-    const Object* as_object() const
+    const Object& as_object() const
     {
         ASSERT(type() == Type::Object);
-        return m_value.as_object;
+        return *m_value.as_object;
     }
 
     PrimitiveString* as_string()

+ 3 - 3
Libraries/LibWeb/Bindings/EventTargetWrapper.cpp

@@ -56,9 +56,9 @@ JS::Value EventTargetWrapper::add_event_listener(JS::Interpreter& interpreter)
         return JS::js_undefined();
     auto event_name = arguments[0].to_string();
     ASSERT(arguments[1].is_object());
-    ASSERT(arguments[1].as_object()->is_function());
-    auto* function = static_cast<JS::Function*>(const_cast<Object*>(arguments[1].as_object()));
-    auto listener = adopt(*new EventListener(JS::make_handle(function)));
+    ASSERT(arguments[1].as_object().is_function());
+    auto& function = static_cast<JS::Function&>(const_cast<Object&>(arguments[1].as_object()));
+    auto listener = adopt(*new EventListener(JS::make_handle(&function)));
     static_cast<EventTargetWrapper*>(this_object)->impl().add_event_listener(event_name, move(listener));
     return JS::js_undefined();
 }

+ 18 - 18
Userland/js.cpp

@@ -97,61 +97,61 @@ String read_next_piece()
 
 static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects);
 
-static void print_array(const JS::Array* array, HashTable<JS::Object*>& seen_objects)
+static void print_array(const JS::Array& array, HashTable<JS::Object*>& seen_objects)
 {
     fputs("[ ", stdout);
-    for (size_t i = 0; i < array->elements().size(); ++i) {
-        print_value(array->elements()[i], seen_objects);
-        if (i != array->elements().size() - 1)
+    for (size_t i = 0; i < array.elements().size(); ++i) {
+        print_value(array.elements()[i], seen_objects);
+        if (i != array.elements().size() - 1)
             fputs(", ", stdout);
     }
     fputs(" ]", stdout);
 }
 
-static void print_object(const JS::Object* object, HashTable<JS::Object*>& seen_objects)
+static void print_object(const JS::Object& object, HashTable<JS::Object*>& seen_objects)
 {
     fputs("{ ", stdout);
     size_t index = 0;
-    for (auto& it : object->own_properties()) {
+    for (auto& it : object.own_properties()) {
         printf("\"\033[33;1m%s\033[0m\": ", it.key.characters());
         print_value(it.value, seen_objects);
-        if (index != object->own_properties().size() - 1)
+        if (index != object.own_properties().size() - 1)
             fputs(", ", stdout);
         ++index;
     }
     fputs(" }", stdout);
 }
 
-static void print_function(const JS::Object* function, HashTable<JS::Object*>&)
+static void print_function(const JS::Object& function, HashTable<JS::Object*>&)
 {
-    printf("\033[34;1m[%s]\033[0m", function->class_name());
+    printf("\033[34;1m[%s]\033[0m", function.class_name());
 }
 
-static void print_date(const JS::Object* date, HashTable<JS::Object*>&)
+static void print_date(const JS::Object& date, HashTable<JS::Object*>&)
 {
-    printf("\033[34;1mDate %s\033[0m", static_cast<const JS::Date*>(date)->string().characters());
+    printf("\033[34;1mDate %s\033[0m", static_cast<const JS::Date&>(date).string().characters());
 }
 
 void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
 {
     if (value.is_object()) {
-        if (seen_objects.contains(value.as_object())) {
+        if (seen_objects.contains(&value.as_object())) {
             // FIXME: Maybe we should only do this for circular references,
             //        not for all reoccurring objects.
-            printf("<already printed Object %p>", value.as_object());
+            printf("<already printed Object %p>", &value.as_object());
             return;
         }
-        seen_objects.set(value.as_object());
+        seen_objects.set(&value.as_object());
     }
 
     if (value.is_array())
-        return print_array(static_cast<const JS::Array*>(value.as_object()), seen_objects);
+        return print_array(static_cast<const JS::Array&>(value.as_object()), seen_objects);
 
     if (value.is_object()) {
-        auto* object = value.as_object();
-        if (object->is_function())
+        auto& object = value.as_object();
+        if (object.is_function())
             return print_function(object, seen_objects);
-        if (object->is_date())
+        if (object.is_date())
             return print_date(object, seen_objects);
         return print_object(object, seen_objects);
     }