mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:37:43 +00:00
LibJS: Replace StringOrSymbol::from_value with Value::to_property_key
This is a more specification compliant implementation of the abstract operation 7.1.19 ToPropertyKey which should handle boxed symbols correctly.
This commit is contained in:
parent
e72e621d89
commit
eb0b1c432a
8 changed files with 29 additions and 29 deletions
|
@ -824,15 +824,15 @@ Value ClassExpression::execute(Interpreter& interpreter, GlobalObject& global_ob
|
||||||
|
|
||||||
switch (method.kind()) {
|
switch (method.kind()) {
|
||||||
case ClassMethod::Kind::Method:
|
case ClassMethod::Kind::Method:
|
||||||
target.define_property(StringOrSymbol::from_value(global_object, key), method_value);
|
target.define_property(key.to_property_key(global_object), method_value);
|
||||||
break;
|
break;
|
||||||
case ClassMethod::Kind::Getter:
|
case ClassMethod::Kind::Getter:
|
||||||
update_function_name(method_value, String::formatted("get {}", get_function_name(global_object, key)));
|
update_function_name(method_value, String::formatted("get {}", get_function_name(global_object, key)));
|
||||||
target.define_accessor(StringOrSymbol::from_value(global_object, key), &method_function, nullptr, Attribute::Configurable | Attribute::Enumerable);
|
target.define_accessor(key.to_property_key(global_object), &method_function, nullptr, Attribute::Configurable | Attribute::Enumerable);
|
||||||
break;
|
break;
|
||||||
case ClassMethod::Kind::Setter:
|
case ClassMethod::Kind::Setter:
|
||||||
update_function_name(method_value, String::formatted("set {}", get_function_name(global_object, key)));
|
update_function_name(method_value, String::formatted("set {}", get_function_name(global_object, key)));
|
||||||
target.define_accessor(StringOrSymbol::from_value(global_object, key), nullptr, &method_function, Attribute::Configurable | Attribute::Enumerable);
|
target.define_accessor(key.to_property_key(global_object), nullptr, &method_function, Attribute::Configurable | Attribute::Enumerable);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
|
|
|
@ -130,6 +130,7 @@ class ScopeNode;
|
||||||
class ScopeObject;
|
class ScopeObject;
|
||||||
class Shape;
|
class Shape;
|
||||||
class Statement;
|
class Statement;
|
||||||
|
class StringOrSymbol;
|
||||||
class Symbol;
|
class Symbol;
|
||||||
class Token;
|
class Token;
|
||||||
class VM;
|
class VM;
|
||||||
|
|
|
@ -202,14 +202,14 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::define_property_)
|
||||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Object argument");
|
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Object argument");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
auto property_key = vm.argument(1).to_property_key(global_object);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
if (!vm.argument(2).is_object()) {
|
if (!vm.argument(2).is_object()) {
|
||||||
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Descriptor argument");
|
vm.throw_exception<TypeError>(global_object, ErrorType::NotAnObject, "Descriptor argument");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
auto& object = vm.argument(0).as_object();
|
auto& object = vm.argument(0).as_object();
|
||||||
auto property_key = StringOrSymbol::from_value(global_object, vm.argument(1));
|
|
||||||
if (vm.exception())
|
|
||||||
return {};
|
|
||||||
auto& descriptor = vm.argument(2).as_object();
|
auto& descriptor = vm.argument(2).as_object();
|
||||||
if (!object.define_property(property_key, descriptor)) {
|
if (!object.define_property(property_key, descriptor)) {
|
||||||
if (!vm.exception()) {
|
if (!vm.exception()) {
|
||||||
|
@ -316,10 +316,10 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::has_own)
|
||||||
auto* object = vm.argument(0).to_object(global_object);
|
auto* object = vm.argument(0).to_object(global_object);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
auto string_or_symbol = StringOrSymbol::from_value(global_object, vm.argument(1));
|
auto property_key = vm.argument(1).to_property_key(global_object);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
return {};
|
return {};
|
||||||
return Value(object->has_own_property(string_or_symbol));
|
return Value(object->has_own_property(property_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,13 +43,13 @@ ObjectPrototype::~ObjectPrototype()
|
||||||
|
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::has_own_property)
|
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::has_own_property)
|
||||||
{
|
{
|
||||||
|
auto property_key = vm.argument(0).to_property_key(global_object);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
auto* this_object = vm.this_value(global_object).to_object(global_object);
|
||||||
if (!this_object)
|
if (!this_object)
|
||||||
return {};
|
return {};
|
||||||
auto string_or_symbol = StringOrSymbol::from_value(global_object, vm.argument(0));
|
return Value(this_object->has_own_property(property_key));
|
||||||
if (vm.exception())
|
|
||||||
return {};
|
|
||||||
return Value(this_object->has_own_property(string_or_symbol));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
|
JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
|
||||||
|
|
|
@ -124,13 +124,13 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::define_property)
|
||||||
auto* target = get_target_object_from(global_object, "defineProperty");
|
auto* target = get_target_object_from(global_object, "defineProperty");
|
||||||
if (!target)
|
if (!target)
|
||||||
return {};
|
return {};
|
||||||
|
auto property_key = vm.argument(1).to_property_key(global_object);
|
||||||
|
if (vm.exception())
|
||||||
|
return {};
|
||||||
if (!vm.argument(2).is_object()) {
|
if (!vm.argument(2).is_object()) {
|
||||||
vm.throw_exception<TypeError>(global_object, ErrorType::ReflectBadDescriptorArgument);
|
vm.throw_exception<TypeError>(global_object, ErrorType::ReflectBadDescriptorArgument);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
auto property_key = StringOrSymbol::from_value(global_object, vm.argument(1));
|
|
||||||
if (vm.exception())
|
|
||||||
return {};
|
|
||||||
auto& descriptor = vm.argument(2).as_object();
|
auto& descriptor = vm.argument(2).as_object();
|
||||||
auto success = target->define_property(property_key, descriptor, false);
|
auto success = target->define_property(property_key, descriptor, false);
|
||||||
if (vm.exception())
|
if (vm.exception())
|
||||||
|
|
|
@ -15,18 +15,6 @@ namespace JS {
|
||||||
|
|
||||||
class StringOrSymbol {
|
class StringOrSymbol {
|
||||||
public:
|
public:
|
||||||
static StringOrSymbol from_value(GlobalObject& global_object, Value value)
|
|
||||||
{
|
|
||||||
if (value.is_empty())
|
|
||||||
return {};
|
|
||||||
if (value.is_symbol())
|
|
||||||
return &value.as_symbol();
|
|
||||||
auto string = value.to_string(global_object);
|
|
||||||
if (string.is_null())
|
|
||||||
return {};
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringOrSymbol() = default;
|
StringOrSymbol() = default;
|
||||||
|
|
||||||
StringOrSymbol(const char* chars)
|
StringOrSymbol(const char* chars)
|
||||||
|
|
|
@ -543,6 +543,16 @@ double Value::to_double(GlobalObject& global_object) const
|
||||||
return number.as_double();
|
return number.as_double();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringOrSymbol Value::to_property_key(GlobalObject& global_object) const
|
||||||
|
{
|
||||||
|
auto key = to_primitive(global_object, PreferredType::String);
|
||||||
|
if (global_object.vm().exception())
|
||||||
|
return {};
|
||||||
|
if (key.is_symbol())
|
||||||
|
return &key.as_symbol();
|
||||||
|
return to_string(global_object);
|
||||||
|
}
|
||||||
|
|
||||||
i32 Value::to_i32_slow_case(GlobalObject& global_object) const
|
i32 Value::to_i32_slow_case(GlobalObject& global_object) const
|
||||||
{
|
{
|
||||||
VERIFY(type() != Type::Int32);
|
VERIFY(type() != Type::Int32);
|
||||||
|
@ -1008,10 +1018,10 @@ Value in(GlobalObject& global_object, Value lhs, Value rhs)
|
||||||
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::InOperatorWithObject);
|
global_object.vm().throw_exception<TypeError>(global_object, ErrorType::InOperatorWithObject);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
auto lhs_string_or_symbol = StringOrSymbol::from_value(global_object, lhs);
|
auto lhs_property_key = lhs.to_property_key(global_object);
|
||||||
if (global_object.vm().exception())
|
if (global_object.vm().exception())
|
||||||
return {};
|
return {};
|
||||||
return Value(rhs.as_object().has_property(lhs_string_or_symbol));
|
return Value(rhs.as_object().has_property(lhs_property_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
Value instance_of(GlobalObject& global_object, Value lhs, Value rhs)
|
Value instance_of(GlobalObject& global_object, Value lhs, Value rhs)
|
||||||
|
|
|
@ -260,6 +260,7 @@ public:
|
||||||
Value to_number(GlobalObject&) const;
|
Value to_number(GlobalObject&) const;
|
||||||
BigInt* to_bigint(GlobalObject&) const;
|
BigInt* to_bigint(GlobalObject&) const;
|
||||||
double to_double(GlobalObject&) const;
|
double to_double(GlobalObject&) const;
|
||||||
|
StringOrSymbol to_property_key(GlobalObject&) const;
|
||||||
i32 to_i32(GlobalObject& global_object) const
|
i32 to_i32(GlobalObject& global_object) const
|
||||||
{
|
{
|
||||||
if (m_type == Type::Int32)
|
if (m_type == Type::Int32)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue