瀏覽代碼

LibJS: Add Value::{is, as}_function()

Linus Groh 5 年之前
父節點
當前提交
eea62dd365

+ 3 - 4
Libraries/LibJS/AST.cpp

@@ -114,8 +114,7 @@ Value CallExpression::execute(Interpreter& interpreter) const
 
     ASSERT(!callee.is_empty());
 
-    if (!callee.is_object()
-        || !callee.as_object().is_function()
+    if (!callee.is_function()
         || (is_new_expression() && (callee.as_object().is_native_function() && !static_cast<NativeFunction&>(callee.as_object()).has_constructor()))) {
         String error_message;
         auto call_type = is_new_expression() ? "constructor" : "function";
@@ -132,7 +131,7 @@ Value CallExpression::execute(Interpreter& interpreter) const
         return interpreter.throw_exception<TypeError>(error_message);
     }
 
-    auto& function = static_cast<Function&>(callee.as_object());
+    auto& function = callee.as_function();
 
     MarkedValueList arguments(interpreter.heap());
     arguments.values().append(function.bound_arguments());
@@ -469,7 +468,7 @@ Value UnaryExpression::execute(Interpreter& interpreter) const
         case Value::Type::String:
             return js_string(interpreter, "string");
         case Value::Type::Object:
-            if (lhs_result.as_object().is_function())
+            if (lhs_result.is_function())
                 return js_string(interpreter, "function");
             return js_string(interpreter, "object");
         case Value::Type::Boolean:

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

@@ -76,11 +76,11 @@ static Function* callback_from_args(Interpreter& interpreter, const String& name
         return nullptr;
     }
     auto callback = interpreter.argument(0);
-    if (!callback.is_object() || !callback.as_object().is_function()) {
+    if (!callback.is_function()) {
         interpreter.throw_exception<TypeError>(String::format("%s is not a function", callback.to_string().characters()));
         return nullptr;
     }
-    return static_cast<Function*>(&callback.as_object());
+    return &callback.as_function();
 }
 
 Value ArrayPrototype::filter(Interpreter& interpreter)

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

@@ -477,10 +477,8 @@ Value Object::to_primitive(PreferredType preferred_type) const
 Value Object::to_string() const
 {
     auto to_string_property = get("toString");
-    if (!to_string_property.is_empty()
-        && to_string_property.is_object()
-        && to_string_property.as_object().is_function()) {
-        auto& to_string_function = static_cast<Function&>(to_string_property.as_object());
+    if (!to_string_property.is_empty() && to_string_property.is_function()) {
+        auto& to_string_function = to_string_property.as_function();
         auto& interpreter = const_cast<Object*>(this)->interpreter();
         auto to_string_result = interpreter.call(to_string_function, const_cast<Object*>(this));
         if (to_string_result.is_object())

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

@@ -47,11 +47,11 @@ static Object* get_target_object_from(Interpreter& interpreter, const String& na
 static Function* get_target_function_from(Interpreter& interpreter, const String& name)
 {
     auto target = interpreter.argument(0);
-    if (!target.is_object() || !target.as_object().is_function()) {
+    if (!target.is_function()) {
         interpreter.throw_exception<TypeError>(String::format("First argument of Reflect.%s() must be a function", name.characters()));
         return nullptr;
     }
-    return static_cast<Function*>(&target.as_object());
+    return &target.as_function();
 }
 
 static void prepare_arguments_list(Interpreter& interpreter, Value value, MarkedValueList* arguments)
@@ -121,13 +121,12 @@ Value ReflectObject::construct(Interpreter& interpreter)
     auto* new_target = target;
     if (interpreter.argument_count() > 2) {
         auto new_target_value = interpreter.argument(2);
-        if (!new_target_value.is_object()
-            || !new_target_value.as_object().is_function()
+        if (!new_target_value.is_function()
             || (new_target_value.as_object().is_native_function() && !static_cast<NativeFunction&>(new_target_value.as_object()).has_constructor())) {
             interpreter.throw_exception<TypeError>("Optional third argument of Reflect.construct() must be a constructor");
             return {};
         }
-        new_target = static_cast<Function*>(&new_target_value.as_object());
+        new_target = &new_target_value.as_function();
     }
     return interpreter.construct(*target, *new_target, move(arguments));
 }

+ 12 - 0
Libraries/LibJS/Runtime/Value.cpp

@@ -31,6 +31,7 @@
 #include <LibJS/Runtime/Array.h>
 #include <LibJS/Runtime/BooleanObject.h>
 #include <LibJS/Runtime/Error.h>
+#include <LibJS/Runtime/Function.h>
 #include <LibJS/Runtime/NumberObject.h>
 #include <LibJS/Runtime/Object.h>
 #include <LibJS/Runtime/PrimitiveString.h>
@@ -48,6 +49,17 @@ bool Value::is_array() const
     return is_object() && as_object().is_array();
 }
 
+bool Value::is_function() const
+{
+    return is_object() && as_object().is_function();
+}
+
+Function& Value::as_function()
+{
+    ASSERT(is_function());
+    return static_cast<Function&>(as_object());
+}
+
 String Value::to_string() const
 {
     if (is_boolean())

+ 3 - 0
Libraries/LibJS/Runtime/Value.h

@@ -54,6 +54,7 @@ public:
     bool is_boolean() const { return m_type == Type::Boolean; }
     bool is_cell() const { return is_string() || is_object(); }
     bool is_array() const;
+    bool is_function() const;
 
     bool is_nan() const { return is_number() && __builtin_isnan(as_double()); }
     bool is_infinity() const { return is_number() && __builtin_isinf(as_double()); }
@@ -157,6 +158,8 @@ public:
         return m_value.as_cell;
     }
 
+    Function& as_function();
+
     String to_string() const;
     bool to_boolean() const;
     Value to_number() const;