diff --git a/core/engine/src/builtins/array/mod.rs b/core/engine/src/builtins/array/mod.rs index ebbc0c80f9c..91abcd0acd4 100644 --- a/core/engine/src/builtins/array/mod.rs +++ b/core/engine/src/builtins/array/mod.rs @@ -3424,6 +3424,33 @@ fn array_exotic_define_own_property( // 3. Else if P is an array index, then PropertyKey::Index(index) => { let index = index.get(); + let new_len = index + 1; + + // Optimization: If the shape of the object is the array template shape, + // we know the position of the "length" property. + if u64::from(new_len) < (2u64.pow(32) - 1) { + let borrowed_object = obj.borrow(); + if borrowed_object.properties().shape.to_addr_usize() + == context + .intrinsics() + .templates() + .array() + .shape() + .to_addr_usize() + { + let old_len = borrowed_object.properties().storage[0].clone(); + drop(borrowed_object); + let old_len = old_len.to_u32(context)?; + if new_len >= old_len { + if ordinary_define_own_property(obj, key, desc, context)? { + let mut borrowed_object = obj.borrow_mut(); + borrowed_object.properties_mut().storage[0] = JsValue::new(new_len); + return Ok(true); + } + return Ok(false); + } + } + } // a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length"). let old_len_desc = @@ -3455,7 +3482,7 @@ fn array_exotic_define_own_property( if index >= old_len { // i. Set oldLenDesc.[[Value]] to index + 1𝔽. let old_len_desc = PropertyDescriptor::builder() - .value(index + 1) + .value(new_len) .maybe_writable(old_len_desc.writable()) .maybe_enumerable(old_len_desc.enumerable()) .maybe_configurable(old_len_desc.configurable());