mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
LibJS: Stop using Optional<Value> in favor of Value's empty state
JS::Value already has the empty state ({} or Value() gives you one.) Use this instead of wrapping Value in Optional in some places. I've also added Value::value_or(Value) so you can easily provide a fallback value when one is not present.
This commit is contained in:
parent
5adf4901df
commit
35aea2e454
Notes:
sideshowbarker
2024-07-19 07:17:54 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/35aea2e454e
14 changed files with 60 additions and 48 deletions
|
@ -136,8 +136,8 @@ Value CallExpression::execute(Interpreter& interpreter) const
|
|||
if (is_new_expression()) {
|
||||
new_object = Object::create_empty(interpreter, interpreter.global_object());
|
||||
auto prototype = function.get("prototype");
|
||||
if (prototype.has_value() && prototype.value().is_object())
|
||||
new_object->set_prototype(&prototype.value().as_object());
|
||||
if (prototype.is_object())
|
||||
new_object->set_prototype(&prototype.as_object());
|
||||
call_frame.this_value = new_object;
|
||||
result = function.construct(interpreter);
|
||||
} else {
|
||||
|
@ -704,10 +704,10 @@ void ForStatement::dump(int indent) const
|
|||
|
||||
Value Identifier::execute(Interpreter& interpreter) const
|
||||
{
|
||||
auto variable = interpreter.get_variable(string());
|
||||
if (!variable.has_value())
|
||||
auto value = interpreter.get_variable(string());
|
||||
if (value.is_empty())
|
||||
return interpreter.throw_exception<ReferenceError>(String::format("'%s' not known", string().characters()));
|
||||
return variable.value();
|
||||
return value;
|
||||
}
|
||||
|
||||
void Identifier::dump(int indent) const
|
||||
|
@ -1022,11 +1022,7 @@ Value MemberExpression::execute(Interpreter& interpreter) const
|
|||
auto* object_result = object_value.to_object(interpreter.heap());
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
auto result = object_result->get(computed_property_name(interpreter));
|
||||
if (result.has_value()) {
|
||||
ASSERT(!result.value().is_empty());
|
||||
}
|
||||
return result.value_or(js_undefined());
|
||||
return object_result->get(computed_property_name(interpreter)).value_or(js_undefined());
|
||||
}
|
||||
|
||||
Value StringLiteral::execute(Interpreter& interpreter) const
|
||||
|
|
|
@ -151,7 +151,7 @@ void Interpreter::set_variable(const FlyString& name, Value value, bool first_as
|
|||
global_object().put(move(name), move(value));
|
||||
}
|
||||
|
||||
Optional<Value> Interpreter::get_variable(const FlyString& name)
|
||||
Value Interpreter::get_variable(const FlyString& name)
|
||||
{
|
||||
if (m_call_stack.size()) {
|
||||
for (auto* environment = current_environment(); environment; environment = environment->parent()) {
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
bool should_unwind_until(ScopeType type) const { return m_unwind_until == type; }
|
||||
bool should_unwind() const { return m_unwind_until != ScopeType::None; }
|
||||
|
||||
Optional<Value> get_variable(const FlyString& name);
|
||||
Value get_variable(const FlyString& name);
|
||||
void set_variable(const FlyString& name, Value, bool first_assignment = false);
|
||||
|
||||
void gather_roots(Badge<Heap>, HashTable<Cell*>&);
|
||||
|
|
|
@ -88,13 +88,13 @@ Value ErrorPrototype::to_string(Interpreter& interpreter)
|
|||
|
||||
String name = "Error";
|
||||
auto object_name_property = this_object.get("name");
|
||||
if (object_name_property.has_value() && !object_name_property.value().is_undefined())
|
||||
name = object_name_property.value().to_string();
|
||||
if (!object_name_property.is_empty() && !object_name_property.is_undefined())
|
||||
name = object_name_property.to_string();
|
||||
|
||||
String message = "";
|
||||
auto object_message_property = this_object.get("message");
|
||||
if (object_message_property.has_value() && !object_message_property.value().is_undefined())
|
||||
message = object_message_property.value().to_string();
|
||||
if (!object_message_property.is_empty() && !object_message_property.is_undefined())
|
||||
message = object_message_property.to_string();
|
||||
|
||||
if (name.length() == 0)
|
||||
return js_string(interpreter, message);
|
||||
|
|
|
@ -68,8 +68,8 @@ BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments)
|
|||
if (interpreter().exception()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (length_property.has_value() && length_property.value().is_number()) {
|
||||
computed_length = max(0, length_property.value().to_i32() - static_cast<i32>(arguments.size()));
|
||||
if (length_property.is_number()) {
|
||||
computed_length = max(0, length_property.to_i32() - static_cast<i32>(arguments.size()));
|
||||
}
|
||||
|
||||
Object* constructor_prototype = nullptr;
|
||||
|
@ -77,8 +77,8 @@ BoundFunction* Function::bind(Value bound_this_value, Vector<Value> arguments)
|
|||
if (interpreter().exception()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (prototype_property.has_value() && prototype_property.value().is_object()) {
|
||||
constructor_prototype = &prototype_property.value().as_object();
|
||||
if (prototype_property.is_object()) {
|
||||
constructor_prototype = &prototype_property.as_object();
|
||||
}
|
||||
|
||||
auto all_bound_arguments = bound_arguments();
|
||||
|
|
|
@ -72,11 +72,15 @@ Value FunctionPrototype::apply(Interpreter& interpreter)
|
|||
return interpreter.throw_exception<TypeError>("argument array must be an object");
|
||||
size_t length = 0;
|
||||
auto length_property = arg_array.as_object().get("length");
|
||||
if (length_property.has_value())
|
||||
length = length_property.value().to_number().to_i32();
|
||||
if (!length_property.is_empty())
|
||||
length = length_property.to_number().to_i32();
|
||||
MarkedValueList arguments(interpreter.heap());
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
arguments.append(arg_array.as_object().get(String::number(i)).value_or(js_undefined()));
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
auto element = arg_array.as_object().get(String::number(i));
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
arguments.append(element.value_or(js_undefined()));
|
||||
}
|
||||
return interpreter.call(function, this_arg, move(arguments));
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ bool Object::has_prototype(const Object* prototype) const
|
|||
return false;
|
||||
}
|
||||
|
||||
Optional<Value> Object::get_own_property(const Object& this_object, const FlyString& property_name) const
|
||||
Value Object::get_own_property(const Object& this_object, const FlyString& property_name) const
|
||||
{
|
||||
auto metadata = shape().lookup(property_name);
|
||||
if (!metadata.has_value())
|
||||
|
@ -154,7 +154,7 @@ void Object::put_own_property(Object& this_object, const FlyString& property_nam
|
|||
}
|
||||
}
|
||||
|
||||
Optional<Value> Object::get_by_index(i32 property_index) const
|
||||
Value Object::get_by_index(i32 property_index) const
|
||||
{
|
||||
if (property_index < 0)
|
||||
return get(String::number(property_index));
|
||||
|
@ -172,7 +172,7 @@ Optional<Value> Object::get_by_index(i32 property_index) const
|
|||
return {};
|
||||
}
|
||||
|
||||
Optional<Value> Object::get(const FlyString& property_name) const
|
||||
Value Object::get(const FlyString& property_name) const
|
||||
{
|
||||
bool ok;
|
||||
i32 property_index = property_name.to_int(ok);
|
||||
|
@ -182,14 +182,14 @@ Optional<Value> Object::get(const FlyString& property_name) const
|
|||
const Object* object = this;
|
||||
while (object) {
|
||||
auto value = object->get_own_property(*this, property_name);
|
||||
if (value.has_value())
|
||||
return value.value();
|
||||
if (!value.is_empty())
|
||||
return value;
|
||||
object = object->prototype();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Optional<Value> Object::get(PropertyName property_name) const
|
||||
Value Object::get(PropertyName property_name) const
|
||||
{
|
||||
if (property_name.is_number())
|
||||
return get_by_index(property_name.as_number());
|
||||
|
@ -308,10 +308,10 @@ Value Object::to_primitive(PreferredType preferred_type) const
|
|||
Value Object::to_string() const
|
||||
{
|
||||
auto to_string_property = get("toString");
|
||||
if (to_string_property.has_value()
|
||||
&& to_string_property.value().is_object()
|
||||
&& to_string_property.value().as_object().is_function()) {
|
||||
auto& to_string_function = static_cast<Function&>(to_string_property.value().as_object());
|
||||
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());
|
||||
return const_cast<Object*>(this)->interpreter().call(&to_string_function, const_cast<Object*>(this));
|
||||
}
|
||||
return js_string(heap(), String::format("[object %s]", class_name()));
|
||||
|
|
|
@ -46,15 +46,15 @@ public:
|
|||
Shape& shape() { return *m_shape; }
|
||||
const Shape& shape() const { return *m_shape; }
|
||||
|
||||
virtual Optional<Value> get_by_index(i32 property_index) const;
|
||||
Optional<Value> get(const FlyString& property_name) const;
|
||||
Optional<Value> get(PropertyName) const;
|
||||
virtual Value get_by_index(i32 property_index) const;
|
||||
Value get(const FlyString& property_name) const;
|
||||
Value get(PropertyName) const;
|
||||
|
||||
virtual void put_by_index(i32 property_index, Value);
|
||||
void put(const FlyString& property_name, Value);
|
||||
void put(PropertyName, Value);
|
||||
|
||||
Optional<Value> get_own_property(const Object& this_object, const FlyString& property_name) const;
|
||||
Value get_own_property(const Object& this_object, const FlyString& property_name) const;
|
||||
|
||||
enum class PutOwnPropertyMode {
|
||||
Put,
|
||||
|
|
|
@ -110,11 +110,16 @@ Value ObjectConstructor::get_own_property_descriptor(Interpreter& interpreter)
|
|||
auto metadata = object.shape().lookup(interpreter.argument(1).to_string());
|
||||
if (!metadata.has_value())
|
||||
return js_undefined();
|
||||
|
||||
auto value = object.get(interpreter.argument(1).to_string()).value_or(js_undefined());
|
||||
if (interpreter.exception())
|
||||
return {};
|
||||
|
||||
auto* descriptor = Object::create_empty(interpreter, interpreter.global_object());
|
||||
descriptor->put("configurable", Value(!!(metadata.value().attributes & Attribute::Configurable)));
|
||||
descriptor->put("enumerable", Value(!!(metadata.value().attributes & Attribute::Enumerable)));
|
||||
descriptor->put("writable", Value(!!(metadata.value().attributes & Attribute::Writable)));
|
||||
descriptor->put("value", object.get(interpreter.argument(1).to_string()).value_or(js_undefined()));
|
||||
descriptor->put("value", value);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
@ -129,7 +134,7 @@ Value ObjectConstructor::define_property(Interpreter& interpreter)
|
|||
auto& object = interpreter.argument(0).as_object();
|
||||
auto& descriptor = interpreter.argument(2).as_object();
|
||||
|
||||
Value value = descriptor.get("value").value_or(Value());
|
||||
auto value = descriptor.get("value");
|
||||
u8 configurable = descriptor.get("configurable").value_or(Value(false)).to_boolean() * Attribute::Configurable;
|
||||
u8 enumerable = descriptor.get("enumerable").value_or(Value(false)).to_boolean() * Attribute::Enumerable;
|
||||
u8 writable = descriptor.get("writable").value_or(Value(false)).to_boolean() * Attribute::Writable;
|
||||
|
|
|
@ -72,7 +72,7 @@ void Uint8ClampedArray::put_by_index(i32 property_index, Value value)
|
|||
m_data[property_index] = clamp(value.to_i32(), 0, 255);
|
||||
}
|
||||
|
||||
Optional<Value> Uint8ClampedArray::get_by_index(i32 property_index) const
|
||||
Value Uint8ClampedArray::get_by_index(i32 property_index) const
|
||||
{
|
||||
ASSERT(property_index >= 0);
|
||||
ASSERT(property_index < m_length);
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
i32 length() const { return m_length; }
|
||||
|
||||
virtual void put_by_index(i32 property_index, Value value) override;
|
||||
virtual Optional<Value> get_by_index(i32 property_index) const override;
|
||||
virtual Value get_by_index(i32 property_index) const override;
|
||||
|
||||
u8* data() { return m_data; }
|
||||
const u8* data() const { return m_data; }
|
||||
|
|
|
@ -387,7 +387,7 @@ Value in(Interpreter& interpreter, Value lhs, Value rhs)
|
|||
if (!rhs.is_object())
|
||||
return interpreter.throw_exception<TypeError>("'in' operator must be used on object");
|
||||
|
||||
return Value(rhs.as_object().get(lhs.to_string()).has_value());
|
||||
return Value(!rhs.as_object().get(lhs.to_string()).is_empty());
|
||||
}
|
||||
|
||||
Value instance_of(Interpreter&, Value lhs, Value rhs)
|
||||
|
@ -396,10 +396,10 @@ Value instance_of(Interpreter&, Value lhs, Value rhs)
|
|||
return Value(false);
|
||||
|
||||
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.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.as_object()));
|
||||
}
|
||||
|
||||
const LogStream& operator<<(const LogStream& stream, const Value& value)
|
||||
|
|
|
@ -164,6 +164,13 @@ public:
|
|||
|
||||
Object* to_object(Heap&) const;
|
||||
|
||||
Value value_or(Value fallback) const
|
||||
{
|
||||
if (is_empty())
|
||||
return fallback;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Type m_type { Type::Empty };
|
||||
|
||||
|
|
|
@ -607,13 +607,13 @@ int main(int argc, char** argv)
|
|||
auto property_pattern = parts[1];
|
||||
|
||||
auto maybe_variable = interpreter->get_variable(name);
|
||||
if (!maybe_variable.has_value()) {
|
||||
if (maybe_variable.is_empty()) {
|
||||
maybe_variable = interpreter->global_object().get(name);
|
||||
if (!maybe_variable.has_value())
|
||||
if (maybe_variable.is_empty())
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto& variable = maybe_variable.value();
|
||||
auto variable = maybe_variable;
|
||||
if (!variable.is_object())
|
||||
return {};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue