1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-22 19:45:08 +00:00

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

This commit is contained in:
Linus Groh 2020-05-06 11:52:53 +01:00 committed by Andreas Kling
parent 419bce6915
commit eea62dd365
6 changed files with 26 additions and 15 deletions

View file

@ -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:

View file

@ -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)

View file

@ -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())

View file

@ -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));
}

View file

@ -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())

View file

@ -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;