diff --git a/Libraries/LibJS/Runtime/AbstractOperations.cpp b/Libraries/LibJS/Runtime/AbstractOperations.cpp index 5259d57e0c8..550259ebcbd 100644 --- a/Libraries/LibJS/Runtime/AbstractOperations.cpp +++ b/Libraries/LibJS/Runtime/AbstractOperations.cpp @@ -1045,11 +1045,11 @@ Object* create_unmapped_arguments_object(VM& vm, ReadonlySpan arguments) // 2. Let obj be OrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »). // 3. Set obj.[[ParameterMap]] to undefined. - auto object = Object::create(realm, realm.intrinsics().object_prototype()); + auto object = Object::create_with_premade_shape(realm.intrinsics().unmapped_arguments_object_shape()); object->set_has_parameter_map(); // 4. Perform ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }). - MUST(object->define_property_or_throw(vm.names.length, { .value = Value(length), .writable = true, .enumerable = false, .configurable = true })); + object->put_direct(realm.intrinsics().unmapped_arguments_object_length_offset(), Value(length)); // 5. Let index be 0. // 6. Repeat, while index < len, @@ -1058,18 +1058,17 @@ Object* create_unmapped_arguments_object(VM& vm, ReadonlySpan arguments) auto value = arguments[index]; // b. Perform ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val). - MUST(object->create_data_property_or_throw(index, value)); + object->indexed_properties().put(index, value); // c. Set index to index + 1. } // 7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }). auto array_prototype_values = realm.intrinsics().array_prototype_values_function(); - MUST(object->define_property_or_throw(vm.well_known_symbol_iterator(), { .value = array_prototype_values, .writable = true, .enumerable = false, .configurable = true })); + object->put_direct(realm.intrinsics().unmapped_arguments_object_well_known_symbol_iterator_offset(), array_prototype_values); // 8. Perform ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false }). - auto throw_type_error = realm.intrinsics().throw_type_error_function(); - MUST(object->define_property_or_throw(vm.names.callee, { .get = throw_type_error, .set = throw_type_error, .enumerable = false, .configurable = false })); + object->put_direct(realm.intrinsics().unmapped_arguments_object_callee_offset(), realm.intrinsics().throw_type_error_accessor()); // 9. Return obj. return object; diff --git a/Libraries/LibJS/Runtime/Intrinsics.cpp b/Libraries/LibJS/Runtime/Intrinsics.cpp index d0d4fd0e7e0..649f91ce001 100644 --- a/Libraries/LibJS/Runtime/Intrinsics.cpp +++ b/Libraries/LibJS/Runtime/Intrinsics.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -219,6 +220,15 @@ void Intrinsics::initialize_intrinsics(Realm& realm) m_native_function_length_offset = m_native_function_shape->lookup(vm.names.length.to_string_or_symbol()).value().offset; m_native_function_name_offset = m_native_function_shape->lookup(vm.names.name.to_string_or_symbol()).value().offset; + m_unmapped_arguments_object_shape = heap().allocate(realm); + m_unmapped_arguments_object_shape->set_prototype_without_transition(m_object_prototype); + m_unmapped_arguments_object_shape->add_property_without_transition(vm.names.length, Attribute::Writable | Attribute::Configurable); + m_unmapped_arguments_object_shape->add_property_without_transition(vm.well_known_symbol_iterator(), Attribute::Writable | Attribute::Configurable); + m_unmapped_arguments_object_shape->add_property_without_transition(vm.names.callee, 0); + m_unmapped_arguments_object_length_offset = m_unmapped_arguments_object_shape->lookup(vm.names.length.to_string_or_symbol()).value().offset; + m_unmapped_arguments_object_well_known_symbol_iterator_offset = m_unmapped_arguments_object_shape->lookup(StringOrSymbol(vm.well_known_symbol_iterator())).value().offset; + m_unmapped_arguments_object_callee_offset = m_unmapped_arguments_object_shape->lookup(vm.names.callee.to_string_or_symbol()).value().offset; + // Normally Realm::create() takes care of this, but these are allocated via Heap::allocate(). m_function_prototype->initialize(realm); m_object_prototype->initialize(realm); @@ -272,6 +282,11 @@ void Intrinsics::initialize_intrinsics(Realm& realm) m_throw_type_error_function->define_direct_property(vm.names.name, PrimitiveString::create(vm, String {}), 0); MUST(m_throw_type_error_function->internal_prevent_extensions()); + m_throw_type_error_accessor = Accessor::create( + vm, + m_throw_type_error_function, + m_throw_type_error_function); + initialize_constructor(vm, vm.names.Error, *m_error_constructor, m_error_prototype); initialize_constructor(vm, vm.names.Function, *m_function_constructor, m_function_prototype); initialize_constructor(vm, vm.names.Object, *m_object_constructor, m_object_prototype); @@ -390,6 +405,7 @@ void Intrinsics::visit_edges(Visitor& visitor) visitor.visit(m_normal_function_prototype_shape); visitor.visit(m_normal_function_shape); visitor.visit(m_native_function_shape); + visitor.visit(m_unmapped_arguments_object_shape); visitor.visit(m_proxy_constructor); visitor.visit(m_async_from_sync_iterator_prototype); visitor.visit(m_async_generator_prototype); @@ -414,6 +430,7 @@ void Intrinsics::visit_edges(Visitor& visitor) visitor.visit(m_json_stringify_function); visitor.visit(m_object_prototype_to_string_function); visitor.visit(m_throw_type_error_function); + visitor.visit(m_throw_type_error_accessor); #define __JS_ENUMERATE(ClassName, snake_name, PrototypeName, ConstructorName, ArrayType) \ visitor.visit(m_##snake_name##_constructor); \ diff --git a/Libraries/LibJS/Runtime/Intrinsics.h b/Libraries/LibJS/Runtime/Intrinsics.h index a6a945264d7..a0a132c78b5 100644 --- a/Libraries/LibJS/Runtime/Intrinsics.h +++ b/Libraries/LibJS/Runtime/Intrinsics.h @@ -40,6 +40,13 @@ public: [[nodiscard]] u32 native_function_length_offset() const { return m_native_function_length_offset; } [[nodiscard]] u32 native_function_name_offset() const { return m_native_function_name_offset; } + [[nodiscard]] GC::Ref unmapped_arguments_object_shape() { return *m_unmapped_arguments_object_shape; } + [[nodiscard]] u32 unmapped_arguments_object_length_offset() const { return m_unmapped_arguments_object_length_offset; } + [[nodiscard]] u32 unmapped_arguments_object_well_known_symbol_iterator_offset() const { return m_unmapped_arguments_object_well_known_symbol_iterator_offset; } + [[nodiscard]] u32 unmapped_arguments_object_callee_offset() const { return m_unmapped_arguments_object_callee_offset; } + + [[nodiscard]] GC::Ref throw_type_error_accessor() { return *m_throw_type_error_accessor; } + // Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype GC::Ref proxy_constructor() { return *m_proxy_constructor; } @@ -157,6 +164,13 @@ private: u32 m_native_function_length_offset { 0 }; u32 m_native_function_name_offset { 0 }; + GC::Ptr m_unmapped_arguments_object_shape; + u32 m_unmapped_arguments_object_length_offset { 0 }; + u32 m_unmapped_arguments_object_well_known_symbol_iterator_offset { 0 }; + u32 m_unmapped_arguments_object_callee_offset { 0 }; + + GC::Ptr m_throw_type_error_accessor; + // Not included in JS_ENUMERATE_NATIVE_OBJECTS due to missing distinct prototype GC::Ptr m_proxy_constructor;