1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 17:37:35 +00:00

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. :^)
This commit is contained in:
Andreas Kling 2020-04-01 22:18:47 +02:00
parent b995a499d3
commit 1549c5c48b
8 changed files with 54 additions and 54 deletions

View file

@ -90,16 +90,16 @@ Value CallExpression::execute(Interpreter& interpreter) const
if (is_new_expression()) { if (is_new_expression()) {
if (!callee.is_object() if (!callee.is_object()
|| !callee.as_object()->is_function() || !callee.as_object().is_function()
|| (callee.as_object()->is_native_function() || (callee.as_object().is_native_function()
&& !static_cast<NativeFunction*>(callee.as_object())->has_constructor())) && !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())); 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())); 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(); auto& call_frame = interpreter.push_call_frame();
for (size_t i = 0; i < m_arguments.size(); ++i) { for (size_t i = 0; i < m_arguments.size(); ++i) {
@ -115,14 +115,14 @@ Value CallExpression::execute(Interpreter& interpreter) const
Value result; Value result;
if (is_new_expression()) { if (is_new_expression()) {
new_object = interpreter.heap().allocate<Object>(); new_object = interpreter.heap().allocate<Object>();
auto prototype = function->get("prototype"); auto prototype = function.get("prototype");
if (prototype.has_value() && prototype.value().is_object()) 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; call_frame.this_value = new_object;
result = function->construct(interpreter); result = function.construct(interpreter);
} else { } else {
call_frame.this_value = this_value; call_frame.this_value = this_value;
result = function->call(interpreter); result = function.call(interpreter);
} }
interpreter.pop_call_frame(); interpreter.pop_call_frame();

View file

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

View file

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

View file

@ -92,7 +92,7 @@ Value ObjectConstructor::set_prototype_of(Interpreter& interpreter)
auto* object = interpreter.call_frame().arguments[0].to_object(interpreter.heap()); auto* object = interpreter.call_frame().arguments[0].to_object(interpreter.heap());
if (interpreter.exception()) if (interpreter.exception())
return {}; 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 {}; return {};
} }

View file

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

View file

@ -109,16 +109,16 @@ public:
return m_value.as_bool; return m_value.as_bool;
} }
Object* as_object() Object& as_object()
{ {
ASSERT(type() == Type::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); ASSERT(type() == Type::Object);
return m_value.as_object; return *m_value.as_object;
} }
PrimitiveString* as_string() PrimitiveString* as_string()

View file

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

View file

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