mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 00:32:45 +00: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
					
				
					 25 changed files with 435 additions and 435 deletions
				
			
		|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Linus Groh
						Linus Groh