mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-08 20:32:56 +03:00
Everywhere: Rename JS::PropertyKey variables from property_{name => key}
PropertyKey used to be called PropertyName, but got renamed. Let's update all the variables of this type as well.
This commit is contained in:
parent
3e6aaa3520
commit
6f20f49b21
Notes:
sideshowbarker
2024-07-17 19:41:36 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/6f20f49b210 Pull-request: https://github.com/SerenityOS/serenity/pull/12314 Reviewed-by: https://github.com/davidot ✅
@ -2411,27 +2411,27 @@ static JS::Value wrap_for_legacy_platform_object_get_own_property(JS::GlobalObje
|
||||
// https://webidl.spec.whatwg.org/#dfn-named-property-visibility
|
||||
|
||||
scoped_generator.append(R"~~~(
|
||||
JS::ThrowCompletionOr<bool> @class_name@::is_named_property_exposed_on_object(JS::PropertyKey const& property_name) const
|
||||
JS::ThrowCompletionOr<bool> @class_name@::is_named_property_exposed_on_object(JS::PropertyKey const& property_key) const
|
||||
{
|
||||
[[maybe_unused]] auto& vm = this->vm();
|
||||
|
||||
// The spec doesn't say anything about the type of the property name here.
|
||||
// Numbers can be converted to a string, which is fine and what other engines do.
|
||||
// However, since a symbol cannot be converted to a string, it cannot be a supported property name. Return early if it's a symbol.
|
||||
if (property_name.is_symbol())
|
||||
if (property_key.is_symbol())
|
||||
return false;
|
||||
|
||||
// 1. If P is not a supported property name of O, then return false.
|
||||
// NOTE: This is in it's own variable to enforce the type.
|
||||
// FIXME: Can this throw?
|
||||
Vector<String> supported_property_names = impl().supported_property_names();
|
||||
auto property_name_string = property_name.to_string();
|
||||
if (!supported_property_names.contains_slow(property_name_string))
|
||||
auto property_key_string = property_key.to_string();
|
||||
if (!supported_property_names.contains_slow(property_key_string))
|
||||
return false;
|
||||
|
||||
// 2. If O has an own property named P, then return false.
|
||||
// NOTE: This has to be done manually instead of using Object::has_own_property, as that would use the overridden internal_get_own_property.
|
||||
auto own_property_named_p = MUST(Object::internal_get_own_property(property_name));
|
||||
auto own_property_named_p = MUST(Object::internal_get_own_property(property_key));
|
||||
|
||||
if (own_property_named_p.has_value())
|
||||
return false;
|
||||
@ -2453,7 +2453,7 @@ JS::ThrowCompletionOr<bool> @class_name@::is_named_property_exposed_on_object(JS
|
||||
while (prototype) {
|
||||
// FIXME: 1. If prototype is not a named properties object, and prototype has an own property named P, then return false.
|
||||
// (It currently does not check for named property objects)
|
||||
bool prototype_has_own_property_named_p = TRY(prototype->has_own_property(property_name));
|
||||
bool prototype_has_own_property_named_p = TRY(prototype->has_own_property(property_key));
|
||||
if (prototype_has_own_property_named_p)
|
||||
return false;
|
||||
|
||||
|
@ -22,39 +22,39 @@ DebuggerGlobalJSObject::DebuggerGlobalJSObject()
|
||||
m_variables = lib->debug_info->get_variables_in_current_scope(regs);
|
||||
}
|
||||
|
||||
JS::ThrowCompletionOr<JS::Value> DebuggerGlobalJSObject::internal_get(JS::PropertyKey const& property_name, JS::Value receiver) const
|
||||
JS::ThrowCompletionOr<JS::Value> DebuggerGlobalJSObject::internal_get(JS::PropertyKey const& property_key, JS::Value receiver) const
|
||||
{
|
||||
if (m_variables.is_empty() || !property_name.is_string())
|
||||
return Base::internal_get(property_name, receiver);
|
||||
if (m_variables.is_empty() || !property_key.is_string())
|
||||
return Base::internal_get(property_key, receiver);
|
||||
|
||||
auto it = m_variables.find_if([&](auto& variable) {
|
||||
return variable->name == property_name.as_string();
|
||||
return variable->name == property_key.as_string();
|
||||
});
|
||||
if (it.is_end())
|
||||
return Base::internal_get(property_name, receiver);
|
||||
return Base::internal_get(property_key, receiver);
|
||||
auto& target_variable = **it;
|
||||
auto js_value = debugger_to_js(target_variable);
|
||||
if (js_value.has_value())
|
||||
return js_value.value();
|
||||
auto error_string = String::formatted("Variable {} of type {} is not convertible to a JS Value", property_name.as_string(), target_variable.type_name);
|
||||
auto error_string = String::formatted("Variable {} of type {} is not convertible to a JS Value", property_key.as_string(), target_variable.type_name);
|
||||
return vm().throw_completion<JS::TypeError>(const_cast<DebuggerGlobalJSObject&>(*this), move(error_string));
|
||||
}
|
||||
|
||||
JS::ThrowCompletionOr<bool> DebuggerGlobalJSObject::internal_set(JS::PropertyKey const& property_name, JS::Value value, JS::Value receiver)
|
||||
JS::ThrowCompletionOr<bool> DebuggerGlobalJSObject::internal_set(JS::PropertyKey const& property_key, JS::Value value, JS::Value receiver)
|
||||
{
|
||||
if (m_variables.is_empty() || !property_name.is_string())
|
||||
return Base::internal_set(property_name, value, receiver);
|
||||
if (m_variables.is_empty() || !property_key.is_string())
|
||||
return Base::internal_set(property_key, value, receiver);
|
||||
|
||||
auto it = m_variables.find_if([&](auto& variable) {
|
||||
return variable->name == property_name.as_string();
|
||||
return variable->name == property_key.as_string();
|
||||
});
|
||||
if (it.is_end())
|
||||
return Base::internal_set(property_name, value, receiver);
|
||||
return Base::internal_set(property_key, value, receiver);
|
||||
auto& target_variable = **it;
|
||||
auto debugger_value = js_to_debugger(value, target_variable);
|
||||
if (debugger_value.has_value())
|
||||
return Debugger::the().session()->poke(target_variable.location_data.address, debugger_value.value());
|
||||
auto error_string = String::formatted("Cannot convert JS value {} to variable {} of type {}", value.to_string_without_side_effects(), property_name.as_string(), target_variable.type_name);
|
||||
auto error_string = String::formatted("Cannot convert JS value {} to variable {} of type {}", value.to_string_without_side_effects(), property_key.as_string(), target_variable.type_name);
|
||||
return vm().throw_completion<JS::TypeError>(const_cast<DebuggerGlobalJSObject&>(*this), move(error_string));
|
||||
}
|
||||
|
||||
|
@ -29,20 +29,20 @@ DebuggerVariableJSObject::~DebuggerVariableJSObject()
|
||||
{
|
||||
}
|
||||
|
||||
JS::ThrowCompletionOr<bool> DebuggerVariableJSObject::internal_set(const JS::PropertyKey& property_name, JS::Value value, JS::Value)
|
||||
JS::ThrowCompletionOr<bool> DebuggerVariableJSObject::internal_set(const JS::PropertyKey& property_key, JS::Value value, JS::Value)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
if (!property_name.is_string())
|
||||
return vm.throw_completion<JS::TypeError>(global_object(), String::formatted("Invalid variable name {}", property_name.to_string()));
|
||||
if (!property_key.is_string())
|
||||
return vm.throw_completion<JS::TypeError>(global_object(), String::formatted("Invalid variable name {}", property_key.to_string()));
|
||||
|
||||
auto name = property_name.as_string();
|
||||
auto name = property_key.as_string();
|
||||
auto it = m_variable_info.members.find_if([&](auto& variable) {
|
||||
return variable->name == name;
|
||||
});
|
||||
|
||||
if (it.is_end())
|
||||
return vm.throw_completion<JS::TypeError>(global_object(), String::formatted("Variable of type {} has no property {}", m_variable_info.type_name, property_name));
|
||||
return vm.throw_completion<JS::TypeError>(global_object(), String::formatted("Variable of type {} has no property {}", m_variable_info.type_name, property_key));
|
||||
|
||||
auto& member = **it;
|
||||
auto new_value = debugger_object().js_to_debugger(value, member);
|
||||
|
@ -1397,7 +1397,7 @@ ThrowCompletionOr<Reference> MemberExpression::to_reference(Interpreter& interpr
|
||||
|
||||
// From here on equivalent to
|
||||
// 13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue, identifierName, strict ), https://tc39.es/ecma262/#sec-evaluate-property-access-with-identifier-key
|
||||
PropertyKey property_name;
|
||||
PropertyKey property_key;
|
||||
if (is_computed()) {
|
||||
// Weird order which I can't quite find from the specs.
|
||||
auto value = TRY(m_property->execute(interpreter, global_object)).release_value();
|
||||
@ -1405,19 +1405,19 @@ ThrowCompletionOr<Reference> MemberExpression::to_reference(Interpreter& interpr
|
||||
|
||||
TRY(require_object_coercible(global_object, base_value));
|
||||
|
||||
property_name = TRY(PropertyKey::from_value(global_object, value));
|
||||
property_key = TRY(PropertyKey::from_value(global_object, value));
|
||||
} else if (is<PrivateIdentifier>(*m_property)) {
|
||||
auto& private_identifier = static_cast<PrivateIdentifier const&>(*m_property);
|
||||
return make_private_reference(interpreter.vm(), base_value, private_identifier.string());
|
||||
} else {
|
||||
property_name = verify_cast<Identifier>(*m_property).string();
|
||||
property_key = verify_cast<Identifier>(*m_property).string();
|
||||
TRY(require_object_coercible(global_object, base_value));
|
||||
}
|
||||
if (!property_name.is_valid())
|
||||
if (!property_key.is_valid())
|
||||
return Reference {};
|
||||
|
||||
auto strict = interpreter.vm().in_strict_mode();
|
||||
return Reference { base_value, move(property_name), {}, strict };
|
||||
return Reference { base_value, move(property_key), {}, strict };
|
||||
}
|
||||
|
||||
// 13.5.1.2 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-delete-operator-runtime-semantics-evaluation
|
||||
@ -1504,7 +1504,7 @@ static ThrowCompletionOr<ClassElement::ClassElementName> class_key_to_property_n
|
||||
// 15.4.5 Runtime Semantics: MethodDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-methoddefinitionevaluation
|
||||
ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluation(Interpreter& interpreter, GlobalObject& global_object, Object& target) const
|
||||
{
|
||||
auto property_key = TRY(class_key_to_property_name(interpreter, global_object, *m_key));
|
||||
auto property_key_or_private_name = TRY(class_key_to_property_name(interpreter, global_object, *m_key));
|
||||
|
||||
auto method_value = TRY(m_function->execute(interpreter, global_object)).release_value();
|
||||
|
||||
@ -1514,38 +1514,38 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluatio
|
||||
method_function.make_method(target);
|
||||
|
||||
auto set_function_name = [&](String prefix = "") {
|
||||
auto property_name = property_key.visit(
|
||||
[&](PropertyKey const& property_name) -> String {
|
||||
if (property_name.is_symbol()) {
|
||||
auto description = property_name.as_symbol()->description();
|
||||
auto name = property_key_or_private_name.visit(
|
||||
[&](PropertyKey const& property_key) -> String {
|
||||
if (property_key.is_symbol()) {
|
||||
auto description = property_key.as_symbol()->description();
|
||||
if (description.is_empty())
|
||||
return "";
|
||||
return String::formatted("[{}]", description);
|
||||
} else {
|
||||
return property_name.to_string();
|
||||
return property_key.to_string();
|
||||
}
|
||||
},
|
||||
[&](PrivateName const& private_name) -> String {
|
||||
return private_name.description;
|
||||
});
|
||||
|
||||
update_function_name(method_value, String::formatted("{}{}{}", prefix, prefix.is_empty() ? "" : " ", property_name));
|
||||
update_function_name(method_value, String::formatted("{}{}{}", prefix, prefix.is_empty() ? "" : " ", name));
|
||||
};
|
||||
|
||||
if (property_key.has<PropertyKey>()) {
|
||||
auto& property_name = property_key.get<PropertyKey>();
|
||||
if (property_key_or_private_name.has<PropertyKey>()) {
|
||||
auto& property_key = property_key_or_private_name.get<PropertyKey>();
|
||||
switch (kind()) {
|
||||
case ClassMethod::Kind::Method:
|
||||
set_function_name();
|
||||
TRY(target.define_property_or_throw(property_name, { .value = method_value, .writable = true, .enumerable = false, .configurable = true }));
|
||||
TRY(target.define_property_or_throw(property_key, { .value = method_value, .writable = true, .enumerable = false, .configurable = true }));
|
||||
break;
|
||||
case ClassMethod::Kind::Getter:
|
||||
set_function_name("get");
|
||||
TRY(target.define_property_or_throw(property_name, { .get = &method_function, .enumerable = true, .configurable = true }));
|
||||
TRY(target.define_property_or_throw(property_key, { .get = &method_function, .enumerable = true, .configurable = true }));
|
||||
break;
|
||||
case ClassMethod::Kind::Setter:
|
||||
set_function_name("set");
|
||||
TRY(target.define_property_or_throw(property_name, { .set = &method_function, .enumerable = true, .configurable = true }));
|
||||
TRY(target.define_property_or_throw(property_key, { .set = &method_function, .enumerable = true, .configurable = true }));
|
||||
break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
@ -1553,7 +1553,7 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassMethod::class_element_evaluatio
|
||||
|
||||
return ClassValue { normal_completion({}) };
|
||||
} else {
|
||||
auto& private_name = property_key.get<PrivateName>();
|
||||
auto& private_name = property_key_or_private_name.get<PrivateName>();
|
||||
switch (kind()) {
|
||||
case Kind::Method:
|
||||
set_function_name();
|
||||
@ -1614,13 +1614,13 @@ private:
|
||||
// 15.7.10 Runtime Semantics: ClassFieldDefinitionEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-classfielddefinitionevaluation
|
||||
ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation(Interpreter& interpreter, GlobalObject& global_object, Object& target) const
|
||||
{
|
||||
auto property_key = TRY(class_key_to_property_name(interpreter, global_object, *m_key));
|
||||
auto property_key_or_private_name = TRY(class_key_to_property_name(interpreter, global_object, *m_key));
|
||||
Handle<ECMAScriptFunctionObject> initializer {};
|
||||
if (m_initializer) {
|
||||
auto copy_initializer = m_initializer;
|
||||
auto name = property_key.visit(
|
||||
[&](PropertyKey const& property_name) -> String {
|
||||
return property_name.is_number() ? property_name.to_string() : property_name.to_string_or_symbol().to_display_string();
|
||||
auto name = property_key_or_private_name.visit(
|
||||
[&](PropertyKey const& property_key) -> String {
|
||||
return property_key.is_number() ? property_key.to_string() : property_key.to_string_or_symbol().to_display_string();
|
||||
},
|
||||
[&](PrivateName const& private_name) -> String {
|
||||
return private_name.description;
|
||||
@ -1634,7 +1634,7 @@ ThrowCompletionOr<ClassElement::ClassValue> ClassField::class_element_evaluation
|
||||
|
||||
return ClassValue {
|
||||
ClassFieldDefinition {
|
||||
move(property_key),
|
||||
move(property_key_or_private_name),
|
||||
move(initializer),
|
||||
}
|
||||
};
|
||||
|
@ -236,15 +236,15 @@ void CopyObjectExcludingProperties::execute_impl(Bytecode::Interpreter& interpre
|
||||
|
||||
for (auto& key : own_keys) {
|
||||
if (!excluded_names.contains(key)) {
|
||||
auto property_name_or_error = key.to_property_key(interpreter.global_object());
|
||||
if (property_name_or_error.is_error())
|
||||
auto property_key_or_error = key.to_property_key(interpreter.global_object());
|
||||
if (property_key_or_error.is_error())
|
||||
return;
|
||||
PropertyKey property_name = property_name_or_error.release_value();
|
||||
auto property_value_or_error = from_object->get(property_name);
|
||||
PropertyKey property_key = property_key_or_error.release_value();
|
||||
auto property_value_or_error = from_object->get(property_key);
|
||||
if (property_value_or_error.is_error())
|
||||
return;
|
||||
auto property_value = property_value_or_error.release_value();
|
||||
to_object->define_direct_property(property_name, property_value, JS::default_attributes);
|
||||
to_object->define_direct_property(property_key, property_value, JS::default_attributes);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1654,14 +1654,14 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||
|
||||
while (!done() && !match(TokenType::CurlyClose)) {
|
||||
property_type = ObjectProperty::Type::KeyValue;
|
||||
RefPtr<Expression> property_name;
|
||||
RefPtr<Expression> property_key;
|
||||
RefPtr<Expression> property_value;
|
||||
FunctionKind function_kind { FunctionKind::Normal };
|
||||
|
||||
if (match(TokenType::TripleDot)) {
|
||||
consume();
|
||||
property_name = parse_expression(4);
|
||||
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_name, nullptr, ObjectProperty::Type::Spread, false));
|
||||
property_key = parse_expression(4);
|
||||
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_key, nullptr, ObjectProperty::Type::Spread, false));
|
||||
if (!match(TokenType::Comma))
|
||||
break;
|
||||
consume(TokenType::Comma);
|
||||
@ -1685,26 +1685,26 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||
if (match(TokenType::Asterisk)) {
|
||||
consume();
|
||||
property_type = ObjectProperty::Type::KeyValue;
|
||||
property_name = parse_property_key();
|
||||
property_key = parse_property_key();
|
||||
VERIFY(function_kind == FunctionKind::Normal || function_kind == FunctionKind::Async);
|
||||
function_kind = function_kind == FunctionKind::Normal ? FunctionKind::Generator : FunctionKind::AsyncGenerator;
|
||||
} else if (match_identifier()) {
|
||||
auto identifier = consume();
|
||||
if (identifier.original_value() == "get"sv && match_property_key()) {
|
||||
property_type = ObjectProperty::Type::Getter;
|
||||
property_name = parse_property_key();
|
||||
property_key = parse_property_key();
|
||||
} else if (identifier.original_value() == "set"sv && match_property_key()) {
|
||||
property_type = ObjectProperty::Type::Setter;
|
||||
property_name = parse_property_key();
|
||||
property_key = parse_property_key();
|
||||
} else {
|
||||
property_name = create_ast_node<StringLiteral>({ m_state.current_token.filename(), rule_start.position(), position() }, identifier.value());
|
||||
property_key = create_ast_node<StringLiteral>({ m_state.current_token.filename(), rule_start.position(), position() }, identifier.value());
|
||||
property_value = create_ast_node<Identifier>({ m_state.current_token.filename(), rule_start.position(), position() }, identifier.value());
|
||||
}
|
||||
} else {
|
||||
property_name = parse_property_key();
|
||||
property_key = parse_property_key();
|
||||
}
|
||||
|
||||
bool is_proto = (type == TokenType::StringLiteral || type == TokenType::Identifier) && is<StringLiteral>(*property_name) && static_cast<StringLiteral const&>(*property_name).value() == "__proto__";
|
||||
bool is_proto = (type == TokenType::StringLiteral || type == TokenType::Identifier) && is<StringLiteral>(*property_key) && static_cast<StringLiteral const&>(*property_key).value() == "__proto__";
|
||||
|
||||
if (property_type == ObjectProperty::Type::Getter || property_type == ObjectProperty::Type::Setter) {
|
||||
if (!match(TokenType::ParenOpen)) {
|
||||
@ -1721,7 +1721,7 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||
if (!invalid_object_literal_property_range.has_value())
|
||||
invalid_object_literal_property_range = expression->source_range();
|
||||
} else if (match(TokenType::ParenOpen)) {
|
||||
VERIFY(property_name);
|
||||
VERIFY(property_key);
|
||||
u8 parse_options = FunctionNodeParseOptions::AllowSuperPropertyLookup;
|
||||
if (property_type == ObjectProperty::Type::Getter)
|
||||
parse_options |= FunctionNodeParseOptions::IsGetterFunction;
|
||||
@ -1732,9 +1732,9 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||
if (function_kind == FunctionKind::Async || function_kind == FunctionKind::AsyncGenerator)
|
||||
parse_options |= FunctionNodeParseOptions::IsAsyncFunction;
|
||||
auto function = parse_function_node<FunctionExpression>(parse_options, function_start);
|
||||
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_name, function, property_type, true));
|
||||
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_key, function, property_type, true));
|
||||
} else if (match(TokenType::Colon)) {
|
||||
if (!property_name) {
|
||||
if (!property_key) {
|
||||
expected("a property name");
|
||||
skip_to_next_property();
|
||||
continue;
|
||||
@ -1745,15 +1745,15 @@ NonnullRefPtr<ObjectExpression> Parser::parse_object_expression()
|
||||
syntax_error("Property name '__proto__' must not appear more than once in object literal");
|
||||
has_direct_proto_property = true;
|
||||
}
|
||||
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_name, parse_expression(2), property_type, false));
|
||||
} else if (property_name && property_value) {
|
||||
if (m_state.strict_mode && is<StringLiteral>(*property_name)) {
|
||||
auto& string_literal = static_cast<StringLiteral const&>(*property_name);
|
||||
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_key, parse_expression(2), property_type, false));
|
||||
} else if (property_key && property_value) {
|
||||
if (m_state.strict_mode && is<StringLiteral>(*property_key)) {
|
||||
auto& string_literal = static_cast<StringLiteral const&>(*property_key);
|
||||
if (is_strict_reserved_word(string_literal.value()))
|
||||
syntax_error(String::formatted("'{}' is a reserved keyword", string_literal.value()));
|
||||
}
|
||||
|
||||
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_name, *property_value, property_type, false));
|
||||
properties.append(create_ast_node<ObjectProperty>({ m_state.current_token.filename(), rule_start.position(), position() }, *property_key, *property_value, property_type, false));
|
||||
} else {
|
||||
expected("a property");
|
||||
skip_to_next_property();
|
||||
|
@ -246,11 +246,11 @@ bool is_compatible_property_descriptor(bool extensible, PropertyDescriptor const
|
||||
}
|
||||
|
||||
// 10.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current ), https://tc39.es/ecma262/#sec-validateandapplypropertydescriptor
|
||||
bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& property_name, bool extensible, PropertyDescriptor const& descriptor, Optional<PropertyDescriptor> const& current)
|
||||
bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& property_key, bool extensible, PropertyDescriptor const& descriptor, Optional<PropertyDescriptor> const& current)
|
||||
{
|
||||
// 1. Assert: If O is not undefined, then IsPropertyKey(P) is true.
|
||||
if (object)
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. If current is undefined, then
|
||||
if (!current.has_value()) {
|
||||
@ -267,7 +267,7 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
|
||||
// to its default value.
|
||||
if (object) {
|
||||
auto value = descriptor.value.value_or(js_undefined());
|
||||
object->storage_set(property_name, { value, descriptor.attributes() });
|
||||
object->storage_set(property_key, { value, descriptor.attributes() });
|
||||
}
|
||||
}
|
||||
// d. Else,
|
||||
@ -281,7 +281,7 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
|
||||
// to its default value.
|
||||
if (object) {
|
||||
auto accessor = Accessor::create(object->vm(), descriptor.get.value_or(nullptr), descriptor.set.value_or(nullptr));
|
||||
object->storage_set(property_name, { accessor, descriptor.attributes() });
|
||||
object->storage_set(property_key, { accessor, descriptor.attributes() });
|
||||
}
|
||||
}
|
||||
// e. Return true.
|
||||
@ -320,7 +320,7 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
|
||||
// set the rest of the property's attributes to their default values.
|
||||
if (object) {
|
||||
auto accessor = Accessor::create(object->vm(), nullptr, nullptr);
|
||||
object->storage_set(property_name, { accessor, current->attributes() });
|
||||
object->storage_set(property_key, { accessor, current->attributes() });
|
||||
}
|
||||
}
|
||||
// c. Else,
|
||||
@ -330,7 +330,7 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
|
||||
// set the rest of the property's attributes to their default values.
|
||||
if (object) {
|
||||
auto value = js_undefined();
|
||||
object->storage_set(property_name, { value, current->attributes() });
|
||||
object->storage_set(property_key, { value, current->attributes() });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -386,7 +386,7 @@ bool validate_and_apply_property_descriptor(Object* object, PropertyKey const& p
|
||||
attributes.set_writable(descriptor.writable.value_or(current->writable.value_or(false)));
|
||||
attributes.set_enumerable(descriptor.enumerable.value_or(current->enumerable.value_or(false)));
|
||||
attributes.set_configurable(descriptor.configurable.value_or(current->configurable.value_or(false)));
|
||||
object->storage_set(property_name, { value, attributes });
|
||||
object->storage_set(property_key, { value, attributes });
|
||||
}
|
||||
|
||||
// 10. Return true.
|
||||
@ -913,19 +913,19 @@ Object* create_mapped_arguments_object(GlobalObject& global_object, FunctionObje
|
||||
}
|
||||
|
||||
// 7.1.21 CanonicalNumericIndexString ( argument ), https://tc39.es/ecma262/#sec-canonicalnumericindexstring
|
||||
Value canonical_numeric_index_string(GlobalObject& global_object, PropertyKey const& property_name)
|
||||
Value canonical_numeric_index_string(GlobalObject& global_object, PropertyKey const& property_key)
|
||||
{
|
||||
// NOTE: If the property name is a number type (An implementation-defined optimized
|
||||
// property key type), it can be treated as a string property that has already been
|
||||
// converted successfully into a canonical numeric index.
|
||||
|
||||
VERIFY(property_name.is_string() || property_name.is_number());
|
||||
VERIFY(property_key.is_string() || property_key.is_number());
|
||||
|
||||
if (property_name.is_number())
|
||||
return Value(property_name.as_number());
|
||||
if (property_key.is_number())
|
||||
return Value(property_key.as_number());
|
||||
|
||||
// 1. Assert: Type(argument) is String.
|
||||
auto argument = Value(js_string(global_object.vm(), property_name.as_string()));
|
||||
auto argument = Value(js_string(global_object.vm(), property_key.as_string()));
|
||||
|
||||
// 2. If argument is "-0", return -0𝔽.
|
||||
if (argument.as_string().string() == "-0")
|
||||
|
@ -35,28 +35,28 @@ void ArgumentsObject::visit_edges(Cell::Visitor& visitor)
|
||||
}
|
||||
|
||||
// 10.4.4.3 [[Get]] ( P, Receiver ), https://tc39.es/ecma262/#sec-arguments-exotic-objects-get-p-receiver
|
||||
ThrowCompletionOr<Value> ArgumentsObject::internal_get(PropertyKey const& property_name, Value receiver) const
|
||||
ThrowCompletionOr<Value> ArgumentsObject::internal_get(PropertyKey const& property_key, Value receiver) const
|
||||
{
|
||||
// 1. Let map be args.[[ParameterMap]].
|
||||
auto& map = *m_parameter_map;
|
||||
|
||||
// 2. Let isMapped be ! HasOwnProperty(map, P).
|
||||
bool is_mapped = MUST(m_parameter_map->has_own_property(property_name));
|
||||
bool is_mapped = MUST(m_parameter_map->has_own_property(property_key));
|
||||
|
||||
// 3. If isMapped is false, then
|
||||
if (!is_mapped) {
|
||||
// a. Return ? OrdinaryGet(args, P, Receiver).
|
||||
return Object::internal_get(property_name, receiver);
|
||||
return Object::internal_get(property_key, receiver);
|
||||
}
|
||||
|
||||
// FIXME: a. Assert: map contains a formal parameter mapping for P.
|
||||
|
||||
// b. Return Get(map, P).
|
||||
return map.get(property_name);
|
||||
return map.get(property_key);
|
||||
}
|
||||
|
||||
// 10.4.4.4 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-arguments-exotic-objects-set-p-v-receiver
|
||||
ThrowCompletionOr<bool> ArgumentsObject::internal_set(PropertyKey const& property_name, Value value, Value receiver)
|
||||
ThrowCompletionOr<bool> ArgumentsObject::internal_set(PropertyKey const& property_key, Value value, Value receiver)
|
||||
{
|
||||
bool is_mapped = false;
|
||||
|
||||
@ -67,38 +67,38 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_set(PropertyKey const& propert
|
||||
} else {
|
||||
// a. Let map be args.[[ParameterMap]].
|
||||
// b. Let isMapped be ! HasOwnProperty(map, P).
|
||||
is_mapped = MUST(parameter_map().has_own_property(property_name));
|
||||
is_mapped = MUST(parameter_map().has_own_property(property_key));
|
||||
}
|
||||
|
||||
// 3. If isMapped is true, then
|
||||
if (is_mapped) {
|
||||
// a. Let setStatus be Set(map, P, V, false).
|
||||
auto set_status = MUST(m_parameter_map->set(property_name, value, Object::ShouldThrowExceptions::No));
|
||||
auto set_status = MUST(m_parameter_map->set(property_key, value, Object::ShouldThrowExceptions::No));
|
||||
|
||||
// b. Assert: setStatus is true because formal parameters mapped by argument objects are always writable.
|
||||
VERIFY(set_status);
|
||||
}
|
||||
|
||||
// 4. Return ? OrdinarySet(args, P, V, Receiver).
|
||||
return Object::internal_set(property_name, value, receiver);
|
||||
return Object::internal_set(property_key, value, receiver);
|
||||
}
|
||||
|
||||
// 10.4.4.5 [[Delete]] ( P ), https://tc39.es/ecma262/#sec-arguments-exotic-objects-delete-p
|
||||
ThrowCompletionOr<bool> ArgumentsObject::internal_delete(PropertyKey const& property_name)
|
||||
ThrowCompletionOr<bool> ArgumentsObject::internal_delete(PropertyKey const& property_key)
|
||||
{
|
||||
// 1. Let map be args.[[ParameterMap]].
|
||||
auto& map = parameter_map();
|
||||
|
||||
// 2. Let isMapped be ! HasOwnProperty(map, P).
|
||||
bool is_mapped = MUST(map.has_own_property(property_name));
|
||||
bool is_mapped = MUST(map.has_own_property(property_key));
|
||||
|
||||
// 3. Let result be ? OrdinaryDelete(args, P).
|
||||
bool result = TRY(Object::internal_delete(property_name));
|
||||
bool result = TRY(Object::internal_delete(property_key));
|
||||
|
||||
// 4. If result is true and isMapped is true, then
|
||||
if (result && is_mapped) {
|
||||
// a. Call map.[[Delete]](P).
|
||||
MUST(map.internal_delete(property_name));
|
||||
MUST(map.internal_delete(property_key));
|
||||
}
|
||||
|
||||
// 5. Return result.
|
||||
@ -106,10 +106,10 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_delete(PropertyKey const& prop
|
||||
}
|
||||
|
||||
// 10.4.4.1 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-arguments-exotic-objects-getownproperty-p
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> ArgumentsObject::internal_get_own_property(PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> ArgumentsObject::internal_get_own_property(PropertyKey const& property_key) const
|
||||
{
|
||||
// 1. Let desc be OrdinaryGetOwnProperty(args, P).
|
||||
auto desc = MUST(Object::internal_get_own_property(property_name));
|
||||
auto desc = MUST(Object::internal_get_own_property(property_key));
|
||||
|
||||
// 2. If desc is undefined, return desc.
|
||||
if (!desc.has_value())
|
||||
@ -117,12 +117,12 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> ArgumentsObject::internal_get_ow
|
||||
|
||||
// 3. Let map be args.[[ParameterMap]].
|
||||
// 4. Let isMapped be ! HasOwnProperty(map, P).
|
||||
bool is_mapped = MUST(m_parameter_map->has_own_property(property_name));
|
||||
bool is_mapped = MUST(m_parameter_map->has_own_property(property_key));
|
||||
|
||||
// 5. If isMapped is true, then
|
||||
if (is_mapped) {
|
||||
// a. Set desc.[[Value]] to Get(map, P).
|
||||
desc->value = TRY(m_parameter_map->get(property_name));
|
||||
desc->value = TRY(m_parameter_map->get(property_key));
|
||||
}
|
||||
|
||||
// 6. Return desc.
|
||||
@ -130,13 +130,13 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> ArgumentsObject::internal_get_ow
|
||||
}
|
||||
|
||||
// 10.4.4.2 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-arguments-exotic-objects-defineownproperty-p-desc
|
||||
ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyKey const& property_name, PropertyDescriptor const& descriptor)
|
||||
ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& descriptor)
|
||||
{
|
||||
// 1. Let map be args.[[ParameterMap]].
|
||||
auto& map = parameter_map();
|
||||
|
||||
// 2. Let isMapped be HasOwnProperty(map, P).
|
||||
bool is_mapped = MUST(map.has_own_property(property_name));
|
||||
bool is_mapped = MUST(map.has_own_property(property_key));
|
||||
|
||||
// 3. Let newArgDesc be Desc.
|
||||
auto new_arg_desc = descriptor;
|
||||
@ -148,12 +148,12 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyKe
|
||||
// i. Set newArgDesc to a copy of Desc.
|
||||
new_arg_desc = descriptor;
|
||||
// ii. Set newArgDesc.[[Value]] to Get(map, P).
|
||||
new_arg_desc.value = TRY(map.get(property_name));
|
||||
new_arg_desc.value = TRY(map.get(property_key));
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Let allowed be ? OrdinaryDefineOwnProperty(args, P, newArgDesc).
|
||||
bool allowed = TRY(Object::internal_define_own_property(property_name, new_arg_desc));
|
||||
bool allowed = TRY(Object::internal_define_own_property(property_key, new_arg_desc));
|
||||
|
||||
// 6. If allowed is false, return false.
|
||||
if (!allowed)
|
||||
@ -164,12 +164,12 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyKe
|
||||
// a. If IsAccessorDescriptor(Desc) is true, then
|
||||
if (descriptor.is_accessor_descriptor()) {
|
||||
// i. Call map.[[Delete]](P).
|
||||
MUST(map.internal_delete(property_name));
|
||||
MUST(map.internal_delete(property_key));
|
||||
} else {
|
||||
// i. If Desc.[[Value]] is present, then
|
||||
if (descriptor.value.has_value()) {
|
||||
// 1. Let setStatus be Set(map, P, Desc.[[Value]], false).
|
||||
bool set_status = MUST(map.set(property_name, descriptor.value.value(), Object::ShouldThrowExceptions::No));
|
||||
bool set_status = MUST(map.set(property_key, descriptor.value.value(), Object::ShouldThrowExceptions::No));
|
||||
|
||||
// 2. Assert: setStatus is true because formal parameters mapped by argument objects are always writable.
|
||||
VERIFY(set_status);
|
||||
@ -177,7 +177,7 @@ ThrowCompletionOr<bool> ArgumentsObject::internal_define_own_property(PropertyKe
|
||||
// ii. If Desc.[[Writable]] is present and its value is false, then
|
||||
if (descriptor.writable == false) {
|
||||
// 1. Call map.[[Delete]](P).
|
||||
MUST(map.internal_delete(property_name));
|
||||
MUST(map.internal_delete(property_key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,31 +151,31 @@ ThrowCompletionOr<bool> Array::set_length(PropertyDescriptor const& property_des
|
||||
}
|
||||
|
||||
// NON-STANDARD: Used to return the value of the ephemeral length property
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> Array::internal_get_own_property(PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> Array::internal_get_own_property(PropertyKey const& property_key) const
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
if (property_name.is_string() && property_name.as_string() == vm.names.length.as_string())
|
||||
if (property_key.is_string() && property_key.as_string() == vm.names.length.as_string())
|
||||
return PropertyDescriptor { .value = Value(indexed_properties().array_like_size()), .writable = m_length_writable, .enumerable = false, .configurable = false };
|
||||
|
||||
return Object::internal_get_own_property(property_name);
|
||||
return Object::internal_get_own_property(property_key);
|
||||
}
|
||||
|
||||
// 10.4.2.1 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-array-exotic-objects-defineownproperty-p-desc
|
||||
ThrowCompletionOr<bool> Array::internal_define_own_property(PropertyKey const& property_name, PropertyDescriptor const& property_descriptor)
|
||||
ThrowCompletionOr<bool> Array::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. If P is "length", then
|
||||
if (property_name.is_string() && property_name.as_string() == vm.names.length.as_string()) {
|
||||
if (property_key.is_string() && property_key.as_string() == vm.names.length.as_string()) {
|
||||
// a. Return ? ArraySetLength(A, Desc).
|
||||
return set_length(property_descriptor);
|
||||
}
|
||||
|
||||
// 3. Else if P is an array index, then
|
||||
if (property_name.is_number()) {
|
||||
if (property_key.is_number()) {
|
||||
// a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
|
||||
// b. Assert: ! IsDataDescriptor(oldLenDesc) is true.
|
||||
// c. Assert: oldLenDesc.[[Configurable]] is false.
|
||||
@ -184,11 +184,11 @@ ThrowCompletionOr<bool> Array::internal_define_own_property(PropertyKey const& p
|
||||
// f. Let index be ! ToUint32(P).
|
||||
|
||||
// g. If index ≥ oldLen and oldLenDesc.[[Writable]] is false, return false.
|
||||
if (property_name.as_number() >= indexed_properties().array_like_size() && !m_length_writable)
|
||||
if (property_key.as_number() >= indexed_properties().array_like_size() && !m_length_writable)
|
||||
return false;
|
||||
|
||||
// h. Let succeeded be ! OrdinaryDefineOwnProperty(A, P, Desc).
|
||||
auto succeeded = MUST(Object::internal_define_own_property(property_name, property_descriptor));
|
||||
auto succeeded = MUST(Object::internal_define_own_property(property_key, property_descriptor));
|
||||
|
||||
// i. If succeeded is false, return false.
|
||||
if (!succeeded)
|
||||
@ -204,16 +204,16 @@ ThrowCompletionOr<bool> Array::internal_define_own_property(PropertyKey const& p
|
||||
}
|
||||
|
||||
// 4. Return OrdinaryDefineOwnProperty(A, P, Desc).
|
||||
return Object::internal_define_own_property(property_name, property_descriptor);
|
||||
return Object::internal_define_own_property(property_key, property_descriptor);
|
||||
}
|
||||
|
||||
// NON-STANDARD: Used to reject deletes to ephemeral (non-configurable) length property
|
||||
ThrowCompletionOr<bool> Array::internal_delete(PropertyKey const& property_name)
|
||||
ThrowCompletionOr<bool> Array::internal_delete(PropertyKey const& property_key)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
if (property_name.is_string() && property_name.as_string() == vm.names.length.as_string())
|
||||
if (property_key.is_string() && property_key.as_string() == vm.names.length.as_string())
|
||||
return false;
|
||||
return Object::internal_delete(property_name);
|
||||
return Object::internal_delete(property_key);
|
||||
}
|
||||
|
||||
// NON-STANDARD: Used to inject the ephemeral length property's key
|
||||
|
@ -173,10 +173,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::filter)
|
||||
// 7. Repeat, while k < len,
|
||||
for (; k < length; ++k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kPresent be ? HasProperty(O, Pk).
|
||||
auto k_present = TRY(object->has_property(property_name));
|
||||
auto k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// c. If kPresent is true, then
|
||||
if (k_present) {
|
||||
@ -223,15 +223,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::for_each)
|
||||
// 5. Repeat, while k < len,
|
||||
for (size_t k = 0; k < length; ++k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kPresent be ? HasProperty(O, Pk).
|
||||
auto k_present = TRY(object->has_property(property_name));
|
||||
auto k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// c. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// i. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// ii. Perform ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
|
||||
TRY(call(global_object, callback_function.as_function(), this_arg, k_value, Value(k), object));
|
||||
@ -267,21 +267,21 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::map)
|
||||
// 6. Repeat, while k < len,
|
||||
for (size_t k = 0; k < length; ++k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kPresent be ? HasProperty(O, Pk).
|
||||
auto k_present = TRY(object->has_property(property_name));
|
||||
auto k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// c. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// i. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// ii. Let mappedValue be ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »).
|
||||
auto mapped_value = TRY(call(global_object, callback_function.as_function(), this_arg, k_value, Value(k), object));
|
||||
|
||||
// iii. Perform ? CreateDataPropertyOrThrow(A, Pk, mappedValue).
|
||||
TRY(array->create_data_property_or_throw(property_name, mapped_value));
|
||||
TRY(array->create_data_property_or_throw(property_key, mapped_value));
|
||||
}
|
||||
|
||||
// d. Set k to k + 1.
|
||||
@ -640,15 +640,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::index_of)
|
||||
|
||||
// 10. Repeat, while k < len,
|
||||
for (; k < length; ++k) {
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// a. Let kPresent be ? HasProperty(O, ! ToString(𝔽(k))).
|
||||
auto k_present = TRY(object->has_property(property_name));
|
||||
auto k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// b. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// i. Let elementK be ? Get(O, ! ToString(𝔽(k))).
|
||||
auto element_k = TRY(object->get(property_name));
|
||||
auto element_k = TRY(object->get(property_key));
|
||||
|
||||
// ii. Let same be IsStrictlyEqual(searchElement, elementK).
|
||||
auto same = is_strictly_equal(search_element, element_k);
|
||||
@ -704,15 +704,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce)
|
||||
// b. Repeat, while kPresent is false and k < len,
|
||||
for (; !k_present && k < length; ++k) {
|
||||
// i. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// ii. Set kPresent to ? HasProperty(O, Pk).
|
||||
k_present = TRY(object->has_property(property_name));
|
||||
k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// iii. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// 1. Set accumulator to ? Get(O, Pk).
|
||||
accumulator = TRY(object->get(property_name));
|
||||
accumulator = TRY(object->get(property_key));
|
||||
}
|
||||
|
||||
// iv. Set k to k + 1.
|
||||
@ -726,15 +726,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce)
|
||||
// 9. Repeat, while k < len,
|
||||
for (; k < length; ++k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kPresent be ? HasProperty(O, Pk).
|
||||
auto k_present = TRY(object->has_property(property_name));
|
||||
auto k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// c. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// i. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »).
|
||||
accumulator = TRY(call(global_object, callback_function.as_function(), js_undefined(), accumulator, k_value, Value(k), object));
|
||||
@ -786,15 +786,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
|
||||
// b. Repeat, while kPresent is false and k ≥ 0,
|
||||
for (; !k_present && k >= 0; --k) {
|
||||
// i. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// ii. Set kPresent to ? HasProperty(O, Pk).
|
||||
k_present = TRY(object->has_property(property_name));
|
||||
k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// iii. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// 1. Set accumulator to ? Get(O, Pk).
|
||||
accumulator = TRY(object->get(property_name));
|
||||
accumulator = TRY(object->get(property_key));
|
||||
}
|
||||
|
||||
// iv. Set k to k - 1.
|
||||
@ -808,15 +808,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::reduce_right)
|
||||
// 9. Repeat, while k ≥ 0,
|
||||
for (; k >= 0; --k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kPresent be ? HasProperty(O, Pk).
|
||||
auto k_present = TRY(object->has_property(property_name));
|
||||
auto k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// c. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// i. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// ii. Set accumulator to ? Call(callbackfn, undefined, « accumulator, kValue, 𝔽(k), O »).
|
||||
accumulator = TRY(call(global_object, callback_function.as_function(), js_undefined(), accumulator, k_value, Value((size_t)k), object));
|
||||
@ -1044,15 +1044,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::last_index_of)
|
||||
|
||||
// 8. Repeat, while k ≥ 0,
|
||||
for (; k >= 0; --k) {
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// a. Let kPresent be ? HasProperty(O, ! ToString(𝔽(k))).
|
||||
auto k_present = TRY(object->has_property(property_name));
|
||||
auto k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// b. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// i. Let elementK be ? Get(O, ! ToString(𝔽(k))).
|
||||
auto element_k = TRY(object->get(property_name));
|
||||
auto element_k = TRY(object->get(property_key));
|
||||
|
||||
// ii. Let same be IsStrictlyEqual(searchElement, elementK).
|
||||
auto same = is_strictly_equal(search_element, element_k);
|
||||
@ -1120,10 +1120,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find)
|
||||
// 5. Repeat, while k < len,
|
||||
for (size_t k = 0; k < length; ++k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
|
||||
auto test_result = TRY(call(global_object, predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
|
||||
@ -1159,10 +1159,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_index)
|
||||
// 5. Repeat, while k < len,
|
||||
for (size_t k = 0; k < length; ++k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
|
||||
auto test_result = TRY(call(global_object, predicate.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
|
||||
@ -1198,10 +1198,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last)
|
||||
// 5. Repeat, while k ≥ 0,
|
||||
for (i64 k = static_cast<i64>(length) - 1; k >= 0; --k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
|
||||
auto test_result = TRY(call(global_object, predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean();
|
||||
@ -1237,10 +1237,10 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::find_last_index)
|
||||
// 5. Repeat, while k ≥ 0,
|
||||
for (i64 k = static_cast<i64>(length) - 1; k >= 0; --k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, 𝔽(k), O »)).
|
||||
auto test_result = TRY(call(global_object, predicate.as_function(), this_arg, k_value, Value((double)k), object)).to_boolean();
|
||||
@ -1276,15 +1276,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::some)
|
||||
// 5. Repeat, while k < len,
|
||||
for (size_t k = 0; k < length; ++k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kPresent be ? HasProperty(O, Pk).
|
||||
auto k_present = TRY(object->has_property(property_name));
|
||||
auto k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// c. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// i. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
|
||||
auto test_result = TRY(call(global_object, callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
|
||||
@ -1321,15 +1321,15 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::every)
|
||||
// 5. Repeat, while k < len,
|
||||
for (size_t k = 0; k < length; ++k) {
|
||||
// a. Let Pk be ! ToString(𝔽(k)).
|
||||
auto property_name = PropertyKey { k };
|
||||
auto property_key = PropertyKey { k };
|
||||
|
||||
// b. Let kPresent be ? HasProperty(O, Pk).
|
||||
auto k_present = TRY(object->has_property(property_name));
|
||||
auto k_present = TRY(object->has_property(property_key));
|
||||
|
||||
// c. If kPresent is true, then
|
||||
if (k_present) {
|
||||
// i. Let kValue be ? Get(O, Pk).
|
||||
auto k_value = TRY(object->get(property_name));
|
||||
auto k_value = TRY(object->get(property_key));
|
||||
|
||||
// ii. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »)).
|
||||
auto test_result = TRY(call(global_object, callback_function.as_function(), this_arg, k_value, Value(k), object)).to_boolean();
|
||||
|
@ -297,8 +297,8 @@ void ECMAScriptFunctionObject::visit_edges(Visitor& visitor)
|
||||
visitor.visit(m_home_object);
|
||||
|
||||
for (auto& field : m_fields) {
|
||||
if (auto* property_name_ptr = field.name.get_pointer<PropertyKey>(); property_name_ptr && property_name_ptr->is_symbol())
|
||||
visitor.visit(property_name_ptr->as_symbol());
|
||||
if (auto* property_key_ptr = field.name.get_pointer<PropertyKey>(); property_key_ptr && property_key_ptr->is_symbol())
|
||||
visitor.visit(property_key_ptr->as_symbol());
|
||||
|
||||
visitor.visit(field.initializer);
|
||||
}
|
||||
|
@ -143,22 +143,22 @@ private:
|
||||
};
|
||||
|
||||
template<typename ConstructorType>
|
||||
inline void GlobalObject::initialize_constructor(PropertyKey const& property_name, ConstructorType*& constructor, Object* prototype)
|
||||
inline void GlobalObject::initialize_constructor(PropertyKey const& property_key, ConstructorType*& constructor, Object* prototype)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
constructor = heap().allocate<ConstructorType>(*this, *this);
|
||||
constructor->define_direct_property(vm.names.name, js_string(heap(), property_name.as_string()), Attribute::Configurable);
|
||||
constructor->define_direct_property(vm.names.name, js_string(heap(), property_key.as_string()), Attribute::Configurable);
|
||||
if (prototype)
|
||||
prototype->define_direct_property(vm.names.constructor, constructor, Attribute::Writable | Attribute::Configurable);
|
||||
}
|
||||
|
||||
template<typename ConstructorType>
|
||||
inline void GlobalObject::add_constructor(PropertyKey const& property_name, ConstructorType*& constructor, Object* prototype)
|
||||
inline void GlobalObject::add_constructor(PropertyKey const& property_key, ConstructorType*& constructor, Object* prototype)
|
||||
{
|
||||
// Some constructors are pre-initialized separately.
|
||||
if (!constructor)
|
||||
initialize_constructor(property_name, constructor, prototype);
|
||||
define_direct_property(property_name, constructor, Attribute::Writable | Attribute::Configurable);
|
||||
initialize_constructor(property_key, constructor, prototype);
|
||||
define_direct_property(property_key, constructor, Attribute::Writable | Attribute::Configurable);
|
||||
}
|
||||
|
||||
inline GlobalObject* Shape::global_object() const
|
||||
@ -170,15 +170,15 @@ template<>
|
||||
inline bool Object::fast_is<GlobalObject>() const { return is_global_object(); }
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> Value::invoke(GlobalObject& global_object, PropertyKey const& property_name, Args... args)
|
||||
[[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> Value::invoke(GlobalObject& global_object, PropertyKey const& property_key, Args... args)
|
||||
{
|
||||
if constexpr (sizeof...(Args) > 0) {
|
||||
MarkedValueList arglist { global_object.vm().heap() };
|
||||
(..., arglist.append(move(args)));
|
||||
return invoke_internal(global_object, property_name, move(arglist));
|
||||
return invoke_internal(global_object, property_key, move(arglist));
|
||||
}
|
||||
|
||||
return invoke_internal(global_object, property_name, Optional<MarkedValueList> {});
|
||||
return invoke_internal(global_object, property_key, Optional<MarkedValueList> {});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -427,8 +427,8 @@ ThrowCompletionOr<Value> JSONObject::internalize_json_property(GlobalObject& glo
|
||||
TRY(process_property(i));
|
||||
} else {
|
||||
auto property_list = TRY(value_object.enumerable_own_property_names(Object::PropertyKind::Key));
|
||||
for (auto& property_name : property_list)
|
||||
TRY(process_property(property_name.as_string().string()));
|
||||
for (auto& property_key : property_list)
|
||||
TRY(process_property(property_key.as_string().string()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,21 +77,21 @@ ThrowCompletionOr<bool> Object::is_extensible() const
|
||||
// 7.3 Operations on Objects, https://tc39.es/ecma262/#sec-operations-on-objects
|
||||
|
||||
// 7.3.2 Get ( O, P ), https://tc39.es/ecma262/#sec-get-o-p
|
||||
ThrowCompletionOr<Value> Object::get(PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<Value> Object::get(PropertyKey const& property_key) const
|
||||
{
|
||||
// 1. Assert: Type(O) is Object.
|
||||
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. Return ? O.[[Get]](P, O).
|
||||
return TRY(internal_get(property_name, this));
|
||||
return TRY(internal_get(property_key, this));
|
||||
}
|
||||
|
||||
// NOTE: 7.3.3 GetV ( V, P ) is implemented as Value::get().
|
||||
|
||||
// 7.3.4 Set ( O, P, V, Throw ), https://tc39.es/ecma262/#sec-set-o-p-v-throw
|
||||
ThrowCompletionOr<bool> Object::set(PropertyKey const& property_name, Value value, ShouldThrowExceptions throw_exceptions)
|
||||
ThrowCompletionOr<bool> Object::set(PropertyKey const& property_key, Value value, ShouldThrowExceptions throw_exceptions)
|
||||
{
|
||||
VERIFY(!value.is_empty());
|
||||
auto& vm = this->vm();
|
||||
@ -99,12 +99,12 @@ ThrowCompletionOr<bool> Object::set(PropertyKey const& property_name, Value valu
|
||||
// 1. Assert: Type(O) is Object.
|
||||
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. Assert: Type(Throw) is Boolean.
|
||||
|
||||
// 4. Let success be ? O.[[Set]](P, V, O).
|
||||
auto success = TRY(internal_set(property_name, value, this));
|
||||
auto success = TRY(internal_set(property_key, value, this));
|
||||
|
||||
// 5. If success is false and Throw is true, throw a TypeError exception.
|
||||
if (!success && throw_exceptions == ShouldThrowExceptions::Yes) {
|
||||
@ -117,12 +117,12 @@ ThrowCompletionOr<bool> Object::set(PropertyKey const& property_name, Value valu
|
||||
}
|
||||
|
||||
// 7.3.5 CreateDataProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createdataproperty
|
||||
ThrowCompletionOr<bool> Object::create_data_property(PropertyKey const& property_name, Value value)
|
||||
ThrowCompletionOr<bool> Object::create_data_property(PropertyKey const& property_key, Value value)
|
||||
{
|
||||
// 1. Assert: Type(O) is Object.
|
||||
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
|
||||
auto new_descriptor = PropertyDescriptor {
|
||||
@ -133,18 +133,18 @@ ThrowCompletionOr<bool> Object::create_data_property(PropertyKey const& property
|
||||
};
|
||||
|
||||
// 4. Return ? O.[[DefineOwnProperty]](P, newDesc).
|
||||
return internal_define_own_property(property_name, new_descriptor);
|
||||
return internal_define_own_property(property_key, new_descriptor);
|
||||
}
|
||||
|
||||
// 7.3.6 CreateMethodProperty ( O, P, V ), https://tc39.es/ecma262/#sec-createmethodproperty
|
||||
ThrowCompletionOr<bool> Object::create_method_property(PropertyKey const& property_name, Value value)
|
||||
ThrowCompletionOr<bool> Object::create_method_property(PropertyKey const& property_key, Value value)
|
||||
{
|
||||
VERIFY(!value.is_empty());
|
||||
|
||||
// 1. Assert: Type(O) is Object.
|
||||
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
|
||||
auto new_descriptor = PropertyDescriptor {
|
||||
@ -155,11 +155,11 @@ ThrowCompletionOr<bool> Object::create_method_property(PropertyKey const& proper
|
||||
};
|
||||
|
||||
// 4. Return ? O.[[DefineOwnProperty]](P, newDesc).
|
||||
return internal_define_own_property(property_name, new_descriptor);
|
||||
return internal_define_own_property(property_key, new_descriptor);
|
||||
}
|
||||
|
||||
// 7.3.7 CreateDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createdatapropertyorthrow
|
||||
ThrowCompletionOr<bool> Object::create_data_property_or_throw(PropertyKey const& property_name, Value value)
|
||||
ThrowCompletionOr<bool> Object::create_data_property_or_throw(PropertyKey const& property_key, Value value)
|
||||
{
|
||||
VERIFY(!value.is_empty());
|
||||
auto& vm = this->vm();
|
||||
@ -167,10 +167,10 @@ ThrowCompletionOr<bool> Object::create_data_property_or_throw(PropertyKey const&
|
||||
// 1. Assert: Type(O) is Object.
|
||||
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. Let success be ? CreateDataProperty(O, P, V).
|
||||
auto success = TRY(create_data_property(property_name, value));
|
||||
auto success = TRY(create_data_property(property_key, value));
|
||||
|
||||
// 4. If success is false, throw a TypeError exception.
|
||||
if (!success) {
|
||||
@ -183,30 +183,30 @@ ThrowCompletionOr<bool> Object::create_data_property_or_throw(PropertyKey const&
|
||||
}
|
||||
|
||||
// 7.3.8 CreateNonEnumerableDataPropertyOrThrow ( O, P, V ), https://tc39.es/ecma262/#sec-createnonenumerabledatapropertyorthrow
|
||||
ThrowCompletionOr<bool> Object::create_non_enumerable_data_property_or_throw(PropertyKey const& property_name, Value value)
|
||||
ThrowCompletionOr<bool> Object::create_non_enumerable_data_property_or_throw(PropertyKey const& property_key, Value value)
|
||||
{
|
||||
VERIFY(!value.is_empty());
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 1. Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
|
||||
auto new_description = PropertyDescriptor { .value = value, .writable = true, .enumerable = false, .configurable = true };
|
||||
|
||||
// 2. Return ? DefinePropertyOrThrow(O, P, newDesc).
|
||||
return define_property_or_throw(property_name, new_description);
|
||||
return define_property_or_throw(property_key, new_description);
|
||||
}
|
||||
|
||||
// 7.3.9 DefinePropertyOrThrow ( O, P, desc ), https://tc39.es/ecma262/#sec-definepropertyorthrow
|
||||
ThrowCompletionOr<bool> Object::define_property_or_throw(PropertyKey const& property_name, PropertyDescriptor const& property_descriptor)
|
||||
ThrowCompletionOr<bool> Object::define_property_or_throw(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. Assert: Type(O) is Object.
|
||||
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. Let success be ? O.[[DefineOwnProperty]](P, desc).
|
||||
auto success = TRY(internal_define_own_property(property_name, property_descriptor));
|
||||
auto success = TRY(internal_define_own_property(property_key, property_descriptor));
|
||||
|
||||
// 4. If success is false, throw a TypeError exception.
|
||||
if (!success) {
|
||||
@ -219,17 +219,17 @@ ThrowCompletionOr<bool> Object::define_property_or_throw(PropertyKey const& prop
|
||||
}
|
||||
|
||||
// 7.3.10 DeletePropertyOrThrow ( O, P ), https://tc39.es/ecma262/#sec-deletepropertyorthrow
|
||||
ThrowCompletionOr<bool> Object::delete_property_or_throw(PropertyKey const& property_name)
|
||||
ThrowCompletionOr<bool> Object::delete_property_or_throw(PropertyKey const& property_key)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
|
||||
// 1. Assert: Type(O) is Object.
|
||||
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. Let success be ? O.[[Delete]](P).
|
||||
auto success = TRY(internal_delete(property_name));
|
||||
auto success = TRY(internal_delete(property_key));
|
||||
|
||||
// 4. If success is false, throw a TypeError exception.
|
||||
if (!success) {
|
||||
@ -242,27 +242,27 @@ ThrowCompletionOr<bool> Object::delete_property_or_throw(PropertyKey const& prop
|
||||
}
|
||||
|
||||
// 7.3.12 HasProperty ( O, P ), https://tc39.es/ecma262/#sec-hasproperty
|
||||
ThrowCompletionOr<bool> Object::has_property(PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<bool> Object::has_property(PropertyKey const& property_key) const
|
||||
{
|
||||
// 1. Assert: Type(O) is Object.
|
||||
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. Return ? O.[[HasProperty]](P).
|
||||
return internal_has_property(property_name);
|
||||
return internal_has_property(property_key);
|
||||
}
|
||||
|
||||
// 7.3.13 HasOwnProperty ( O, P ), https://tc39.es/ecma262/#sec-hasownproperty
|
||||
ThrowCompletionOr<bool> Object::has_own_property(PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<bool> Object::has_own_property(PropertyKey const& property_key) const
|
||||
{
|
||||
// 1. Assert: Type(O) is Object.
|
||||
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. Let desc be ? O.[[GetOwnProperty]](P).
|
||||
auto descriptor = TRY(internal_get_own_property(property_name));
|
||||
auto descriptor = TRY(internal_get_own_property(property_key));
|
||||
|
||||
// 4. If desc is undefined, return false.
|
||||
if (!descriptor.has_value())
|
||||
@ -296,10 +296,10 @@ ThrowCompletionOr<bool> Object::set_integrity_level(IntegrityLevel level)
|
||||
if (level == IntegrityLevel::Sealed) {
|
||||
// a. For each element k of keys, do
|
||||
for (auto& key : keys) {
|
||||
auto property_name = MUST(PropertyKey::from_value(global_object, key));
|
||||
auto property_key = MUST(PropertyKey::from_value(global_object, key));
|
||||
|
||||
// i. Perform ? DefinePropertyOrThrow(O, k, PropertyDescriptor { [[Configurable]]: false }).
|
||||
TRY(define_property_or_throw(property_name, { .configurable = false }));
|
||||
TRY(define_property_or_throw(property_key, { .configurable = false }));
|
||||
}
|
||||
}
|
||||
// 7. Else,
|
||||
@ -308,10 +308,10 @@ ThrowCompletionOr<bool> Object::set_integrity_level(IntegrityLevel level)
|
||||
|
||||
// b. For each element k of keys, do
|
||||
for (auto& key : keys) {
|
||||
auto property_name = MUST(PropertyKey::from_value(global_object, key));
|
||||
auto property_key = MUST(PropertyKey::from_value(global_object, key));
|
||||
|
||||
// i. Let currentDesc be ? O.[[GetOwnProperty]](k).
|
||||
auto current_descriptor = TRY(internal_get_own_property(property_name));
|
||||
auto current_descriptor = TRY(internal_get_own_property(property_key));
|
||||
|
||||
// ii. If currentDesc is not undefined, then
|
||||
if (!current_descriptor.has_value())
|
||||
@ -331,7 +331,7 @@ ThrowCompletionOr<bool> Object::set_integrity_level(IntegrityLevel level)
|
||||
}
|
||||
|
||||
// 3. Perform ? DefinePropertyOrThrow(O, k, desc).
|
||||
TRY(define_property_or_throw(property_name, descriptor));
|
||||
TRY(define_property_or_throw(property_key, descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
@ -360,10 +360,10 @@ ThrowCompletionOr<bool> Object::test_integrity_level(IntegrityLevel level) const
|
||||
|
||||
// 7. For each element k of keys, do
|
||||
for (auto& key : keys) {
|
||||
auto property_name = MUST(PropertyKey::from_value(global_object(), key));
|
||||
auto property_key = MUST(PropertyKey::from_value(global_object(), key));
|
||||
|
||||
// a. Let currentDesc be ? O.[[GetOwnProperty]](k).
|
||||
auto current_descriptor = TRY(internal_get_own_property(property_name));
|
||||
auto current_descriptor = TRY(internal_get_own_property(property_key));
|
||||
|
||||
// b. If currentDesc is not undefined, then
|
||||
if (!current_descriptor.has_value())
|
||||
@ -405,10 +405,10 @@ ThrowCompletionOr<MarkedValueList> Object::enumerable_own_property_names(Propert
|
||||
// a. If Type(key) is String, then
|
||||
if (!key.is_string())
|
||||
continue;
|
||||
auto property_name = MUST(PropertyKey::from_value(global_object, key));
|
||||
auto property_key = MUST(PropertyKey::from_value(global_object, key));
|
||||
|
||||
// i. Let desc be ? O.[[GetOwnProperty]](key).
|
||||
auto descriptor = TRY(internal_get_own_property(property_name));
|
||||
auto descriptor = TRY(internal_get_own_property(property_key));
|
||||
|
||||
// ii. If desc is not undefined and desc.[[Enumerable]] is true, then
|
||||
if (descriptor.has_value() && *descriptor->enumerable) {
|
||||
@ -420,7 +420,7 @@ ThrowCompletionOr<MarkedValueList> Object::enumerable_own_property_names(Propert
|
||||
// 2. Else,
|
||||
|
||||
// a. Let value be ? Get(O, key).
|
||||
auto value = TRY(get(property_name));
|
||||
auto value = TRY(get(property_key));
|
||||
|
||||
// b. If kind is value, append value to properties.
|
||||
if (kind == PropertyKind::Value) {
|
||||
@ -560,8 +560,8 @@ ThrowCompletionOr<void> Object::define_field(Variant<PropertyKey, PrivateName> n
|
||||
if (initializer)
|
||||
init_value = TRY(call(global_object(), *initializer, this));
|
||||
|
||||
if (auto* property_name_ptr = name.get_pointer<PropertyKey>())
|
||||
TRY(create_data_property_or_throw(*property_name_ptr, init_value));
|
||||
if (auto* property_key_ptr = name.get_pointer<PropertyKey>())
|
||||
TRY(create_data_property_or_throw(*property_key_ptr, init_value));
|
||||
else
|
||||
TRY(private_field_add(name.get<PrivateName>(), init_value));
|
||||
|
||||
@ -641,13 +641,13 @@ ThrowCompletionOr<bool> Object::internal_prevent_extensions()
|
||||
}
|
||||
|
||||
// 10.1.5 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> Object::internal_get_own_property(PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> Object::internal_get_own_property(PropertyKey const& property_key) const
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. If O does not have an own property with key P, return undefined.
|
||||
auto maybe_storage_entry = storage_get(property_name);
|
||||
auto maybe_storage_entry = storage_get(property_key);
|
||||
if (!maybe_storage_entry.has_value())
|
||||
return Optional<PropertyDescriptor> {};
|
||||
|
||||
@ -687,27 +687,27 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> Object::internal_get_own_propert
|
||||
}
|
||||
|
||||
// 10.1.6 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-defineownproperty-p-desc
|
||||
ThrowCompletionOr<bool> Object::internal_define_own_property(PropertyKey const& property_name, PropertyDescriptor const& property_descriptor)
|
||||
ThrowCompletionOr<bool> Object::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
|
||||
{
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
// 1. Let current be ? O.[[GetOwnProperty]](P).
|
||||
auto current = TRY(internal_get_own_property(property_name));
|
||||
auto current = TRY(internal_get_own_property(property_key));
|
||||
|
||||
// 2. Let extensible be ? IsExtensible(O).
|
||||
auto extensible = TRY(is_extensible());
|
||||
|
||||
// 3. Return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current).
|
||||
return validate_and_apply_property_descriptor(this, property_name, extensible, property_descriptor, current);
|
||||
return validate_and_apply_property_descriptor(this, property_key, extensible, property_descriptor, current);
|
||||
}
|
||||
|
||||
// 10.1.7 [[HasProperty]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p
|
||||
ThrowCompletionOr<bool> Object::internal_has_property(PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<bool> Object::internal_has_property(PropertyKey const& property_key) const
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let hasOwn be ? O.[[GetOwnProperty]](P).
|
||||
auto has_own = TRY(internal_get_own_property(property_name));
|
||||
auto has_own = TRY(internal_get_own_property(property_key));
|
||||
|
||||
// 3. If hasOwn is not undefined, return true.
|
||||
if (has_own.has_value())
|
||||
@ -719,7 +719,7 @@ ThrowCompletionOr<bool> Object::internal_has_property(PropertyKey const& propert
|
||||
// 5. If parent is not null, then
|
||||
if (parent) {
|
||||
// a. Return ? parent.[[HasProperty]](P).
|
||||
return parent->internal_has_property(property_name);
|
||||
return parent->internal_has_property(property_key);
|
||||
}
|
||||
|
||||
// 6. Return false.
|
||||
@ -727,15 +727,15 @@ ThrowCompletionOr<bool> Object::internal_has_property(PropertyKey const& propert
|
||||
}
|
||||
|
||||
// 10.1.8 [[Get]] ( P, Receiver ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-get-p-receiver
|
||||
ThrowCompletionOr<Value> Object::internal_get(PropertyKey const& property_name, Value receiver) const
|
||||
ThrowCompletionOr<Value> Object::internal_get(PropertyKey const& property_key, Value receiver) const
|
||||
{
|
||||
VERIFY(!receiver.is_empty());
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let desc be ? O.[[GetOwnProperty]](P).
|
||||
auto descriptor = TRY(internal_get_own_property(property_name));
|
||||
auto descriptor = TRY(internal_get_own_property(property_key));
|
||||
|
||||
// 3. If desc is undefined, then
|
||||
if (!descriptor.has_value()) {
|
||||
@ -747,7 +747,7 @@ ThrowCompletionOr<Value> Object::internal_get(PropertyKey const& property_name,
|
||||
return js_undefined();
|
||||
|
||||
// c. Return ? parent.[[Get]](P, Receiver).
|
||||
return parent->internal_get(property_name, receiver);
|
||||
return parent->internal_get(property_key, receiver);
|
||||
}
|
||||
|
||||
// 4. If IsDataDescriptor(desc) is true, return desc.[[Value]].
|
||||
@ -769,26 +769,26 @@ ThrowCompletionOr<Value> Object::internal_get(PropertyKey const& property_name,
|
||||
}
|
||||
|
||||
// 10.1.9 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver
|
||||
ThrowCompletionOr<bool> Object::internal_set(PropertyKey const& property_name, Value value, Value receiver)
|
||||
ThrowCompletionOr<bool> Object::internal_set(PropertyKey const& property_key, Value value, Value receiver)
|
||||
{
|
||||
VERIFY(!value.is_empty());
|
||||
VERIFY(!receiver.is_empty());
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let ownDesc be ? O.[[GetOwnProperty]](P).
|
||||
auto own_descriptor = TRY(internal_get_own_property(property_name));
|
||||
auto own_descriptor = TRY(internal_get_own_property(property_key));
|
||||
|
||||
// 3. Return OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc).
|
||||
return ordinary_set_with_own_descriptor(property_name, value, receiver, own_descriptor);
|
||||
return ordinary_set_with_own_descriptor(property_key, value, receiver, own_descriptor);
|
||||
}
|
||||
|
||||
// 10.1.9.2 OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc ), https://tc39.es/ecma262/#sec-ordinarysetwithowndescriptor
|
||||
ThrowCompletionOr<bool> Object::ordinary_set_with_own_descriptor(PropertyKey const& property_name, Value value, Value receiver, Optional<PropertyDescriptor> own_descriptor)
|
||||
ThrowCompletionOr<bool> Object::ordinary_set_with_own_descriptor(PropertyKey const& property_key, Value value, Value receiver, Optional<PropertyDescriptor> own_descriptor)
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. If ownDesc is undefined, then
|
||||
if (!own_descriptor.has_value()) {
|
||||
@ -798,7 +798,7 @@ ThrowCompletionOr<bool> Object::ordinary_set_with_own_descriptor(PropertyKey con
|
||||
// b. If parent is not null, then
|
||||
if (parent) {
|
||||
// i. Return ? parent.[[Set]](P, V, Receiver).
|
||||
return TRY(parent->internal_set(property_name, value, receiver));
|
||||
return TRY(parent->internal_set(property_key, value, receiver));
|
||||
}
|
||||
// c. Else,
|
||||
else {
|
||||
@ -823,7 +823,7 @@ ThrowCompletionOr<bool> Object::ordinary_set_with_own_descriptor(PropertyKey con
|
||||
return false;
|
||||
|
||||
// c. Let existingDescriptor be ? Receiver.[[GetOwnProperty]](P).
|
||||
auto existing_descriptor = TRY(receiver.as_object().internal_get_own_property(property_name));
|
||||
auto existing_descriptor = TRY(receiver.as_object().internal_get_own_property(property_key));
|
||||
|
||||
// d. If existingDescriptor is not undefined, then
|
||||
if (existing_descriptor.has_value()) {
|
||||
@ -839,15 +839,15 @@ ThrowCompletionOr<bool> Object::ordinary_set_with_own_descriptor(PropertyKey con
|
||||
auto value_descriptor = PropertyDescriptor { .value = value };
|
||||
|
||||
// iv. Return ? Receiver.[[DefineOwnProperty]](P, valueDesc).
|
||||
return TRY(receiver.as_object().internal_define_own_property(property_name, value_descriptor));
|
||||
return TRY(receiver.as_object().internal_define_own_property(property_key, value_descriptor));
|
||||
}
|
||||
// e. Else,
|
||||
else {
|
||||
// i. Assert: Receiver does not currently have a property P.
|
||||
VERIFY(!receiver.as_object().storage_has(property_name));
|
||||
VERIFY(!receiver.as_object().storage_has(property_key));
|
||||
|
||||
// ii. Return ? CreateDataProperty(Receiver, P, V).
|
||||
return TRY(receiver.as_object().create_data_property(property_name, value));
|
||||
return TRY(receiver.as_object().create_data_property(property_key, value));
|
||||
}
|
||||
}
|
||||
|
||||
@ -869,13 +869,13 @@ ThrowCompletionOr<bool> Object::ordinary_set_with_own_descriptor(PropertyKey con
|
||||
}
|
||||
|
||||
// 10.1.10 [[Delete]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-delete-p
|
||||
ThrowCompletionOr<bool> Object::internal_delete(PropertyKey const& property_name)
|
||||
ThrowCompletionOr<bool> Object::internal_delete(PropertyKey const& property_key)
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let desc be ? O.[[GetOwnProperty]](P).
|
||||
auto descriptor = TRY(internal_get_own_property(property_name));
|
||||
auto descriptor = TRY(internal_get_own_property(property_key));
|
||||
|
||||
// 3. If desc is undefined, return true.
|
||||
if (!descriptor.has_value())
|
||||
@ -884,7 +884,7 @@ ThrowCompletionOr<bool> Object::internal_delete(PropertyKey const& property_name
|
||||
// 4. If desc.[[Configurable]] is true, then
|
||||
if (*descriptor->configurable) {
|
||||
// a. Remove the own property with name P from O.
|
||||
storage_delete(property_name);
|
||||
storage_delete(property_key);
|
||||
|
||||
// b. Return true.
|
||||
return true;
|
||||
@ -944,21 +944,21 @@ ThrowCompletionOr<bool> Object::set_immutable_prototype(Object* prototype)
|
||||
return false;
|
||||
}
|
||||
|
||||
Optional<ValueAndAttributes> Object::storage_get(PropertyKey const& property_name) const
|
||||
Optional<ValueAndAttributes> Object::storage_get(PropertyKey const& property_key) const
|
||||
{
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
Value value;
|
||||
PropertyAttributes attributes;
|
||||
|
||||
if (property_name.is_number()) {
|
||||
auto value_and_attributes = m_indexed_properties.get(property_name.as_number());
|
||||
if (property_key.is_number()) {
|
||||
auto value_and_attributes = m_indexed_properties.get(property_key.as_number());
|
||||
if (!value_and_attributes.has_value())
|
||||
return {};
|
||||
value = value_and_attributes->value;
|
||||
attributes = value_and_attributes->attributes;
|
||||
} else {
|
||||
auto metadata = shape().lookup(property_name.to_string_or_symbol());
|
||||
auto metadata = shape().lookup(property_key.to_string_or_symbol());
|
||||
if (!metadata.has_value())
|
||||
return {};
|
||||
value = m_storage[metadata->offset];
|
||||
@ -967,28 +967,28 @@ Optional<ValueAndAttributes> Object::storage_get(PropertyKey const& property_nam
|
||||
return ValueAndAttributes { .value = value, .attributes = attributes };
|
||||
}
|
||||
|
||||
bool Object::storage_has(PropertyKey const& property_name) const
|
||||
bool Object::storage_has(PropertyKey const& property_key) const
|
||||
{
|
||||
VERIFY(property_name.is_valid());
|
||||
if (property_name.is_number())
|
||||
return m_indexed_properties.has_index(property_name.as_number());
|
||||
return shape().lookup(property_name.to_string_or_symbol()).has_value();
|
||||
VERIFY(property_key.is_valid());
|
||||
if (property_key.is_number())
|
||||
return m_indexed_properties.has_index(property_key.as_number());
|
||||
return shape().lookup(property_key.to_string_or_symbol()).has_value();
|
||||
}
|
||||
|
||||
void Object::storage_set(PropertyKey const& property_name, ValueAndAttributes const& value_and_attributes)
|
||||
void Object::storage_set(PropertyKey const& property_key, ValueAndAttributes const& value_and_attributes)
|
||||
{
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
auto [value, attributes] = value_and_attributes;
|
||||
|
||||
if (property_name.is_number()) {
|
||||
auto index = property_name.as_number();
|
||||
if (property_key.is_number()) {
|
||||
auto index = property_key.as_number();
|
||||
m_indexed_properties.put(index, value, attributes);
|
||||
return;
|
||||
}
|
||||
|
||||
auto property_name_string_or_symbol = property_name.to_string_or_symbol();
|
||||
auto metadata = shape().lookup(property_name_string_or_symbol);
|
||||
auto property_key_string_or_symbol = property_key.to_string_or_symbol();
|
||||
auto metadata = shape().lookup(property_key_string_or_symbol);
|
||||
|
||||
if (!metadata.has_value()) {
|
||||
if (!m_shape->is_unique() && shape().property_count() > 100) {
|
||||
@ -998,9 +998,9 @@ void Object::storage_set(PropertyKey const& property_name, ValueAndAttributes co
|
||||
}
|
||||
|
||||
if (m_shape->is_unique())
|
||||
m_shape->add_property_to_unique_shape(property_name_string_or_symbol, attributes);
|
||||
m_shape->add_property_to_unique_shape(property_key_string_or_symbol, attributes);
|
||||
else
|
||||
set_shape(*m_shape->create_put_transition(property_name_string_or_symbol, attributes));
|
||||
set_shape(*m_shape->create_put_transition(property_key_string_or_symbol, attributes));
|
||||
|
||||
m_storage.append(value);
|
||||
return;
|
||||
@ -1008,28 +1008,28 @@ void Object::storage_set(PropertyKey const& property_name, ValueAndAttributes co
|
||||
|
||||
if (attributes != metadata->attributes) {
|
||||
if (m_shape->is_unique())
|
||||
m_shape->reconfigure_property_in_unique_shape(property_name_string_or_symbol, attributes);
|
||||
m_shape->reconfigure_property_in_unique_shape(property_key_string_or_symbol, attributes);
|
||||
else
|
||||
set_shape(*m_shape->create_configure_transition(property_name_string_or_symbol, attributes));
|
||||
set_shape(*m_shape->create_configure_transition(property_key_string_or_symbol, attributes));
|
||||
}
|
||||
|
||||
m_storage[metadata->offset] = value;
|
||||
}
|
||||
|
||||
void Object::storage_delete(PropertyKey const& property_name)
|
||||
void Object::storage_delete(PropertyKey const& property_key)
|
||||
{
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(storage_has(property_name));
|
||||
VERIFY(property_key.is_valid());
|
||||
VERIFY(storage_has(property_key));
|
||||
|
||||
if (property_name.is_number())
|
||||
return m_indexed_properties.remove(property_name.as_number());
|
||||
if (property_key.is_number())
|
||||
return m_indexed_properties.remove(property_key.as_number());
|
||||
|
||||
auto metadata = shape().lookup(property_name.to_string_or_symbol());
|
||||
auto metadata = shape().lookup(property_key.to_string_or_symbol());
|
||||
VERIFY(metadata.has_value());
|
||||
|
||||
ensure_shape_is_unique();
|
||||
|
||||
shape().remove_property_from_unique_shape(property_name.to_string_or_symbol(), metadata->offset);
|
||||
shape().remove_property_from_unique_shape(property_key.to_string_or_symbol(), metadata->offset);
|
||||
m_storage.remove(metadata->offset);
|
||||
}
|
||||
|
||||
@ -1044,43 +1044,43 @@ void Object::set_prototype(Object* new_prototype)
|
||||
m_shape = shape.create_prototype_transition(new_prototype);
|
||||
}
|
||||
|
||||
void Object::define_native_accessor(PropertyKey const& property_name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> getter, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> setter, PropertyAttributes attribute)
|
||||
void Object::define_native_accessor(PropertyKey const& property_key, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> getter, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> setter, PropertyAttributes attribute)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
String formatted_property_name;
|
||||
if (property_name.is_number()) {
|
||||
formatted_property_name = property_name.to_string();
|
||||
} else if (property_name.is_string()) {
|
||||
formatted_property_name = property_name.as_string();
|
||||
String formatted_property_key;
|
||||
if (property_key.is_number()) {
|
||||
formatted_property_key = property_key.to_string();
|
||||
} else if (property_key.is_string()) {
|
||||
formatted_property_key = property_key.as_string();
|
||||
} else {
|
||||
formatted_property_name = String::formatted("[{}]", property_name.as_symbol()->description());
|
||||
formatted_property_key = String::formatted("[{}]", property_key.as_symbol()->description());
|
||||
}
|
||||
FunctionObject* getter_function = nullptr;
|
||||
if (getter) {
|
||||
auto name = String::formatted("get {}", formatted_property_name);
|
||||
auto name = String::formatted("get {}", formatted_property_key);
|
||||
getter_function = NativeFunction::create(global_object(), name, move(getter));
|
||||
getter_function->define_direct_property(vm.names.length, Value(0), Attribute::Configurable);
|
||||
getter_function->define_direct_property(vm.names.name, js_string(vm, name), Attribute::Configurable);
|
||||
}
|
||||
FunctionObject* setter_function = nullptr;
|
||||
if (setter) {
|
||||
auto name = String::formatted("set {}", formatted_property_name);
|
||||
auto name = String::formatted("set {}", formatted_property_key);
|
||||
setter_function = NativeFunction::create(global_object(), name, move(setter));
|
||||
setter_function->define_direct_property(vm.names.length, Value(1), Attribute::Configurable);
|
||||
setter_function->define_direct_property(vm.names.name, js_string(vm, name), Attribute::Configurable);
|
||||
}
|
||||
return define_direct_accessor(property_name, getter_function, setter_function, attribute);
|
||||
return define_direct_accessor(property_key, getter_function, setter_function, attribute);
|
||||
}
|
||||
|
||||
void Object::define_direct_accessor(PropertyKey const& property_name, FunctionObject* getter, FunctionObject* setter, PropertyAttributes attributes)
|
||||
void Object::define_direct_accessor(PropertyKey const& property_key, FunctionObject* getter, FunctionObject* setter, PropertyAttributes attributes)
|
||||
{
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
auto existing_property = storage_get(property_name).value_or({}).value;
|
||||
auto existing_property = storage_get(property_key).value_or({}).value;
|
||||
auto* accessor = existing_property.is_accessor() ? &existing_property.as_accessor() : nullptr;
|
||||
if (!accessor) {
|
||||
accessor = Accessor::create(vm(), getter, setter);
|
||||
define_direct_property(property_name, accessor, attributes);
|
||||
define_direct_property(property_key, accessor, attributes);
|
||||
} else {
|
||||
if (getter)
|
||||
accessor->set_getter(getter);
|
||||
@ -1098,11 +1098,11 @@ void Object::ensure_shape_is_unique()
|
||||
}
|
||||
|
||||
// Simple side-effect free property lookup, following the prototype chain. Non-standard.
|
||||
Value Object::get_without_side_effects(const PropertyKey& property_name) const
|
||||
Value Object::get_without_side_effects(const PropertyKey& property_key) const
|
||||
{
|
||||
auto* object = this;
|
||||
while (object) {
|
||||
auto value_and_attributes = object->storage_get(property_name);
|
||||
auto value_and_attributes = object->storage_get(property_key);
|
||||
if (value_and_attributes.has_value())
|
||||
return value_and_attributes->value;
|
||||
object = object->prototype();
|
||||
@ -1110,19 +1110,19 @@ Value Object::get_without_side_effects(const PropertyKey& property_name) const
|
||||
return {};
|
||||
}
|
||||
|
||||
void Object::define_native_function(PropertyKey const& property_name, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute)
|
||||
void Object::define_native_function(PropertyKey const& property_key, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)> native_function, i32 length, PropertyAttributes attribute)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
String function_name;
|
||||
if (property_name.is_string()) {
|
||||
function_name = property_name.as_string();
|
||||
if (property_key.is_string()) {
|
||||
function_name = property_key.as_string();
|
||||
} else {
|
||||
function_name = String::formatted("[{}]", property_name.as_symbol()->description());
|
||||
function_name = String::formatted("[{}]", property_key.as_symbol()->description());
|
||||
}
|
||||
auto* function = NativeFunction::create(global_object(), function_name, move(native_function));
|
||||
function->define_direct_property(vm.names.length, Value(length), Attribute::Configurable);
|
||||
function->define_direct_property(vm.names.name, js_string(vm, function_name), Attribute::Configurable);
|
||||
define_direct_property(property_name, function, attribute);
|
||||
define_direct_property(property_key, function, attribute);
|
||||
}
|
||||
|
||||
// 20.1.2.3.1 ObjectDefineProperties ( O, Properties ), https://tc39.es/ecma262/#sec-objectdefineproperties
|
||||
@ -1148,21 +1148,21 @@ ThrowCompletionOr<Object*> Object::define_properties(Value properties)
|
||||
|
||||
// 5. For each element nextKey of keys, do
|
||||
for (auto& next_key : keys) {
|
||||
auto property_name = MUST(PropertyKey::from_value(global_object, next_key));
|
||||
auto property_key = MUST(PropertyKey::from_value(global_object, next_key));
|
||||
|
||||
// a. Let propDesc be ? props.[[GetOwnProperty]](nextKey).
|
||||
auto property_descriptor = TRY(props->internal_get_own_property(property_name));
|
||||
auto property_descriptor = TRY(props->internal_get_own_property(property_key));
|
||||
|
||||
// b. If propDesc is not undefined and propDesc.[[Enumerable]] is true, then
|
||||
if (property_descriptor.has_value() && *property_descriptor->enumerable) {
|
||||
// i. Let descObj be ? Get(props, nextKey).
|
||||
auto descriptor_object = TRY(props->get(property_name));
|
||||
auto descriptor_object = TRY(props->get(property_key));
|
||||
|
||||
// ii. Let desc be ? ToPropertyDescriptor(descObj).
|
||||
auto descriptor = TRY(to_property_descriptor(global_object, descriptor_object));
|
||||
|
||||
// iii. Append the pair (a two element List) consisting of nextKey and desc to the end of descriptors.
|
||||
descriptors.append({ property_name, descriptor });
|
||||
descriptors.append({ property_key, descriptor });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,7 +145,7 @@ public:
|
||||
|
||||
Value get_without_side_effects(const PropertyKey&) const;
|
||||
|
||||
void define_direct_property(PropertyKey const& property_name, Value value, PropertyAttributes attributes) { storage_set(property_name, { value, attributes }); };
|
||||
void define_direct_property(PropertyKey const& property_key, Value value, PropertyAttributes attributes) { storage_set(property_key, { value, attributes }); };
|
||||
void define_direct_accessor(PropertyKey const&, FunctionObject* getter, FunctionObject* setter, PropertyAttributes attributes);
|
||||
|
||||
void define_native_function(PropertyKey const&, Function<ThrowCompletionOr<Value>(VM&, GlobalObject&)>, i32 length, PropertyAttributes attributes);
|
||||
|
@ -277,17 +277,17 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::get_own_property_descriptors)
|
||||
|
||||
// 4. For each element key of ownKeys, do
|
||||
for (auto& key : own_keys) {
|
||||
auto property_name = MUST(PropertyKey::from_value(global_object, key));
|
||||
auto property_key = MUST(PropertyKey::from_value(global_object, key));
|
||||
|
||||
// a. Let desc be ? obj.[[GetOwnProperty]](key).
|
||||
auto desc = TRY(object->internal_get_own_property(property_name));
|
||||
auto desc = TRY(object->internal_get_own_property(property_key));
|
||||
|
||||
// b. Let descriptor be ! FromPropertyDescriptor(desc).
|
||||
auto descriptor = from_property_descriptor(global_object, desc);
|
||||
|
||||
// c. If descriptor is not undefined, perform ! CreateDataPropertyOrThrow(descriptors, key, descriptor).
|
||||
if (!descriptor.is_undefined())
|
||||
MUST(descriptors->create_data_property_or_throw(property_name, descriptor));
|
||||
MUST(descriptors->create_data_property_or_throw(property_key, descriptor));
|
||||
}
|
||||
|
||||
// 5. Return descriptors.
|
||||
@ -411,20 +411,20 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectConstructor::assign)
|
||||
|
||||
// iii. For each element nextKey of keys, do
|
||||
for (auto& next_key : keys) {
|
||||
auto property_name = MUST(PropertyKey::from_value(global_object, next_key));
|
||||
auto property_key = MUST(PropertyKey::from_value(global_object, next_key));
|
||||
|
||||
// 1. Let desc be ? from.[[GetOwnProperty]](nextKey).
|
||||
auto desc = TRY(from->internal_get_own_property(property_name));
|
||||
auto desc = TRY(from->internal_get_own_property(property_key));
|
||||
|
||||
// 2. If desc is not undefined and desc.[[Enumerable]] is true, then
|
||||
if (!desc.has_value() || !*desc->enumerable)
|
||||
continue;
|
||||
|
||||
// a. Let propValue be ? Get(from, nextKey).
|
||||
auto prop_value = TRY(from->get(property_name));
|
||||
auto prop_value = TRY(from->get(property_key));
|
||||
|
||||
// b. Perform ? Set(to, nextKey, propValue, true).
|
||||
TRY(to->set(property_name, prop_value, Object::ShouldThrowExceptions::Yes));
|
||||
TRY(to->set(property_key, prop_value, Object::ShouldThrowExceptions::Yes));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -225,13 +225,13 @@ struct Traits<JS::PropertyKey> : public GenericTraits<JS::PropertyKey> {
|
||||
|
||||
template<>
|
||||
struct Formatter<JS::PropertyKey> : Formatter<StringView> {
|
||||
ErrorOr<void> format(FormatBuilder& builder, JS::PropertyKey const& property_name)
|
||||
ErrorOr<void> format(FormatBuilder& builder, JS::PropertyKey const& property_key)
|
||||
{
|
||||
if (!property_name.is_valid())
|
||||
if (!property_key.is_valid())
|
||||
return Formatter<StringView>::format(builder, "<invalid PropertyKey>");
|
||||
if (property_name.is_number())
|
||||
return Formatter<StringView>::format(builder, String::number(property_name.as_number()));
|
||||
return Formatter<StringView>::format(builder, property_name.to_string_or_symbol().to_display_string());
|
||||
if (property_key.is_number())
|
||||
return Formatter<StringView>::format(builder, String::number(property_key.as_number()));
|
||||
return Formatter<StringView>::format(builder, property_key.to_string_or_symbol().to_display_string());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -31,17 +31,17 @@ ProxyObject::~ProxyObject()
|
||||
{
|
||||
}
|
||||
|
||||
static Value property_name_to_value(VM& vm, PropertyKey const& name)
|
||||
static Value property_key_to_value(VM& vm, PropertyKey const& property_key)
|
||||
{
|
||||
VERIFY(name.is_valid());
|
||||
if (name.is_symbol())
|
||||
return name.as_symbol();
|
||||
VERIFY(property_key.is_valid());
|
||||
if (property_key.is_symbol())
|
||||
return property_key.as_symbol();
|
||||
|
||||
if (name.is_string())
|
||||
return js_string(vm, name.as_string());
|
||||
if (property_key.is_string())
|
||||
return js_string(vm, property_key.as_string());
|
||||
|
||||
VERIFY(name.is_number());
|
||||
return js_string(vm, String::number(name.as_number()));
|
||||
VERIFY(property_key.is_number());
|
||||
return js_string(vm, String::number(property_key.as_number()));
|
||||
}
|
||||
|
||||
// 10.5.1 [[GetPrototypeOf]] ( ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getprototypeof
|
||||
@ -223,13 +223,13 @@ ThrowCompletionOr<bool> ProxyObject::internal_prevent_extensions()
|
||||
}
|
||||
|
||||
// 10.5.5 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> ProxyObject::internal_get_own_property(const PropertyKey& property_name) const
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> ProxyObject::internal_get_own_property(const PropertyKey& property_key) const
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
|
||||
@ -246,18 +246,18 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> ProxyObject::internal_get_own_pr
|
||||
// 7. If trap is undefined, then
|
||||
if (!trap) {
|
||||
// a. Return ? target.[[GetOwnProperty]](P).
|
||||
return m_target.internal_get_own_property(property_name);
|
||||
return m_target.internal_get_own_property(property_key);
|
||||
}
|
||||
|
||||
// 8. Let trapResultObj be ? Call(trap, handler, « target, P »).
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_name_to_value(vm, property_name)));
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key)));
|
||||
|
||||
// 9. If Type(trapResultObj) is neither Object nor Undefined, throw a TypeError exception.
|
||||
if (!trap_result.is_object() && !trap_result.is_undefined())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::ProxyGetOwnDescriptorReturn);
|
||||
|
||||
// 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_name));
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_key));
|
||||
|
||||
// 11. If trapResultObj is undefined, then
|
||||
if (trap_result.is_undefined()) {
|
||||
@ -316,13 +316,13 @@ ThrowCompletionOr<Optional<PropertyDescriptor>> ProxyObject::internal_get_own_pr
|
||||
}
|
||||
|
||||
// 10.5.6 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc
|
||||
ThrowCompletionOr<bool> ProxyObject::internal_define_own_property(PropertyKey const& property_name, PropertyDescriptor const& property_descriptor)
|
||||
ThrowCompletionOr<bool> ProxyObject::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
|
||||
@ -339,21 +339,21 @@ ThrowCompletionOr<bool> ProxyObject::internal_define_own_property(PropertyKey co
|
||||
// 7. If trap is undefined, then
|
||||
if (!trap) {
|
||||
// a. Return ? target.[[DefineOwnProperty]](P, Desc).
|
||||
return m_target.internal_define_own_property(property_name, property_descriptor);
|
||||
return m_target.internal_define_own_property(property_key, property_descriptor);
|
||||
}
|
||||
|
||||
// 8. Let descObj be FromPropertyDescriptor(Desc).
|
||||
auto descriptor_object = from_property_descriptor(global_object, property_descriptor);
|
||||
|
||||
// 9. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, descObj »)).
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_name_to_value(vm, property_name), descriptor_object)).to_boolean();
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key), descriptor_object)).to_boolean();
|
||||
|
||||
// 10. If booleanTrapResult is false, return false.
|
||||
if (!trap_result)
|
||||
return false;
|
||||
|
||||
// 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_name));
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_key));
|
||||
|
||||
// 12. Let extensibleTarget be ? IsExtensible(target).
|
||||
auto extensible_target = TRY(m_target.is_extensible());
|
||||
@ -400,13 +400,13 @@ ThrowCompletionOr<bool> ProxyObject::internal_define_own_property(PropertyKey co
|
||||
}
|
||||
|
||||
// 10.5.7 [[HasProperty]] ( P ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p
|
||||
ThrowCompletionOr<bool> ProxyObject::internal_has_property(PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<bool> ProxyObject::internal_has_property(PropertyKey const& property_key) const
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
|
||||
@ -423,16 +423,16 @@ ThrowCompletionOr<bool> ProxyObject::internal_has_property(PropertyKey const& pr
|
||||
// 7. If trap is undefined, then
|
||||
if (!trap) {
|
||||
// a. Return ? target.[[HasProperty]](P).
|
||||
return m_target.internal_has_property(property_name);
|
||||
return m_target.internal_has_property(property_key);
|
||||
}
|
||||
|
||||
// 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)).
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_name_to_value(vm, property_name))).to_boolean();
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key))).to_boolean();
|
||||
|
||||
// 9. If booleanTrapResult is false, then
|
||||
if (!trap_result) {
|
||||
// a. Let targetDesc be ? target.[[GetOwnProperty]](P).
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_name));
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_key));
|
||||
|
||||
// b. If targetDesc is not undefined, then
|
||||
if (target_descriptor.has_value()) {
|
||||
@ -454,7 +454,7 @@ ThrowCompletionOr<bool> ProxyObject::internal_has_property(PropertyKey const& pr
|
||||
}
|
||||
|
||||
// 10.5.8 [[Get]] ( P, Receiver ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver
|
||||
ThrowCompletionOr<Value> ProxyObject::internal_get(PropertyKey const& property_name, Value receiver) const
|
||||
ThrowCompletionOr<Value> ProxyObject::internal_get(PropertyKey const& property_key, Value receiver) const
|
||||
{
|
||||
VERIFY(!receiver.is_empty());
|
||||
|
||||
@ -462,7 +462,7 @@ ThrowCompletionOr<Value> ProxyObject::internal_get(PropertyKey const& property_n
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
|
||||
@ -495,14 +495,14 @@ ThrowCompletionOr<Value> ProxyObject::internal_get(PropertyKey const& property_n
|
||||
// 7. If trap is undefined, then
|
||||
if (!trap) {
|
||||
// a. Return ? target.[[Get]](P, Receiver).
|
||||
return m_target.internal_get(property_name, receiver);
|
||||
return m_target.internal_get(property_key, receiver);
|
||||
}
|
||||
|
||||
// 8. Let trapResult be ? Call(trap, handler, « target, P, Receiver »).
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_name_to_value(vm, property_name), receiver));
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key), receiver));
|
||||
|
||||
// 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_name));
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_key));
|
||||
|
||||
// 10. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then
|
||||
if (target_descriptor.has_value() && !*target_descriptor->configurable) {
|
||||
@ -525,7 +525,7 @@ ThrowCompletionOr<Value> ProxyObject::internal_get(PropertyKey const& property_n
|
||||
}
|
||||
|
||||
// 10.5.9 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
|
||||
ThrowCompletionOr<bool> ProxyObject::internal_set(PropertyKey const& property_name, Value value, Value receiver)
|
||||
ThrowCompletionOr<bool> ProxyObject::internal_set(PropertyKey const& property_key, Value value, Value receiver)
|
||||
{
|
||||
VERIFY(!value.is_empty());
|
||||
VERIFY(!receiver.is_empty());
|
||||
@ -534,7 +534,7 @@ ThrowCompletionOr<bool> ProxyObject::internal_set(PropertyKey const& property_na
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
|
||||
@ -551,18 +551,18 @@ ThrowCompletionOr<bool> ProxyObject::internal_set(PropertyKey const& property_na
|
||||
// 7. If trap is undefined, then
|
||||
if (!trap) {
|
||||
// a. Return ? target.[[Set]](P, V, Receiver).
|
||||
return m_target.internal_set(property_name, value, receiver);
|
||||
return m_target.internal_set(property_key, value, receiver);
|
||||
}
|
||||
|
||||
// 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P, V, Receiver »)).
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_name_to_value(vm, property_name), value, receiver)).to_boolean();
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key), value, receiver)).to_boolean();
|
||||
|
||||
// 9. If booleanTrapResult is false, return false.
|
||||
if (!trap_result)
|
||||
return false;
|
||||
|
||||
// 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_name));
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_key));
|
||||
|
||||
// 11. If targetDesc is not undefined and targetDesc.[[Configurable]] is false, then
|
||||
if (target_descriptor.has_value() && !*target_descriptor->configurable) {
|
||||
@ -585,13 +585,13 @@ ThrowCompletionOr<bool> ProxyObject::internal_set(PropertyKey const& property_na
|
||||
}
|
||||
|
||||
// 10.5.10 [[Delete]] ( P ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-delete-p
|
||||
ThrowCompletionOr<bool> ProxyObject::internal_delete(PropertyKey const& property_name)
|
||||
ThrowCompletionOr<bool> ProxyObject::internal_delete(PropertyKey const& property_key)
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& global_object = this->global_object();
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let handler be O.[[ProxyHandler]].
|
||||
|
||||
@ -608,18 +608,18 @@ ThrowCompletionOr<bool> ProxyObject::internal_delete(PropertyKey const& property
|
||||
// 7. If trap is undefined, then
|
||||
if (!trap) {
|
||||
// a. Return ? target.[[Delete]](P).
|
||||
return m_target.internal_delete(property_name);
|
||||
return m_target.internal_delete(property_key);
|
||||
}
|
||||
|
||||
// 8. Let booleanTrapResult be ! ToBoolean(? Call(trap, handler, « target, P »)).
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_name_to_value(vm, property_name))).to_boolean();
|
||||
auto trap_result = TRY(call(global_object, *trap, &m_handler, &m_target, property_key_to_value(vm, property_key))).to_boolean();
|
||||
|
||||
// 9. If booleanTrapResult is false, return false.
|
||||
if (!trap_result)
|
||||
return false;
|
||||
|
||||
// 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_name));
|
||||
auto target_descriptor = TRY(m_target.internal_get_own_property(property_key));
|
||||
|
||||
// 11. If targetDesc is undefined, return true.
|
||||
if (!target_descriptor.has_value())
|
||||
|
@ -53,24 +53,24 @@ Shape* Shape::get_or_prune_cached_prototype_transition(Object* prototype)
|
||||
return it->value;
|
||||
}
|
||||
|
||||
Shape* Shape::create_put_transition(const StringOrSymbol& property_name, PropertyAttributes attributes)
|
||||
Shape* Shape::create_put_transition(const StringOrSymbol& property_key, PropertyAttributes attributes)
|
||||
{
|
||||
TransitionKey key { property_name, attributes };
|
||||
TransitionKey key { property_key, attributes };
|
||||
if (auto* existing_shape = get_or_prune_cached_forward_transition(key))
|
||||
return existing_shape;
|
||||
auto* new_shape = heap().allocate_without_global_object<Shape>(*this, property_name, attributes, TransitionType::Put);
|
||||
auto* new_shape = heap().allocate_without_global_object<Shape>(*this, property_key, attributes, TransitionType::Put);
|
||||
if (!m_forward_transitions)
|
||||
m_forward_transitions = make<HashMap<TransitionKey, WeakPtr<Shape>>>();
|
||||
m_forward_transitions->set(key, new_shape);
|
||||
return new_shape;
|
||||
}
|
||||
|
||||
Shape* Shape::create_configure_transition(const StringOrSymbol& property_name, PropertyAttributes attributes)
|
||||
Shape* Shape::create_configure_transition(const StringOrSymbol& property_key, PropertyAttributes attributes)
|
||||
{
|
||||
TransitionKey key { property_name, attributes };
|
||||
TransitionKey key { property_key, attributes };
|
||||
if (auto* existing_shape = get_or_prune_cached_forward_transition(key))
|
||||
return existing_shape;
|
||||
auto* new_shape = heap().allocate_without_global_object<Shape>(*this, property_name, attributes, TransitionType::Configure);
|
||||
auto* new_shape = heap().allocate_without_global_object<Shape>(*this, property_key, attributes, TransitionType::Configure);
|
||||
if (!m_forward_transitions)
|
||||
m_forward_transitions = make<HashMap<TransitionKey, WeakPtr<Shape>>>();
|
||||
m_forward_transitions->set(key, new_shape);
|
||||
@ -97,10 +97,10 @@ Shape::Shape(Object& global_object)
|
||||
{
|
||||
}
|
||||
|
||||
Shape::Shape(Shape& previous_shape, const StringOrSymbol& property_name, PropertyAttributes attributes, TransitionType transition_type)
|
||||
Shape::Shape(Shape& previous_shape, const StringOrSymbol& property_key, PropertyAttributes attributes, TransitionType transition_type)
|
||||
: m_global_object(previous_shape.m_global_object)
|
||||
, m_previous(&previous_shape)
|
||||
, m_property_name(property_name)
|
||||
, m_property_key(property_key)
|
||||
, m_prototype(previous_shape.m_prototype)
|
||||
, m_property_count(transition_type == TransitionType::Put ? previous_shape.m_property_count + 1 : previous_shape.m_property_count)
|
||||
, m_attributes(attributes)
|
||||
@ -127,18 +127,18 @@ void Shape::visit_edges(Cell::Visitor& visitor)
|
||||
visitor.visit(m_global_object);
|
||||
visitor.visit(m_prototype);
|
||||
visitor.visit(m_previous);
|
||||
m_property_name.visit_edges(visitor);
|
||||
m_property_key.visit_edges(visitor);
|
||||
if (m_property_table) {
|
||||
for (auto& it : *m_property_table)
|
||||
it.key.visit_edges(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
Optional<PropertyMetadata> Shape::lookup(const StringOrSymbol& property_name) const
|
||||
Optional<PropertyMetadata> Shape::lookup(const StringOrSymbol& property_key) const
|
||||
{
|
||||
if (m_property_count == 0)
|
||||
return {};
|
||||
auto property = property_table().get(property_name);
|
||||
auto property = property_table().get(property_key);
|
||||
if (!property.has_value())
|
||||
return {};
|
||||
return property;
|
||||
@ -183,46 +183,46 @@ void Shape::ensure_property_table() const
|
||||
|
||||
for (ssize_t i = transition_chain.size() - 1; i >= 0; --i) {
|
||||
auto* shape = transition_chain[i];
|
||||
if (!shape->m_property_name.is_valid()) {
|
||||
if (!shape->m_property_key.is_valid()) {
|
||||
// Ignore prototype transitions as they don't affect the key map.
|
||||
continue;
|
||||
}
|
||||
if (shape->m_transition_type == TransitionType::Put) {
|
||||
m_property_table->set(shape->m_property_name, { next_offset++, shape->m_attributes });
|
||||
m_property_table->set(shape->m_property_key, { next_offset++, shape->m_attributes });
|
||||
} else if (shape->m_transition_type == TransitionType::Configure) {
|
||||
auto it = m_property_table->find(shape->m_property_name);
|
||||
auto it = m_property_table->find(shape->m_property_key);
|
||||
VERIFY(it != m_property_table->end());
|
||||
it->value.attributes = shape->m_attributes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Shape::add_property_to_unique_shape(const StringOrSymbol& property_name, PropertyAttributes attributes)
|
||||
void Shape::add_property_to_unique_shape(const StringOrSymbol& property_key, PropertyAttributes attributes)
|
||||
{
|
||||
VERIFY(is_unique());
|
||||
VERIFY(m_property_table);
|
||||
VERIFY(!m_property_table->contains(property_name));
|
||||
m_property_table->set(property_name, { static_cast<u32>(m_property_table->size()), attributes });
|
||||
VERIFY(!m_property_table->contains(property_key));
|
||||
m_property_table->set(property_key, { static_cast<u32>(m_property_table->size()), attributes });
|
||||
|
||||
VERIFY(m_property_count < NumericLimits<u32>::max());
|
||||
++m_property_count;
|
||||
}
|
||||
|
||||
void Shape::reconfigure_property_in_unique_shape(const StringOrSymbol& property_name, PropertyAttributes attributes)
|
||||
void Shape::reconfigure_property_in_unique_shape(const StringOrSymbol& property_key, PropertyAttributes attributes)
|
||||
{
|
||||
VERIFY(is_unique());
|
||||
VERIFY(m_property_table);
|
||||
auto it = m_property_table->find(property_name);
|
||||
auto it = m_property_table->find(property_key);
|
||||
VERIFY(it != m_property_table->end());
|
||||
it->value.attributes = attributes;
|
||||
m_property_table->set(property_name, it->value);
|
||||
m_property_table->set(property_key, it->value);
|
||||
}
|
||||
|
||||
void Shape::remove_property_from_unique_shape(const StringOrSymbol& property_name, size_t offset)
|
||||
void Shape::remove_property_from_unique_shape(const StringOrSymbol& property_key, size_t offset)
|
||||
{
|
||||
VERIFY(is_unique());
|
||||
VERIFY(m_property_table);
|
||||
if (m_property_table->remove(property_name))
|
||||
if (m_property_table->remove(property_key))
|
||||
--m_property_count;
|
||||
for (auto& it : *m_property_table) {
|
||||
VERIFY(it.value.offset != offset);
|
||||
@ -231,20 +231,20 @@ void Shape::remove_property_from_unique_shape(const StringOrSymbol& property_nam
|
||||
}
|
||||
}
|
||||
|
||||
void Shape::add_property_without_transition(StringOrSymbol const& property_name, PropertyAttributes attributes)
|
||||
void Shape::add_property_without_transition(StringOrSymbol const& property_key, PropertyAttributes attributes)
|
||||
{
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
ensure_property_table();
|
||||
if (m_property_table->set(property_name, { m_property_count, attributes }) == AK::HashSetResult::InsertedNewEntry) {
|
||||
if (m_property_table->set(property_key, { m_property_count, attributes }) == AK::HashSetResult::InsertedNewEntry) {
|
||||
VERIFY(m_property_count < NumericLimits<u32>::max());
|
||||
++m_property_count;
|
||||
}
|
||||
}
|
||||
|
||||
FLATTEN void Shape::add_property_without_transition(PropertyKey const& property_name, PropertyAttributes attributes)
|
||||
FLATTEN void Shape::add_property_without_transition(PropertyKey const& property_key, PropertyAttributes attributes)
|
||||
{
|
||||
VERIFY(property_name.is_valid());
|
||||
add_property_without_transition(property_name.to_string_or_symbol(), attributes);
|
||||
VERIFY(property_key.is_valid());
|
||||
add_property_without_transition(property_key.to_string_or_symbol(), attributes);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,12 +24,12 @@ struct PropertyMetadata {
|
||||
};
|
||||
|
||||
struct TransitionKey {
|
||||
StringOrSymbol property_name;
|
||||
StringOrSymbol property_key;
|
||||
PropertyAttributes attributes { 0 };
|
||||
|
||||
bool operator==(const TransitionKey& other) const
|
||||
{
|
||||
return property_name == other.property_name && attributes == other.attributes;
|
||||
return property_key == other.property_key && attributes == other.attributes;
|
||||
}
|
||||
};
|
||||
|
||||
@ -50,7 +50,7 @@ public:
|
||||
|
||||
explicit Shape(ShapeWithoutGlobalObjectTag);
|
||||
explicit Shape(Object& global_object);
|
||||
Shape(Shape& previous_shape, const StringOrSymbol& property_name, PropertyAttributes attributes, TransitionType);
|
||||
Shape(Shape& previous_shape, const StringOrSymbol& property_key, PropertyAttributes attributes, TransitionType);
|
||||
Shape(Shape& previous_shape, Object* new_prototype);
|
||||
|
||||
Shape* create_put_transition(const StringOrSymbol&, PropertyAttributes attributes);
|
||||
@ -83,7 +83,7 @@ public:
|
||||
|
||||
void remove_property_from_unique_shape(const StringOrSymbol&, size_t offset);
|
||||
void add_property_to_unique_shape(const StringOrSymbol&, PropertyAttributes attributes);
|
||||
void reconfigure_property_in_unique_shape(const StringOrSymbol& property_name, PropertyAttributes attributes);
|
||||
void reconfigure_property_in_unique_shape(const StringOrSymbol& property_key, PropertyAttributes attributes);
|
||||
|
||||
private:
|
||||
virtual const char* class_name() const override { return "Shape"; }
|
||||
@ -101,7 +101,7 @@ private:
|
||||
OwnPtr<HashMap<TransitionKey, WeakPtr<Shape>>> m_forward_transitions;
|
||||
OwnPtr<HashMap<Object*, WeakPtr<Shape>>> m_prototype_transitions;
|
||||
Shape* m_previous { nullptr };
|
||||
StringOrSymbol m_property_name;
|
||||
StringOrSymbol m_property_key;
|
||||
Object* m_prototype { nullptr };
|
||||
u32 m_property_count { 0 };
|
||||
|
||||
@ -116,6 +116,6 @@ template<>
|
||||
struct AK::Traits<JS::TransitionKey> : public GenericTraits<JS::TransitionKey> {
|
||||
static unsigned hash(const JS::TransitionKey& key)
|
||||
{
|
||||
return pair_int_hash(key.attributes.bits(), Traits<JS::StringOrSymbol>::hash(key.property_name));
|
||||
return pair_int_hash(key.attributes.bits(), Traits<JS::StringOrSymbol>::hash(key.property_key));
|
||||
}
|
||||
};
|
||||
|
@ -44,20 +44,20 @@ void StringObject::visit_edges(Cell::Visitor& visitor)
|
||||
}
|
||||
|
||||
// 10.4.3.5 StringGetOwnProperty ( S, P ), https://tc39.es/ecma262/#sec-stringgetownproperty
|
||||
static Optional<PropertyDescriptor> string_get_own_property(GlobalObject& global_object, StringObject const& string, PropertyKey const& property_name)
|
||||
static Optional<PropertyDescriptor> string_get_own_property(GlobalObject& global_object, StringObject const& string, PropertyKey const& property_key)
|
||||
{
|
||||
// 1. Assert: S is an Object that has a [[StringData]] internal slot.
|
||||
// 2. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 3. If Type(P) is not String, return undefined.
|
||||
// NOTE: The spec only uses string and symbol keys, and later coerces to numbers -
|
||||
// this is not the case for PropertyKey, so '!property_name.is_string()' would be wrong.
|
||||
if (property_name.is_symbol())
|
||||
// this is not the case for PropertyKey, so '!property_key.is_string()' would be wrong.
|
||||
if (property_key.is_symbol())
|
||||
return {};
|
||||
|
||||
// 4. Let index be ! CanonicalNumericIndexString(P).
|
||||
auto index = canonical_numeric_index_string(global_object, property_name);
|
||||
auto index = canonical_numeric_index_string(global_object, property_key);
|
||||
// 5. If index is undefined, return undefined.
|
||||
if (index.is_undefined())
|
||||
return {};
|
||||
@ -92,29 +92,29 @@ static Optional<PropertyDescriptor> string_get_own_property(GlobalObject& global
|
||||
}
|
||||
|
||||
// 10.4.3.1 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-string-exotic-objects-getownproperty-p
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> StringObject::internal_get_own_property(PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<Optional<PropertyDescriptor>> StringObject::internal_get_own_property(PropertyKey const& property_key) const
|
||||
{
|
||||
// Assert: IsPropertyKey(P) is true.
|
||||
|
||||
// 2. Let desc be OrdinaryGetOwnProperty(S, P).
|
||||
auto descriptor = MUST(Object::internal_get_own_property(property_name));
|
||||
auto descriptor = MUST(Object::internal_get_own_property(property_key));
|
||||
|
||||
// 3. If desc is not undefined, return desc.
|
||||
if (descriptor.has_value())
|
||||
return descriptor;
|
||||
|
||||
// 4. Return ! StringGetOwnProperty(S, P).
|
||||
return string_get_own_property(global_object(), *this, property_name);
|
||||
return string_get_own_property(global_object(), *this, property_key);
|
||||
}
|
||||
|
||||
// 10.4.3.2 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-string-exotic-objects-defineownproperty-p-desc
|
||||
ThrowCompletionOr<bool> StringObject::internal_define_own_property(PropertyKey const& property_name, PropertyDescriptor const& property_descriptor)
|
||||
ThrowCompletionOr<bool> StringObject::internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor)
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let stringDesc be ! StringGetOwnProperty(S, P).
|
||||
auto string_descriptor = string_get_own_property(global_object(), *this, property_name);
|
||||
auto string_descriptor = string_get_own_property(global_object(), *this, property_key);
|
||||
|
||||
// 3. If stringDesc is not undefined, then
|
||||
if (string_descriptor.has_value()) {
|
||||
@ -126,7 +126,7 @@ ThrowCompletionOr<bool> StringObject::internal_define_own_property(PropertyKey c
|
||||
}
|
||||
|
||||
// 4. Return ! OrdinaryDefineOwnProperty(S, P, Desc).
|
||||
return Object::internal_define_own_property(property_name, property_descriptor);
|
||||
return Object::internal_define_own_property(property_key, property_descriptor);
|
||||
}
|
||||
|
||||
// 10.4.3.3 [[OwnPropertyKeys]] ( ), https://tc39.es/ecma262/#sec-string-exotic-objects-ownpropertykeys
|
||||
|
@ -993,15 +993,15 @@ ThrowCompletionOr<Object*> default_merge_fields(GlobalObject& global_object, Obj
|
||||
for (auto& next_key : original_keys) {
|
||||
// a. If nextKey is not "month" or "monthCode", then
|
||||
if (next_key.as_string().string() != vm.names.month.as_string() && next_key.as_string().string() != vm.names.monthCode.as_string()) {
|
||||
auto property_name = MUST(PropertyKey::from_value(global_object, next_key));
|
||||
auto property_key = MUST(PropertyKey::from_value(global_object, next_key));
|
||||
|
||||
// i. Let propValue be ? Get(fields, nextKey).
|
||||
auto prop_value = TRY(fields.get(property_name));
|
||||
auto prop_value = TRY(fields.get(property_key));
|
||||
|
||||
// ii. If propValue is not undefined, then
|
||||
if (!prop_value.is_undefined()) {
|
||||
// 1. Perform ! CreateDataPropertyOrThrow(merged, nextKey, propValue).
|
||||
MUST(merged->create_data_property_or_throw(property_name, prop_value));
|
||||
MUST(merged->create_data_property_or_throw(property_key, prop_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1014,15 +1014,15 @@ ThrowCompletionOr<Object*> default_merge_fields(GlobalObject& global_object, Obj
|
||||
|
||||
// 5. For each element nextKey of newKeys, do
|
||||
for (auto& next_key : new_keys) {
|
||||
auto property_name = MUST(PropertyKey::from_value(global_object, next_key));
|
||||
auto property_key = MUST(PropertyKey::from_value(global_object, next_key));
|
||||
|
||||
// a. Let propValue be ? Get(additionalFields, nextKey).
|
||||
auto prop_value = TRY(additional_fields.get(property_name));
|
||||
auto prop_value = TRY(additional_fields.get(property_key));
|
||||
|
||||
// b. If propValue is not undefined, then
|
||||
if (!prop_value.is_undefined()) {
|
||||
// i. Perform ! CreateDataPropertyOrThrow(merged, nextKey, propValue).
|
||||
MUST(merged->create_data_property_or_throw(property_name, prop_value));
|
||||
MUST(merged->create_data_property_or_throw(property_key, prop_value));
|
||||
}
|
||||
|
||||
// See comment above.
|
||||
|
@ -183,10 +183,10 @@ class TypedArray : public TypedArrayBase {
|
||||
|
||||
public:
|
||||
// 10.4.5.1 [[GetOwnProperty]] ( P ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-getownproperty-p
|
||||
virtual ThrowCompletionOr<Optional<PropertyDescriptor>> internal_get_own_property(PropertyKey const& property_name) const override
|
||||
virtual ThrowCompletionOr<Optional<PropertyDescriptor>> internal_get_own_property(PropertyKey const& property_key) const override
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Assert: O is an Integer-Indexed exotic object.
|
||||
|
||||
@ -196,9 +196,9 @@ public:
|
||||
|
||||
// 3. If Type(P) is String, then
|
||||
// NOTE: This includes an implementation-defined optimization, see note above!
|
||||
if (property_name.is_string() || property_name.is_number()) {
|
||||
if (property_key.is_string() || property_key.is_number()) {
|
||||
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_name);
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_key);
|
||||
// b. If numericIndex is not undefined, then
|
||||
if (!numeric_index.is_undefined()) {
|
||||
// i. Let value be ! IntegerIndexedElementGet(O, numericIndex).
|
||||
@ -219,14 +219,14 @@ public:
|
||||
}
|
||||
|
||||
// 4. Return OrdinaryGetOwnProperty(O, P).
|
||||
return Object::internal_get_own_property(property_name);
|
||||
return Object::internal_get_own_property(property_key);
|
||||
}
|
||||
|
||||
// 10.4.5.2 [[HasProperty]] ( P ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-hasproperty-p
|
||||
virtual ThrowCompletionOr<bool> internal_has_property(PropertyKey const& property_name) const override
|
||||
virtual ThrowCompletionOr<bool> internal_has_property(PropertyKey const& property_key) const override
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Assert: O is an Integer-Indexed exotic object.
|
||||
|
||||
@ -236,23 +236,23 @@ public:
|
||||
|
||||
// 3. If Type(P) is String, then
|
||||
// NOTE: This includes an implementation-defined optimization, see note above!
|
||||
if (property_name.is_string() || property_name.is_number()) {
|
||||
if (property_key.is_string() || property_key.is_number()) {
|
||||
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_name);
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_key);
|
||||
// b. If numericIndex is not undefined, return ! IsValidIntegerIndex(O, numericIndex).
|
||||
if (!numeric_index.is_undefined())
|
||||
return is_valid_integer_index(*this, numeric_index);
|
||||
}
|
||||
|
||||
// 4. Return ? OrdinaryHasProperty(O, P).
|
||||
return Object::internal_has_property(property_name);
|
||||
return Object::internal_has_property(property_key);
|
||||
}
|
||||
|
||||
// 10.4.5.3 [[DefineOwnProperty]] ( P, Desc ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-defineownproperty-p-desc
|
||||
virtual ThrowCompletionOr<bool> internal_define_own_property(PropertyKey const& property_name, PropertyDescriptor const& property_descriptor) override
|
||||
virtual ThrowCompletionOr<bool> internal_define_own_property(PropertyKey const& property_key, PropertyDescriptor const& property_descriptor) override
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Assert: O is an Integer-Indexed exotic object.
|
||||
|
||||
@ -262,9 +262,9 @@ public:
|
||||
|
||||
// 3. If Type(P) is String, then
|
||||
// NOTE: This includes an implementation-defined optimization, see note above!
|
||||
if (property_name.is_string() || property_name.is_number()) {
|
||||
if (property_key.is_string() || property_key.is_number()) {
|
||||
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_name);
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_key);
|
||||
// b. If numericIndex is not undefined, then
|
||||
if (!numeric_index.is_undefined()) {
|
||||
// i. If ! IsValidIntegerIndex(O, numericIndex) is false, return false.
|
||||
@ -297,25 +297,25 @@ public:
|
||||
}
|
||||
|
||||
// 4. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
|
||||
return Object::internal_define_own_property(property_name, property_descriptor);
|
||||
return Object::internal_define_own_property(property_key, property_descriptor);
|
||||
}
|
||||
|
||||
// 10.4.5.4 [[Get]] ( P, Receiver ), 10.4.5.4 [[Get]] ( P, Receiver )
|
||||
virtual ThrowCompletionOr<Value> internal_get(PropertyKey const& property_name, Value receiver) const override
|
||||
virtual ThrowCompletionOr<Value> internal_get(PropertyKey const& property_key, Value receiver) const override
|
||||
{
|
||||
VERIFY(!receiver.is_empty());
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
// NOTE: If the property name is a number type (An implementation-defined optimized
|
||||
// property key type), it can be treated as a string property that will transparently be
|
||||
// converted into a canonical numeric index.
|
||||
|
||||
// 2. If Type(P) is String, then
|
||||
// NOTE: This includes an implementation-defined optimization, see note above!
|
||||
if (property_name.is_string() || property_name.is_number()) {
|
||||
if (property_key.is_string() || property_key.is_number()) {
|
||||
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_name);
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_key);
|
||||
// b. If numericIndex is not undefined, then
|
||||
if (!numeric_index.is_undefined()) {
|
||||
// i. Return ! IntegerIndexedElementGet(O, numericIndex).
|
||||
@ -324,26 +324,26 @@ public:
|
||||
}
|
||||
|
||||
// 3. Return ? OrdinaryGet(O, P, Receiver).
|
||||
return Object::internal_get(property_name, receiver);
|
||||
return Object::internal_get(property_key, receiver);
|
||||
}
|
||||
|
||||
// 10.4.5.5 [[Set]] ( P, V, Receiver ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-set-p-v-receiver
|
||||
virtual ThrowCompletionOr<bool> internal_set(PropertyKey const& property_name, Value value, Value receiver) override
|
||||
virtual ThrowCompletionOr<bool> internal_set(PropertyKey const& property_key, Value value, Value receiver) override
|
||||
{
|
||||
VERIFY(!value.is_empty());
|
||||
VERIFY(!receiver.is_empty());
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
// NOTE: If the property name is a number type (An implementation-defined optimized
|
||||
// property key type), it can be treated as a string property that will transparently be
|
||||
// converted into a canonical numeric index.
|
||||
|
||||
// 2. If Type(P) is String, then
|
||||
// NOTE: This includes an implementation-defined optimization, see note above!
|
||||
if (property_name.is_string() || property_name.is_number()) {
|
||||
if (property_key.is_string() || property_key.is_number()) {
|
||||
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_name);
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_key);
|
||||
// b. If numericIndex is not undefined, then
|
||||
if (!numeric_index.is_undefined()) {
|
||||
// i. Perform ? IntegerIndexedElementSet(O, numericIndex, V).
|
||||
@ -355,14 +355,14 @@ public:
|
||||
}
|
||||
|
||||
// 3. Return ? OrdinarySet(O, P, V, Receiver).
|
||||
return Object::internal_set(property_name, value, receiver);
|
||||
return Object::internal_set(property_key, value, receiver);
|
||||
}
|
||||
|
||||
// 10.4.5.6 [[Delete]] ( P ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-delete-p
|
||||
virtual ThrowCompletionOr<bool> internal_delete(PropertyKey const& property_name) override
|
||||
virtual ThrowCompletionOr<bool> internal_delete(PropertyKey const& property_key) override
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Assert: O is an Integer-Indexed exotic object.
|
||||
// NOTE: If the property name is a number type (An implementation-defined optimized
|
||||
@ -371,9 +371,9 @@ public:
|
||||
|
||||
// 3. If Type(P) is String, then
|
||||
// NOTE: This includes an implementation-defined optimization, see note above!
|
||||
if (property_name.is_string() || property_name.is_number()) {
|
||||
if (property_key.is_string() || property_key.is_number()) {
|
||||
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_name);
|
||||
auto numeric_index = canonical_numeric_index_string(global_object(), property_key);
|
||||
// b. If numericIndex is not undefined, then
|
||||
if (!numeric_index.is_undefined()) {
|
||||
// i. If ! IsValidIntegerIndex(O, numericIndex) is false, return true; else return false.
|
||||
@ -384,7 +384,7 @@ public:
|
||||
}
|
||||
|
||||
// 4. Return ? OrdinaryDelete(O, P).
|
||||
return Object::internal_delete(property_name);
|
||||
return Object::internal_delete(property_key);
|
||||
}
|
||||
|
||||
// 10.4.5.7 [[OwnPropertyKeys]] ( ), https://tc39.es/ecma262/#sec-integer-indexed-exotic-objects-ownpropertykeys
|
||||
|
@ -804,28 +804,28 @@ ThrowCompletionOr<double> Value::to_integer_or_infinity(GlobalObject& global_obj
|
||||
}
|
||||
|
||||
// 7.3.3 GetV ( V, P ), https://tc39.es/ecma262/#sec-getv
|
||||
ThrowCompletionOr<Value> Value::get(GlobalObject& global_object, PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<Value> Value::get(GlobalObject& global_object, PropertyKey const& property_key) const
|
||||
{
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let O be ? ToObject(V).
|
||||
auto* object = TRY(to_object(global_object));
|
||||
|
||||
// 3. Return ? O.[[Get]](P, V).
|
||||
return TRY(object->internal_get(property_name, *this));
|
||||
return TRY(object->internal_get(property_key, *this));
|
||||
}
|
||||
|
||||
// 7.3.11 GetMethod ( V, P ), https://tc39.es/ecma262/#sec-getmethod
|
||||
ThrowCompletionOr<FunctionObject*> Value::get_method(GlobalObject& global_object, PropertyKey const& property_name) const
|
||||
ThrowCompletionOr<FunctionObject*> Value::get_method(GlobalObject& global_object, PropertyKey const& property_key) const
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
|
||||
// 1. Assert: IsPropertyKey(P) is true.
|
||||
VERIFY(property_name.is_valid());
|
||||
VERIFY(property_key.is_valid());
|
||||
|
||||
// 2. Let func be ? GetV(V, P).
|
||||
auto function = TRY(get(global_object, property_name));
|
||||
auto function = TRY(get(global_object, property_key));
|
||||
|
||||
// 3. If func is either undefined or null, return undefined.
|
||||
if (function.is_nullish())
|
||||
@ -1569,10 +1569,10 @@ ThrowCompletionOr<TriState> is_less_than(GlobalObject& global_object, bool left_
|
||||
}
|
||||
|
||||
// 7.3.21 Invoke ( V, P [ , argumentsList ] ), https://tc39.es/ecma262/#sec-invoke
|
||||
ThrowCompletionOr<Value> Value::invoke_internal(GlobalObject& global_object, JS::PropertyKey const& property_name, Optional<MarkedValueList> arguments)
|
||||
ThrowCompletionOr<Value> Value::invoke_internal(GlobalObject& global_object, JS::PropertyKey const& property_key, Optional<MarkedValueList> arguments)
|
||||
{
|
||||
auto& vm = global_object.vm();
|
||||
auto property = TRY(get(global_object, property_name));
|
||||
auto property = TRY(get(global_object, property_key));
|
||||
if (!property.is_function())
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAFunction, property.to_string_without_side_effects());
|
||||
|
||||
|
@ -347,7 +347,7 @@ public:
|
||||
bool operator==(Value const&) const;
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> invoke(GlobalObject& global_object, PropertyKey const& property_name, Args... args);
|
||||
[[nodiscard]] ALWAYS_INLINE ThrowCompletionOr<Value> invoke(GlobalObject& global_object, PropertyKey const& property_key, Args... args);
|
||||
|
||||
private:
|
||||
Type m_type { Type::Empty };
|
||||
|
Loading…
Reference in New Issue
Block a user