mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-07 08:39:22 +00:00
LibJS: Remove default constructor of PropertyKey
This constructor was creating an "invalid" `PropertyKey`, but every code path constructing such a `PropertyKey` was either never used or immediately `VERIFY`ing that the `PropertyKey` was valid. The `VERIFY` call has been moved to the `PropertyKey::from_value(...)` call, and the array/object literal spreading code could be refactored to not take a `PropertyKey` but creates dummy values for now. The default constructor for `Reference` has similairly be deleted, because it was never used.
This commit is contained in:
parent
1d8e62926f
commit
27859c17b4
Notes:
github-actions[bot]
2024-11-09 16:56:10 +00:00
Author: https://github.com/yyny
Commit: 27859c17b4
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2120
Reviewed-by: https://github.com/trflynn89
5 changed files with 30 additions and 42 deletions
|
@ -1362,7 +1362,7 @@ inline ThrowCompletionOr<void> put_by_value(VM& vm, Value base, Optional<Depreca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto property_key = kind != Op::PropertyKind::Spread ? TRY(property_key_value.to_property_key(vm)) : PropertyKey {};
|
auto property_key = kind != Op::PropertyKind::Spread ? TRY(property_key_value.to_property_key(vm)) : PropertyKey { 0 };
|
||||||
TRY(put_by_property_key(vm, base, base, value, base_identifier, property_key, kind));
|
TRY(put_by_property_key(vm, base, base, value, base_identifier, property_key, kind));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -2807,7 +2807,7 @@ ThrowCompletionOr<void> PutByValueWithThis::execute_impl(Bytecode::Interpreter&
|
||||||
auto& vm = interpreter.vm();
|
auto& vm = interpreter.vm();
|
||||||
auto value = interpreter.get(m_src);
|
auto value = interpreter.get(m_src);
|
||||||
auto base = interpreter.get(m_base);
|
auto base = interpreter.get(m_base);
|
||||||
auto property_key = m_kind != PropertyKind::Spread ? TRY(interpreter.get(m_property).to_property_key(vm)) : PropertyKey {};
|
auto property_key = m_kind != PropertyKind::Spread ? TRY(interpreter.get(m_property).to_property_key(vm)) : PropertyKey { 0 };
|
||||||
TRY(put_by_property_key(vm, base, interpreter.get(m_this_value), value, {}, property_key, m_kind));
|
TRY(put_by_property_key(vm, base, interpreter.get(m_this_value), value, {}, property_key, m_kind));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1448,18 +1448,13 @@ ThrowCompletionOr<Value> Object::ordinary_to_primitive(Value::PreferredType pref
|
||||||
|
|
||||||
auto& vm = this->vm();
|
auto& vm = this->vm();
|
||||||
|
|
||||||
AK::Array<PropertyKey, 2> method_names;
|
AK::Array<PropertyKey, 2> method_names = (preferred_type == Value::PreferredType::String)
|
||||||
|
// 1. If hint is string, then
|
||||||
// 1. If hint is string, then
|
|
||||||
if (preferred_type == Value::PreferredType::String) {
|
|
||||||
// a. Let methodNames be « "toString", "valueOf" ».
|
// a. Let methodNames be « "toString", "valueOf" ».
|
||||||
method_names = { vm.names.toString, vm.names.valueOf };
|
? AK::Array { vm.names.toString, vm.names.valueOf }
|
||||||
}
|
// 2. Else,
|
||||||
// 2. Else,
|
|
||||||
else {
|
|
||||||
// a. Let methodNames be « "valueOf", "toString" ».
|
// a. Let methodNames be « "valueOf", "toString" ».
|
||||||
method_names = { vm.names.valueOf, vm.names.toString };
|
: AK::Array { vm.names.valueOf, vm.names.toString };
|
||||||
}
|
|
||||||
|
|
||||||
// 3. For each element name of methodNames, do
|
// 3. For each element name of methodNames, do
|
||||||
for (auto& method_name : method_names) {
|
for (auto& method_name : method_names) {
|
||||||
|
|
|
@ -30,8 +30,7 @@ public:
|
||||||
|
|
||||||
static ThrowCompletionOr<PropertyKey> from_value(VM& vm, Value value)
|
static ThrowCompletionOr<PropertyKey> from_value(VM& vm, Value value)
|
||||||
{
|
{
|
||||||
if (value.is_empty())
|
VERIFY(!value.is_empty());
|
||||||
return PropertyKey {};
|
|
||||||
if (value.is_symbol())
|
if (value.is_symbol())
|
||||||
return PropertyKey { value.as_symbol() };
|
return PropertyKey { value.as_symbol() };
|
||||||
if (value.is_integral_number() && value.as_double() >= 0 && value.as_double() < NumericLimits<u32>::max())
|
if (value.is_integral_number() && value.as_double() >= 0 && value.as_double() < NumericLimits<u32>::max())
|
||||||
|
@ -39,7 +38,7 @@ public:
|
||||||
return TRY(value.to_byte_string(vm));
|
return TRY(value.to_byte_string(vm));
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyKey() = default;
|
PropertyKey() = delete;
|
||||||
|
|
||||||
template<Integral T>
|
template<Integral T>
|
||||||
PropertyKey(T index)
|
PropertyKey(T index)
|
||||||
|
|
|
@ -31,7 +31,7 @@ ThrowCompletionOr<void> Reference::put_value(VM& vm, Value value)
|
||||||
auto& global_object = vm.get_global_object();
|
auto& global_object = vm.get_global_object();
|
||||||
|
|
||||||
// c. Perform ? Set(globalObj, V.[[ReferencedName]], W, false).
|
// c. Perform ? Set(globalObj, V.[[ReferencedName]], W, false).
|
||||||
TRY(global_object.set(m_name, value, Object::ShouldThrowExceptions::No));
|
TRY(global_object.set(name(), value, Object::ShouldThrowExceptions::No));
|
||||||
|
|
||||||
// Return unused.
|
// Return unused.
|
||||||
return {};
|
return {};
|
||||||
|
@ -45,15 +45,15 @@ ThrowCompletionOr<void> Reference::put_value(VM& vm, Value value)
|
||||||
// b. If IsPrivateReference(V) is true, then
|
// b. If IsPrivateReference(V) is true, then
|
||||||
if (is_private_reference()) {
|
if (is_private_reference()) {
|
||||||
// i. Return ? PrivateSet(baseObj, V.[[ReferencedName]], W).
|
// i. Return ? PrivateSet(baseObj, V.[[ReferencedName]], W).
|
||||||
return base_obj->private_set(m_private_name, value);
|
return base_obj->private_set(private_name(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// c. Let succeeded be ? baseObj.[[Set]](V.[[ReferencedName]], W, GetThisValue(V)).
|
// c. Let succeeded be ? baseObj.[[Set]](V.[[ReferencedName]], W, GetThisValue(V)).
|
||||||
auto succeeded = TRY(base_obj->internal_set(m_name, value, get_this_value()));
|
auto succeeded = TRY(base_obj->internal_set(name(), value, get_this_value()));
|
||||||
|
|
||||||
// d. If succeeded is false and V.[[Strict]] is true, throw a TypeError exception.
|
// d. If succeeded is false and V.[[Strict]] is true, throw a TypeError exception.
|
||||||
if (!succeeded && m_strict)
|
if (!succeeded && m_strict)
|
||||||
return vm.throw_completion<TypeError>(ErrorType::ReferenceNullishSetProperty, m_name, m_base_value.to_string_without_side_effects());
|
return vm.throw_completion<TypeError>(ErrorType::ReferenceNullishSetProperty, name(), m_base_value.to_string_without_side_effects());
|
||||||
|
|
||||||
// e. Return unused.
|
// e. Return unused.
|
||||||
return {};
|
return {};
|
||||||
|
@ -70,15 +70,15 @@ ThrowCompletionOr<void> Reference::put_value(VM& vm, Value value)
|
||||||
if (m_environment_coordinate.has_value())
|
if (m_environment_coordinate.has_value())
|
||||||
return static_cast<DeclarativeEnvironment*>(m_base_environment)->set_mutable_binding_direct(vm, m_environment_coordinate->index, value, m_strict);
|
return static_cast<DeclarativeEnvironment*>(m_base_environment)->set_mutable_binding_direct(vm, m_environment_coordinate->index, value, m_strict);
|
||||||
else
|
else
|
||||||
return m_base_environment->set_mutable_binding(vm, m_name.as_string(), value, m_strict);
|
return m_base_environment->set_mutable_binding(vm, name().as_string(), value, m_strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
Completion Reference::throw_reference_error(VM& vm) const
|
Completion Reference::throw_reference_error(VM& vm) const
|
||||||
{
|
{
|
||||||
if (!m_name.is_valid())
|
if (is_private_reference())
|
||||||
return vm.throw_completion<ReferenceError>(ErrorType::ReferenceUnresolvable);
|
return vm.throw_completion<ReferenceError>(ErrorType::ReferenceUnresolvable);
|
||||||
else
|
else
|
||||||
return vm.throw_completion<ReferenceError>(ErrorType::UnknownIdentifier, m_name.to_string_or_symbol().to_display_string());
|
return vm.throw_completion<ReferenceError>(ErrorType::UnknownIdentifier, name().to_string_or_symbol().to_display_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.2.4.5 GetValue ( V ), https://tc39.es/ecma262/#sec-getvalue
|
// 6.2.4.5 GetValue ( V ), https://tc39.es/ecma262/#sec-getvalue
|
||||||
|
@ -108,13 +108,13 @@ ThrowCompletionOr<Value> Reference::get_value(VM& vm) const
|
||||||
auto base_obj = TRY(m_base_value.to_object(vm));
|
auto base_obj = TRY(m_base_value.to_object(vm));
|
||||||
|
|
||||||
// i. Return ? PrivateGet(baseObj, V.[[ReferencedName]]).
|
// i. Return ? PrivateGet(baseObj, V.[[ReferencedName]]).
|
||||||
return base_obj->private_get(m_private_name);
|
return base_obj->private_get(private_name());
|
||||||
}
|
}
|
||||||
|
|
||||||
// OPTIMIZATION: For various primitives we can avoid actually creating a new object for them.
|
// OPTIMIZATION: For various primitives we can avoid actually creating a new object for them.
|
||||||
GCPtr<Object> base_obj;
|
GCPtr<Object> base_obj;
|
||||||
if (m_base_value.is_string()) {
|
if (m_base_value.is_string()) {
|
||||||
auto string_value = TRY(m_base_value.as_string().get(vm, m_name));
|
auto string_value = TRY(m_base_value.as_string().get(vm, name()));
|
||||||
if (string_value.has_value())
|
if (string_value.has_value())
|
||||||
return *string_value;
|
return *string_value;
|
||||||
base_obj = realm.intrinsics().string_prototype();
|
base_obj = realm.intrinsics().string_prototype();
|
||||||
|
@ -130,7 +130,7 @@ ThrowCompletionOr<Value> Reference::get_value(VM& vm) const
|
||||||
base_obj = TRY(m_base_value.to_object(vm));
|
base_obj = TRY(m_base_value.to_object(vm));
|
||||||
|
|
||||||
// c. Return ? baseObj.[[Get]](V.[[ReferencedName]], GetThisValue(V)).
|
// c. Return ? baseObj.[[Get]](V.[[ReferencedName]], GetThisValue(V)).
|
||||||
return base_obj->internal_get(m_name, get_this_value());
|
return base_obj->internal_get(name(), get_this_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Else,
|
// 5. Else,
|
||||||
|
@ -143,7 +143,7 @@ ThrowCompletionOr<Value> Reference::get_value(VM& vm) const
|
||||||
// c. Return ? base.GetBindingValue(V.[[ReferencedName]], V.[[Strict]]) (see 9.1).
|
// c. Return ? base.GetBindingValue(V.[[ReferencedName]], V.[[Strict]]) (see 9.1).
|
||||||
if (m_environment_coordinate.has_value())
|
if (m_environment_coordinate.has_value())
|
||||||
return static_cast<DeclarativeEnvironment*>(m_base_environment)->get_binding_value_direct(vm, m_environment_coordinate->index);
|
return static_cast<DeclarativeEnvironment*>(m_base_environment)->get_binding_value_direct(vm, m_environment_coordinate->index);
|
||||||
return m_base_environment->get_binding_value(vm, m_name.as_string(), m_strict);
|
return m_base_environment->get_binding_value(vm, name().as_string(), m_strict);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 13.5.1.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation
|
// 13.5.1.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation
|
||||||
|
@ -178,11 +178,11 @@ ThrowCompletionOr<bool> Reference::delete_(VM& vm)
|
||||||
auto base_obj = TRY(m_base_value.to_object(vm));
|
auto base_obj = TRY(m_base_value.to_object(vm));
|
||||||
|
|
||||||
// d. Let deleteStatus be ? baseObj.[[Delete]](ref.[[ReferencedName]]).
|
// d. Let deleteStatus be ? baseObj.[[Delete]](ref.[[ReferencedName]]).
|
||||||
bool delete_status = TRY(base_obj->internal_delete(m_name));
|
bool delete_status = TRY(base_obj->internal_delete(name()));
|
||||||
|
|
||||||
// e. If deleteStatus is false and ref.[[Strict]] is true, throw a TypeError exception.
|
// e. If deleteStatus is false and ref.[[Strict]] is true, throw a TypeError exception.
|
||||||
if (!delete_status && m_strict)
|
if (!delete_status && m_strict)
|
||||||
return vm.throw_completion<TypeError>(ErrorType::ReferenceNullishDeleteProperty, m_name, m_base_value.to_string_without_side_effects());
|
return vm.throw_completion<TypeError>(ErrorType::ReferenceNullishDeleteProperty, name(), m_base_value.to_string_without_side_effects());
|
||||||
|
|
||||||
// f. Return deleteStatus.
|
// f. Return deleteStatus.
|
||||||
return delete_status;
|
return delete_status;
|
||||||
|
@ -195,7 +195,7 @@ ThrowCompletionOr<bool> Reference::delete_(VM& vm)
|
||||||
VERIFY(m_base_type == BaseType::Environment);
|
VERIFY(m_base_type == BaseType::Environment);
|
||||||
|
|
||||||
// c. Return ? base.DeleteBinding(ref.[[ReferencedName]]).
|
// c. Return ? base.DeleteBinding(ref.[[ReferencedName]]).
|
||||||
return m_base_environment->delete_binding(vm, m_name.as_string());
|
return m_base_environment->delete_binding(vm, name().as_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.2.4.8 InitializeReferencedBinding ( V, W ), https://tc39.es/ecma262/#sec-object.prototype.hasownproperty
|
// 6.2.4.8 InitializeReferencedBinding ( V, W ), https://tc39.es/ecma262/#sec-object.prototype.hasownproperty
|
||||||
|
@ -204,7 +204,7 @@ ThrowCompletionOr<void> Reference::initialize_referenced_binding(VM& vm, Value v
|
||||||
{
|
{
|
||||||
VERIFY(!is_unresolvable());
|
VERIFY(!is_unresolvable());
|
||||||
VERIFY(m_base_type == BaseType::Environment);
|
VERIFY(m_base_type == BaseType::Environment);
|
||||||
return m_base_environment->initialize_binding(vm, m_name.as_string(), value, hint);
|
return m_base_environment->initialize_binding(vm, name().as_string(), value, hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6.2.4.9 MakePrivateReference ( baseValue, privateIdentifier ), https://tc39.es/ecma262/#sec-makeprivatereference
|
// 6.2.4.9 MakePrivateReference ( baseValue, privateIdentifier ), https://tc39.es/ecma262/#sec-makeprivatereference
|
||||||
|
|
|
@ -23,7 +23,6 @@ public:
|
||||||
Environment,
|
Environment,
|
||||||
};
|
};
|
||||||
|
|
||||||
Reference() = default;
|
|
||||||
Reference(BaseType type, PropertyKey name, bool strict)
|
Reference(BaseType type, PropertyKey name, bool strict)
|
||||||
: m_base_type(type)
|
: m_base_type(type)
|
||||||
, m_name(move(name))
|
, m_name(move(name))
|
||||||
|
@ -52,10 +51,8 @@ public:
|
||||||
Reference(Value base, PrivateName name)
|
Reference(Value base, PrivateName name)
|
||||||
: m_base_type(BaseType::Value)
|
: m_base_type(BaseType::Value)
|
||||||
, m_base_value(base)
|
, m_base_value(base)
|
||||||
, m_this_value(Value {})
|
, m_name(move(name))
|
||||||
, m_strict(true)
|
, m_strict(true)
|
||||||
, m_is_private(true)
|
|
||||||
, m_private_name(move(name))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +68,8 @@ public:
|
||||||
return *m_base_environment;
|
return *m_base_environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyKey const& name() const { return m_name; }
|
PropertyKey const& name() const { return m_name.get<PropertyKey>(); }
|
||||||
|
PrivateName const& private_name() const { return m_name.get<PrivateName>(); }
|
||||||
bool is_strict() const { return m_strict; }
|
bool is_strict() const { return m_strict; }
|
||||||
|
|
||||||
// 6.2.4.2 IsUnresolvableReference ( V ), https://tc39.es/ecma262/#sec-isunresolvablereference
|
// 6.2.4.2 IsUnresolvableReference ( V ), https://tc39.es/ecma262/#sec-isunresolvablereference
|
||||||
|
@ -105,7 +103,7 @@ public:
|
||||||
// 6.2.4.4 IsPrivateReference ( V ), https://tc39.es/ecma262/#sec-isprivatereference
|
// 6.2.4.4 IsPrivateReference ( V ), https://tc39.es/ecma262/#sec-isprivatereference
|
||||||
bool is_private_reference() const
|
bool is_private_reference() const
|
||||||
{
|
{
|
||||||
return m_is_private;
|
return m_name.has<PrivateName>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: Non-standard helper.
|
// Note: Non-standard helper.
|
||||||
|
@ -120,7 +118,7 @@ public:
|
||||||
ThrowCompletionOr<Value> get_value(VM&) const;
|
ThrowCompletionOr<Value> get_value(VM&) const;
|
||||||
ThrowCompletionOr<bool> delete_(VM&);
|
ThrowCompletionOr<bool> delete_(VM&);
|
||||||
|
|
||||||
bool is_valid_reference() const { return m_name.is_valid() || m_is_private; }
|
bool is_valid_reference() const { return true; }
|
||||||
|
|
||||||
Optional<EnvironmentCoordinate> environment_coordinate() const { return m_environment_coordinate; }
|
Optional<EnvironmentCoordinate> environment_coordinate() const { return m_environment_coordinate; }
|
||||||
|
|
||||||
|
@ -132,14 +130,10 @@ private:
|
||||||
Value m_base_value {};
|
Value m_base_value {};
|
||||||
mutable Environment* m_base_environment;
|
mutable Environment* m_base_environment;
|
||||||
};
|
};
|
||||||
PropertyKey m_name;
|
Variant<PropertyKey, PrivateName> m_name;
|
||||||
Value m_this_value;
|
Value m_this_value;
|
||||||
bool m_strict { false };
|
bool m_strict { false };
|
||||||
|
|
||||||
bool m_is_private { false };
|
|
||||||
// FIXME: This can (probably) be an union with m_name.
|
|
||||||
PrivateName m_private_name;
|
|
||||||
|
|
||||||
Optional<EnvironmentCoordinate> m_environment_coordinate;
|
Optional<EnvironmentCoordinate> m_environment_coordinate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue