LibJS: Remove hand-rolled Object is_foo() helpers in favor of RTTI

This commit is contained in:
Andreas Kling 2021-01-01 17:46:39 +01:00
parent 8333055c3d
commit f48751a739
Notes: sideshowbarker 2024-07-19 00:15:57 +09:00
47 changed files with 78 additions and 107 deletions

View file

@ -54,7 +54,7 @@ GUI::Variant SheetModel::data(const GUI::ModelIndex& index, GUI::ModelRole role)
auto value = exception->value();
if (value.is_object()) {
auto& object = value.as_object();
if (object.is_error()) {
if (is<JS::Error>(object)) {
auto error = object.get("message").to_string_without_side_effects();
builder.append(error);
return builder.to_string();

View file

@ -61,7 +61,7 @@ static void update_function_name(Value value, const FlyString& name, HashTable<J
auto& object = value.as_object();
if (object.is_function()) {
auto& function = static_cast<Function&>(object);
if (function.is_script_function() && function.name().is_empty())
if (is<ScriptFunction>(function) && function.name().is_empty())
static_cast<ScriptFunction&>(function).set_name(name);
} else if (object.is_array()) {
auto& array = static_cast<Array&>(object);
@ -178,7 +178,7 @@ Value CallExpression::execute(Interpreter& interpreter, GlobalObject& global_obj
ASSERT(!callee.is_empty());
if (!callee.is_function()
|| (is_new_expression() && (callee.as_object().is_native_function() && !static_cast<NativeFunction&>(callee.as_object()).has_constructor()))) {
|| (is_new_expression() && (is<NativeFunction>(callee.as_object()) && !static_cast<NativeFunction&>(callee.as_object()).has_constructor()))) {
String error_message;
auto call_type = is_new_expression() ? "constructor" : "function";
if (m_callee->is_identifier() || m_callee->is_member_expression()) {
@ -793,7 +793,7 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
update_function_name(class_constructor_value, m_name);
ASSERT(class_constructor_value.is_function() && class_constructor_value.as_function().is_script_function());
ASSERT(class_constructor_value.is_function() && is<ScriptFunction>(class_constructor_value.as_function()));
ScriptFunction* class_constructor = static_cast<ScriptFunction*>(&class_constructor_value.as_function());
class_constructor->set_is_class_constructor();
Value super_constructor = js_undefined();

View file

@ -190,7 +190,7 @@ Value Interpreter::execute_statement(GlobalObject& global_object, const Statemen
LexicalEnvironment* Interpreter::current_environment()
{
ASSERT(vm().call_frame().scope->is_lexical_environment());
ASSERT(is<LexicalEnvironment>(vm().call_frame().scope));
return static_cast<LexicalEnvironment*>(vm().call_frame().scope);
}

View file

@ -77,9 +77,9 @@ void MarkupGenerator::value_to_html(Value value, StringBuilder& output_html, Has
auto& object = value.as_object();
if (object.is_function())
return function_to_html(object, output_html, seen_objects);
if (object.is_date())
if (is<Date>(object))
return date_to_html(object, output_html, seen_objects);
if (object.is_error())
if (is<Error>(object))
return error_to_html(object, output_html, seen_objects);
return object_to_html(object, output_html, seen_objects);
}

View file

@ -45,8 +45,6 @@ public:
const ByteBuffer& buffer() const { return m_buffer; }
private:
virtual bool is_array_buffer() const override { return true; }
ByteBuffer m_buffer;
};

View file

@ -59,7 +59,7 @@ static ArrayBuffer* array_buffer_object_from(VM& vm, GlobalObject& global_object
if (!this_value.is_object())
return nullptr;
auto& this_object = this_value.as_object();
if (!this_object.is_array_buffer()) {
if (!is<ArrayBuffer>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "ArrayBuffer");
return nullptr;
}

View file

@ -46,7 +46,6 @@ public:
private:
friend class ArrayIteratorPrototype;
virtual bool is_array_iterator_object() const override { return true; }
virtual void visit_edges(Cell::Visitor&) override;
Value m_array;

View file

@ -54,7 +54,7 @@ ArrayIteratorPrototype::~ArrayIteratorPrototype()
JS_DEFINE_NATIVE_FUNCTION(ArrayIteratorPrototype::next)
{
auto this_value = vm.this_value(global_object);
if (!this_value.is_object() || !this_value.as_object().is_array_iterator_object()) {
if (!this_value.is_object() || !is<ArrayIterator>(this_value.as_object())) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "Array Iterator");
return {};
}

View file

@ -48,7 +48,6 @@ public:
private:
virtual void visit_edges(Visitor&) override;
virtual bool is_bigint_object() const override { return true; }
BigInt& m_bigint;
};

View file

@ -58,7 +58,7 @@ static BigIntObject* bigint_object_from(VM& vm, GlobalObject& global_object)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_bigint_object()) {
if (!is<BigIntObject>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "BigInt");
return nullptr;
}

View file

@ -44,7 +44,6 @@ public:
}
private:
virtual bool is_boolean_object() const override { return true; }
bool m_value { false };
};
}

View file

@ -50,30 +50,28 @@ BooleanPrototype::~BooleanPrototype()
JS_DEFINE_NATIVE_FUNCTION(BooleanPrototype::to_string)
{
auto this_object = vm.this_value(global_object);
if (this_object.is_boolean()) {
return js_string(vm, this_object.as_bool() ? "true" : "false");
}
if (!this_object.is_object() || !this_object.as_object().is_boolean_object()) {
auto this_value = vm.this_value(global_object);
if (this_value.is_boolean())
return js_string(vm, this_value.as_bool() ? "true" : "false");
if (!this_value.is_object() || !is<BooleanObject>(this_value.as_object())) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Boolean");
return {};
}
bool bool_value = static_cast<BooleanObject&>(this_object.as_object()).value_of().as_bool();
bool bool_value = static_cast<const BooleanObject&>(this_value.as_object()).value_of().as_bool();
return js_string(vm, bool_value ? "true" : "false");
}
JS_DEFINE_NATIVE_FUNCTION(BooleanPrototype::value_of)
{
auto this_object = vm.this_value(global_object);
if (this_object.is_boolean()) {
return this_object;
}
if (!this_object.is_object() || !this_object.as_object().is_boolean_object()) {
auto this_value = vm.this_value(global_object);
if (this_value.is_boolean())
return this_value;
if (!this_value.is_object() || !is<BooleanObject>(this_value.as_object())) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Boolean");
return {};
}
return static_cast<BooleanObject&>(this_object.as_object()).value_of();
return static_cast<const BooleanObject&>(this_value.as_object()).value_of();
}
}

View file

@ -59,8 +59,6 @@ public:
virtual bool is_strict_mode() const override { return m_target_function->is_strict_mode(); }
private:
virtual bool is_bound_function() const override { return true; }
Function* m_target_function = nullptr;
Object* m_constructor_prototype = nullptr;
FlyString m_name;

View file

@ -30,6 +30,7 @@
#include <AK/Forward.h>
#include <AK/Noncopyable.h>
#include <AK/String.h>
#include <AK/TypeCasts.h>
#include <LibJS/Forward.h>
namespace JS {

View file

@ -85,7 +85,6 @@ public:
private:
tm to_utc_tm() const;
virtual bool is_date() const final { return true; }
Core::DateTime m_datetime;
u16 m_milliseconds;

View file

@ -40,7 +40,7 @@ static Date* typed_this(VM& vm, GlobalObject& global_object)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_date()) {
if (!is<Date>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Date");
return nullptr;
}

View file

@ -46,8 +46,6 @@ public:
void set_name(const FlyString& name) { m_name = name; }
private:
virtual bool is_error() const final { return true; }
FlyString m_name;
String m_message;
};

View file

@ -58,7 +58,7 @@ JS_DEFINE_NATIVE_GETTER(ErrorPrototype::name_getter)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_error()) {
if (!is<Error>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "Error");
return {};
}
@ -70,7 +70,7 @@ JS_DEFINE_NATIVE_SETTER(ErrorPrototype::name_setter)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return;
if (!this_object->is_error()) {
if (!is<Error>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "Error");
return;
}
@ -85,7 +85,7 @@ JS_DEFINE_NATIVE_GETTER(ErrorPrototype::message_getter)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return {};
if (!this_object->is_error()) {
if (!is<Error>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotAn, "Error");
return {};
}

View file

@ -50,7 +50,7 @@ Function::~Function()
BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments)
{
auto& vm = this->vm();
Function& target_function = is_bound_function() ? static_cast<BoundFunction&>(*this).target_function() : *this;
Function& target_function = is<BoundFunction>(*this) ? static_cast<BoundFunction&>(*this).target_function() : *this;
auto bound_this_object = [&vm, bound_this_value, this]() -> Value {
if (!m_bound_this.is_empty())

View file

@ -34,6 +34,7 @@
#include <LibJS/Runtime/FunctionPrototype.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/MarkedValueList.h>
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/ScriptFunction.h>
namespace JS {
@ -148,7 +149,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::to_string)
String function_parameters = "";
String function_body;
if (this_object->is_native_function() || this_object->is_bound_function()) {
if (is<NativeFunction>(this_object) || is<BoundFunction>(this_object)) {
function_body = String::formatted(" [{}]", this_object->class_name());
} else {
StringBuilder parameters_builder;

View file

@ -76,8 +76,6 @@ protected:
void add_constructor(const FlyString& property_name, ConstructorType*&, Object* prototype);
private:
virtual bool is_global_object() const final { return true; }
JS_DECLARE_NATIVE_FUNCTION(gc);
JS_DECLARE_NATIVE_FUNCTION(is_nan);
JS_DECLARE_NATIVE_FUNCTION(is_finite);

View file

@ -30,10 +30,14 @@
#include <AK/JsonParser.h>
#include <AK/StringBuilder.h>
#include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/BigIntObject.h>
#include <LibJS/Runtime/BooleanObject.h>
#include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/JSONObject.h>
#include <LibJS/Runtime/NumberObject.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/StringObject.h>
namespace JS {
@ -81,7 +85,7 @@ String JSONObject::stringify_impl(GlobalObject& global_object, Value value, Valu
return {};
} else if (replacer_value.is_object()) {
auto& value_object = replacer_value.as_object();
if (value_object.is_string_object() || value_object.is_number_object()) {
if (is<StringObject>(value_object) || is<NumberObject>(value_object)) {
item = value_object.value_of().to_string(global_object);
if (vm.exception())
return {};
@ -97,7 +101,7 @@ String JSONObject::stringify_impl(GlobalObject& global_object, Value value, Valu
if (space.is_object()) {
auto& space_obj = space.as_object();
if (space_obj.is_string_object() || space_obj.is_number_object())
if (is<StringObject>(space_obj) || is<NumberObject>(space_obj))
space = space_obj.value_of();
}
@ -172,7 +176,7 @@ String JSONObject::serialize_json_property(GlobalObject& global_object, Stringif
if (value.is_object()) {
auto& value_object = value.as_object();
if (value_object.is_number_object() || value_object.is_boolean_object() || value_object.is_string_object() || value_object.is_bigint_object())
if (is<NumberObject>(value_object) || is<BooleanObject>(value_object) || is<StringObject>(value_object) || is<BigIntObject>(value_object))
value = value_object.value_of();
}

View file

@ -85,7 +85,6 @@ public:
EnvironmentRecordType type() const { return m_environment_record_type; }
private:
virtual bool is_lexical_environment() const final { return true; }
virtual void visit_edges(Visitor&) override;
EnvironmentRecordType m_environment_record_type : 8 { EnvironmentRecordType::Declarative };

View file

@ -54,7 +54,6 @@ protected:
explicit NativeFunction(Object& prototype);
private:
virtual bool is_native_function() const override { return true; }
virtual LexicalEnvironment* create_environment() override final;
FlyString m_name;

View file

@ -39,7 +39,6 @@ public:
NumberObject(double, Object& prototype);
virtual ~NumberObject() override;
virtual bool is_number_object() const override { return true; }
virtual Value value_of() const override { return Value(m_value); }
double number() const { return m_value; }

View file

@ -66,7 +66,7 @@ JS_DEFINE_NATIVE_FUNCTION(NumberPrototype::to_string)
auto this_value = vm.this_value(global_object);
if (this_value.is_number()) {
number_value = this_value;
} else if (this_value.is_object() && this_value.as_object().is_number_object()) {
} else if (this_value.is_object() && is<NumberObject>(this_value.as_object())) {
number_value = static_cast<NumberObject&>(this_value.as_object()).value_of();
} else {
vm.throw_exception<TypeError>(global_object, ErrorType::NumberIncompatibleThis, "toString");

View file

@ -191,7 +191,7 @@ Value Object::get_own_properties(const Object& this_object, PropertyKind kind, b
auto* properties_array = Array::create(global_object());
// FIXME: Support generic iterables
if (this_object.is_string_object()) {
if (is<StringObject>(this_object)) {
auto str = static_cast<const StringObject&>(this_object).primitive_string().string();
for (size_t i = 0; i < str.length(); ++i) {
@ -662,7 +662,7 @@ Value Object::get_by_index(u32 property_index) const
{
const Object* object = this;
while (object) {
if (is_string_object()) {
if (is<StringObject>(*this)) {
auto& string = static_cast<const StringObject*>(this)->primitive_string().string();
if (property_index < string.length())
return js_string(heap(), string.substring(property_index, 1));
@ -841,7 +841,7 @@ bool Object::has_own_property(const PropertyName& property_name) const
ASSERT(property_name.is_valid());
auto has_indexed_property = [&](u32 index) -> bool {
if (is_string_object())
if (is<StringObject>(*this))
return index < static_cast<const StringObject*>(this)->primitive_string().string().length();
return m_indexed_properties.has_index(index);
};

View file

@ -110,25 +110,8 @@ public:
virtual Value delete_property(const PropertyName&);
virtual bool is_array() const { return false; }
virtual bool is_date() const { return false; }
virtual bool is_error() const { return false; }
virtual bool is_function() const { return false; }
virtual bool is_native_function() const { return false; }
virtual bool is_script_function() const { return false; }
virtual bool is_bound_function() const { return false; }
virtual bool is_proxy_object() const { return false; }
virtual bool is_regexp_object() const { return false; }
virtual bool is_boolean_object() const { return false; }
virtual bool is_string_object() const { return false; }
virtual bool is_number_object() const { return false; }
virtual bool is_symbol_object() const { return false; }
virtual bool is_bigint_object() const { return false; }
virtual bool is_string_iterator_object() const { return false; }
virtual bool is_array_iterator_object() const { return false; }
virtual bool is_lexical_environment() const { return false; }
virtual bool is_global_object() const { return false; }
virtual bool is_typed_array() const { return false; }
virtual bool is_array_buffer() const { return false; }
virtual bool is_node_wrapper() const { return false; }
virtual const char* class_name() const override { return "Object"; }

View file

@ -30,6 +30,7 @@
#include <LibJS/Runtime/Error.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/ObjectConstructor.h>
#include <LibJS/Runtime/ProxyObject.h>
#include <LibJS/Runtime/Shape.h>
namespace JS {
@ -182,7 +183,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_)
auto& descriptor = vm.argument(2).as_object();
if (!object.define_property(property_key, descriptor)) {
if (!vm.exception()) {
if (object.is_proxy_object()) {
if (AK::is<ProxyObject>(object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::ObjectDefinePropertyReturnedFalse);
} else {
vm.throw_exception<TypeError>(global_object, ErrorType::NonExtensibleDefine, property_key.to_display_string());

View file

@ -27,8 +27,13 @@
#include <AK/Function.h>
#include <AK/String.h>
#include <LibJS/Heap/Heap.h>
#include <LibJS/Runtime/BooleanObject.h>
#include <LibJS/Runtime/Date.h>
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/NumberObject.h>
#include <LibJS/Runtime/ObjectPrototype.h>
#include <LibJS/Runtime/RegExpObject.h>
#include <LibJS/Runtime/StringObject.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
@ -90,17 +95,17 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
tag = "Array";
} else if (this_object->is_function()) {
tag = "Function";
} else if (this_object->is_error()) {
} else if (is<Error>(this_object)) {
tag = "Error";
} else if (this_object->is_boolean_object()) {
} else if (is<BooleanObject>(this_object)) {
tag = "Boolean";
} else if (this_object->is_number_object()) {
} else if (is<NumberObject>(this_object)) {
tag = "Number";
} else if (this_object->is_string_object()) {
} else if (is<StringObject>(this_object)) {
tag = "String";
} else if (this_object->is_date()) {
} else if (is<Date>(this_object)) {
tag = "Date";
} else if (this_object->is_regexp_object()) {
} else if (is<RegExpObject>(this_object)) {
tag = "RegExp";
} else {
tag = "Object";

View file

@ -63,7 +63,6 @@ public:
private:
virtual void visit_edges(Visitor&) override;
virtual bool is_proxy_object() const override { return true; }
virtual bool is_function() const override { return m_target.is_function(); }
virtual bool is_array() const override { return m_target.is_array(); };

View file

@ -132,7 +132,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::construct)
if (vm.argument_count() > 2) {
auto new_target_value = vm.argument(2);
if (!new_target_value.is_function()
|| (new_target_value.as_object().is_native_function() && !static_cast<NativeFunction&>(new_target_value.as_object()).has_constructor())) {
|| (is<NativeFunction>(new_target_value.as_object()) && !static_cast<NativeFunction&>(new_target_value.as_object()).has_constructor())) {
vm.throw_exception<TypeError>(global_object, ErrorType::ReflectBadNewTarget);
return {};
}

View file

@ -135,7 +135,7 @@ static RegExpObject* regexp_object_from(VM& vm, GlobalObject& global_object)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_regexp_object()) {
if (!is<RegExpObject>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "RegExp");
return nullptr;
}

View file

@ -54,8 +54,6 @@ public:
const Regex<ECMA262>& regex() const { return m_regex; }
private:
virtual bool is_regexp_object() const override { return true; }
JS_DECLARE_NATIVE_GETTER(last_index);
JS_DECLARE_NATIVE_SETTER(set_last_index);

View file

@ -78,7 +78,7 @@ static RegExpObject* regexp_object_from(VM& vm, GlobalObject& global_object)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_regexp_object()) {
if (!is<RegExpObject>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "RegExp");
return nullptr;
}

View file

@ -106,7 +106,7 @@ LexicalEnvironment* ScriptFunction::create_environment()
environment->set_home_object(home_object());
environment->set_current_function(*this);
if (m_is_arrow_function) {
if (m_parent_scope->is_lexical_environment())
if (is<LexicalEnvironment>(m_parent_scope))
environment->set_new_target(static_cast<LexicalEnvironment*>(m_parent_scope)->new_target());
}
return environment;

View file

@ -56,7 +56,6 @@ protected:
virtual bool is_strict_mode() const final { return m_is_strict; }
private:
virtual bool is_script_function() const override { return true; }
virtual LexicalEnvironment* create_environment() override;
virtual void visit_edges(Visitor&) override;

View file

@ -46,8 +46,6 @@ public:
private:
friend class StringIteratorPrototype;
virtual bool is_string_iterator_object() const override { return true; }
String m_string;
Utf8CodepointIterator m_iterator;
bool m_done { false };

View file

@ -53,7 +53,7 @@ StringIteratorPrototype::~StringIteratorPrototype()
JS_DEFINE_NATIVE_FUNCTION(StringIteratorPrototype::next)
{
auto this_value = vm.this_value(global_object);
if (!this_value.is_object() || !this_value.as_object().is_string_iterator_object()) {
if (!this_value.is_object() || !is<StringIterator>(this_value.as_object())) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "String Iterator");
return {};
}

View file

@ -47,7 +47,6 @@ public:
private:
virtual void visit_edges(Visitor&) override;
virtual bool is_string_object() const override { return true; }
PrimitiveString& m_string;
};

View file

@ -44,7 +44,7 @@ static StringObject* typed_this(VM& vm, GlobalObject& global_object)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_string_object()) {
if (!is<StringObject>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "String");
return nullptr;
}

View file

@ -53,7 +53,6 @@ public:
private:
virtual void visit_edges(Visitor&) override;
virtual bool is_symbol_object() const override { return true; }
Symbol& m_symbol;
};

View file

@ -63,7 +63,7 @@ static SymbolObject* typed_this(VM& vm, GlobalObject& global_object)
auto* this_object = vm.this_value(global_object).to_object(global_object);
if (!this_object)
return nullptr;
if (!this_object->is_symbol_object()) {
if (!is<SymbolObject>(this_object)) {
vm.throw_exception<TypeError>(global_object, ErrorType::NotA, "Symbol");
return nullptr;
}

View file

@ -132,7 +132,7 @@ void TypedArrayBase::visit_edges(Visitor& visitor)
if (first_argument.as_object().is_typed_array()) { \
/* FIXME: Initialize from TypedArray */ \
TODO(); \
} else if (first_argument.as_object().is_array_buffer()) { \
} else if (is<ArrayBuffer>(first_argument.as_object())) { \
auto& array_buffer = static_cast<ArrayBuffer&>(first_argument.as_object()); \
initialize_typed_array_from_array_buffer(global_object(), *typed_array, array_buffer, vm.argument(1), vm.argument(2)); \
if (vm.exception()) \

View file

@ -198,7 +198,7 @@ Reference VM::get_reference(const FlyString& name)
{
if (m_call_stack.size()) {
for (auto* scope = current_scope(); scope; scope = scope->parent()) {
if (scope->is_global_object())
if (is<GlobalObject>(scope))
break;
auto possible_match = scope->get_from_scope(name);
if (possible_match.has_value())
@ -256,7 +256,7 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
// If we are constructing an instance of a derived class,
// set the prototype on objects created by constructors that return an object (i.e. NativeFunction subclasses).
if (function.constructor_kind() == Function::ConstructorKind::Base && new_target.constructor_kind() == Function::ConstructorKind::Derived && result.is_object()) {
ASSERT(current_scope()->is_lexical_environment());
ASSERT(is<LexicalEnvironment>(current_scope()));
static_cast<LexicalEnvironment*>(current_scope())->replace_this_binding(result);
auto prototype = new_target.get(names.prototype);
if (exception())
@ -280,7 +280,7 @@ Value VM::construct(Function& function, Function& new_target, Optional<MarkedVal
void VM::throw_exception(Exception* exception)
{
if (should_log_exceptions() && exception->value().is_object() && exception->value().as_object().is_error()) {
if (should_log_exceptions() && exception->value().is_object() && is<Error>(exception->value().as_object())) {
auto& error = static_cast<Error&>(exception->value().as_object());
dbgln("Throwing JavaScript Error: {}, {}", error.name(), error.message());
@ -324,7 +324,7 @@ const ScopeObject* VM::find_this_scope() const
Value VM::get_new_target() const
{
ASSERT(find_this_scope()->is_lexical_environment());
ASSERT(is<LexicalEnvironment>(find_this_scope()));
return static_cast<const LexicalEnvironment*>(find_this_scope())->new_target();
}

View file

@ -44,6 +44,7 @@
#include <LibJS/Runtime/NumberObject.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/PrimitiveString.h>
#include <LibJS/Runtime/RegExpObject.h>
#include <LibJS/Runtime/StringObject.h>
#include <LibJS/Runtime/Symbol.h>
#include <LibJS/Runtime/SymbolObject.h>
@ -243,7 +244,7 @@ bool Value::is_regexp(GlobalObject& global_object) const
if (!matcher.is_empty() && !matcher.is_undefined())
return matcher.to_boolean();
return as_object().is_regexp_object();
return is<RegExpObject>(as_object());
}
String Value::to_string_without_side_effects() const
@ -926,8 +927,8 @@ Value ordinary_has_instance(GlobalObject& global_object, Value lhs, Value rhs)
return Value(false);
auto& rhs_function = rhs.as_function();
if (rhs_function.is_bound_function()) {
auto& bound_target = static_cast<BoundFunction&>(rhs_function);
if (is<BoundFunction>(rhs_function)) {
auto& bound_target = static_cast<const BoundFunction&>(rhs_function);
return instance_of(global_object, lhs, Value(&bound_target.target_function()));
}

View file

@ -230,9 +230,9 @@ static void print_object(JS::Object& object, HashTable<JS::Object*>& seen_object
static void print_function(const JS::Object& object, HashTable<JS::Object*>&)
{
print_type(object.class_name());
if (object.is_script_function())
if (is<JS::ScriptFunction>(object))
out(" {}", static_cast<const JS::ScriptFunction&>(object).name());
if (object.is_native_function())
else if (is<JS::NativeFunction>(object))
out(" {}", static_cast<const JS::NativeFunction&>(object).name());
}
@ -357,23 +357,23 @@ static void print_value(JS::Value value, HashTable<JS::Object*>& seen_objects)
auto& object = value.as_object();
if (object.is_function())
return print_function(object, seen_objects);
if (object.is_date())
if (is<JS::Date>(object))
return print_date(object, seen_objects);
if (object.is_error())
if (is<JS::Error>(object))
return print_error(object, seen_objects);
if (object.is_regexp_object())
if (is<JS::RegExpObject>(object))
return print_regexp_object(object, seen_objects);
if (object.is_proxy_object())
if (is<JS::ProxyObject>(object))
return print_proxy_object(object, seen_objects);
if (object.is_array_buffer())
if (is<JS::ArrayBuffer>(object))
return print_array_buffer(object, seen_objects);
if (object.is_typed_array())
return print_typed_array(object, seen_objects);
if (object.is_string_object())
if (is<JS::StringObject>(object))
return print_primitive_wrapper_object("String", object, seen_objects);
if (object.is_number_object())
if (is<JS::NumberObject>(object))
return print_primitive_wrapper_object("Number", object, seen_objects);
if (object.is_boolean_object())
if (is<JS::BooleanObject>(object))
return print_primitive_wrapper_object("Boolean", object, seen_objects);
return print_object(object, seen_objects);
}