1# ArkCompiler Subsystem Changelog 2 3## cl.arkcompiler.1 Behavior Change for Property Lookup and Setting on Array 4 5**Access Level** 6 7Public API 8 9**Reason for Change** 10 11According to the ECMAScript specification, when certain properties are queried on Array instances and these properties do not exist on the Array instance itself, the prototype chain should be traversed to perform the query. Some non-StableArrays are mistakenly identified as StableArrays. As a result, the prototype chain query is skipped, and the query result is inconsistent with the expected outcomes defined by the ECMAScript specification. 12 13**Impact of the Change** 14 15This change does not require application adaptation. 16 17**Before** 18 19- Case 1: When an object (o) is an instance of the Array type and (Array.prototype) is modified using specific methods (**fill**, **push**, **splice**, or **unshift**), certain APIs (**concat**, **slice**, **at**, **reduce**, or **reverse**) cannot correctly read elements from (o) on (Array.prototype), returning an incorrect result. 20- Case 2: When a class MyArray inherits from Array and an object (o) is an instance of MyArray, the constructor property on (o) is not correctly invoked, leading to incorrect results when calling **instance of** on (o). 21- Case 3: When a class MyArray inherits from Array, an object (o) is an instance of MyArray, and MyArray.prototype.proto is modified, certain APIs (**concat**, **slice**, **at**, **reduce**, or **reverse**) cannot correctly read elements from (o) on MyArray.prototype.proto, returning an incorrect result. 22- Case 4: When a class MyArray inherits from Array, an object (o) is an instance of MyArray, and an element is inserted to (MyArray.prototype), certain APIs (**concat**, **slice**, **at**, **reduce**, or **reverse**) cannot correctly read elements from (o) on (MyArray.prototype), returning an incorrect result. 23 24```js 25// Case 1: 26function BehaviorChange1() { 27// The following provides four methods to modify Array.prototype, making Array.prototype = [233, 233, 233]. Each code block is parallel. 28// ----------------- Method 1 ----------------- 29 let arr1 = new Array(10); 30 arr1.__proto__.length = 3; 31 arr1.__proto__.fill(233, 0, 3); 32// ----------------- Method 1 ----------------- 33 34// ----------------- Method 2 ----------------- 35 let arr1 = new Array(10); 36 arr1.__proto__.push(233, 233, 233); 37// ----------------- Method 2 ----------------- 38 39// ----------------- Method 3 ----------------- 40 let arr1 = new Array(10); 41 arr1.__proto__.length = 3; 42 arr1.__proto__.splice(1, 0, 233, 233, 233); 43// ----------------- Method 3 ----------------- 44 45// ----------------- Method 4 ----------------- 46 let arr1 = new Array(10); 47 arr1.__proto__.unshift(233, 233, 233); 48// ----------------- Method 4 ----------------- 49 50 let arr2 = new Array(10); 51 let arr3 = arr1.concat(arr2); 52 print(arr3[11]); // Output: undefined, non-compliant 53 54 let arr4 = arr1.slice(1); 55 print(arr4[0]); // Output: undefined, non-compliant 56 57 let res = arr1.at(1); 58 print(res); // Output: undefined, non-compliant 59 60 const sum = arr1.reduce((accumulator, currentValue) => { 61 return accumulator + currentValue; 62 }) 63 print(sum); // Output: undefined, non-compliant 64 65 arr1.reverse(); 66 print(arr1[1]); // Output: undefined, non-compliant 67} 68BehaviorChange1(); 69 70// Case 2: 71function BehaviorChange2() { 72 class MyArray extends Array {} 73 let custom = new MyArray(1, 2, 3); 74 let result1 = custom.concat([4, 5]); 75 print(result1 instanceof MyArray); // Output: false, non-compliant 76 77 let result2 = custom.slice(1); 78 print(result2 instanceof MyArray); // Output: false, non-compliant 79} 80BehaviorChange2() 81 82// Case 3: 83function BehaviorChange3() { 84 class MyArray extends Array {} 85 let arr1 = new MyArray(10); 86 MyArray.prototype.__proto__ = [233, 233, 233]; 87 let arr2 = new Array(10); 88 let arr3 = arr1.concat(arr2); 89 print(arr3[1]); // Output: undefined, non-compliant 90 91 let arr4 = arr1.slice(1); 92 print(arr4[0]); // Output: undefined, non-compliant 93 94 let res = arr1.at(1); 95 print(res); // Output: undefined, non-compliant 96 97 const sum = arr1.reduce((accumulator, currentValue) => { 98 return accumulator + currentValue; 99 }) 100 print(sum); // Output: undefined, non-compliant 101 102 arr1.reverse(); 103 print(arr1[1]); // Output: undefined, non-compliant 104} 105BehaviorChange3(); 106 107// Case 4: 108function BehaviorChange4() { 109 class MyArray extends Array {} 110 let arr1 = new MyArray(10); 111 MyArray.prototype[0] = 233; 112 MyArray.prototype[1] = 233; 113 MyArray.prototype[2] = 233; 114 115 let arr2 = new Array(10); 116 let arr3 = arr1.concat(arr2); 117 print(arr3[1]); // Output: undefined, non-compliant 118 119 let arr4 = arr1.slice(1); 120 print(arr4[0]); // Output: undefined, non-compliant 121 122 let res = arr1.at(1); 123 print(res); // Output: undefined, non-compliant 124 125 const sum = arr1.reduce((accumulator, currentValue) => { 126 return accumulator + currentValue; 127 }) 128 print(sum); // Output: undefined, non-compliant 129 130 arr1.reverse(); 131 print(arr1[1]); // Output: undefined, non-compliant 132} 133BehaviorChange4(); 134``` 135**After change** 136 137- Case 1: When an object (o) is an instance of the Array type and (Array.prototype) is modified using specific methods (**fill**, **push**, **splice**, or **unshift**), the APIs (**concat**, **slice**, **at**, **reduce**, or **reverse**) can correctly read elements from (o) on (Array.prototype), returning the correct result. (incompatible change) 138- Case 2: When a class MyArray inherits from Array and an object (o) is an instance of MyArray, the constructor property on (o) is not correctly invoked, leading to correct results when calling **instance of** on (o). (incompatible change) 139- Case 3: When a class MyArray inherits from Array, an object (o) is an instance of MyArray, and MyArray.prototype.proto is modified, the APIs (**concat**, **slice**, **at**, **reduce**, or **reverse**) can correctly read elements from (o) on MyArray.prototype.proto, returning the correct result. (incompatible change) 140- Case 4: When a class MyArray inherits from Array, an object (o) is an instance of MyArray, and an element is inserted to (MyArray.prototype), the APIs (**concat**, **slice**, **at**, **reduce**, or **reverse**) can correctly read elements from (o) on (MyArray.prototype), returning the correct result. (incompatible change) 141 142```js 143// Case 1: 144function BehaviorChange1() { 145// The following provides four methods to modify Array.prototype, making Array.prototype = [233, 233, 233]. Each code block is parallel. 146// ----------------- Method 1 ----------------- 147 let arr1 = new Array(10); 148 arr1.__proto__.length = 3; 149 arr1.__proto__.fill(233, 0, 3); 150// ----------------- Method 1 ----------------- 151 152// ----------------- Method 2 ----------------- 153 let arr1 = new Array(10); 154 arr1.__proto__.push(233, 233, 233); 155// ----------------- Method 2 ----------------- 156 157// ----------------- Method 3 ----------------- 158 let arr1 = new Array(10); 159 arr1.__proto__.length = 3; 160 arr1.__proto__.splice(1, 0, 233, 233, 233); 161// ----------------- Method 3 ----------------- 162 163// ----------------- Method 4 ----------------- 164 let arr1 = new Array(10); 165 arr1.__proto__.unshift(233, 233, 233); 166// ----------------- Method 4 ----------------- 167 168 let arr2 = new Array(10); 169 let arr3 = arr1.concat(arr2); 170 print(arr3[11]); // Output: 233, compliant. concat traverses the prototype chain when the property is not found on the instance. 171 172 let arr4 = arr1.slice(1); 173 print(arr4[0]); // Output: 233, compliant. slice traverses the prototype chain when the property is not found on the instance. 174 175 let res = arr1.at(1); 176 print(res); // Output: 233, compliant. at traverses the prototype chain when the property is not found on the instance. 177 178 const sum = arr1.reduce((accumulator, currentValue) => { 179 return accumulator + currentValue; 180 }) 181 print(sum); // Output: 699, compliant. reduce traverses the prototype chain when the property is not found on the instance. 182 183 arr1.reverse(); 184 print(arr1[1]); // Output: 233, compliant. reverse traverses the prototype chain when the property is not found on the instance. 185} 186BehaviorChange1(); 187 188// Case 2: 189function BehaviorChange2() { 190 class MyArray extends Array {} 191 let custom = new MyArray(1, 2, 3); 192 let result1 = custom.concat([4, 5]); 193 print(result1 instanceof MyArray); // Output: true, compliant. constructor on custom is correctly called. 194 195 let result2 = custom.slice(1); 196 print(result2 instanceof MyArray); // Output: true, compliant. constructor on custom is correctly called. 197} 198BehaviorChange2() 199 200// Case 3: 201function BehaviorChange3() { 202 class MyArray extends Array {} 203 let arr1 = new MyArray(10); 204 MyArray.prototype.__proto__ = [233, 233, 233]; 205 let arr2 = new Array(10); 206 let arr3 = arr1.concat(arr2); 207 print(arr3[1]); // Output: 233, compliant. concat traverses the prototype chain when the property is not found on the instance. 208 209 let arr4 = arr1.slice(1); 210 print(arr4[0]); // Output: 233, compliant. slice traverses the prototype chain when the property is not found on the instance. 211 212 let res = arr1.at(1); 213 print(res); // Output: 233, compliant. at traverses the prototype chain when the property is not found on the instance. 214 215 const sum = arr1.reduce((accumulator, currentValue) => { 216 return accumulator + currentValue; 217 }) 218 print(sum); // Output: 233, compliant. reduce traverses the prototype chain when the property is not found on the instance. 219 220 arr1.reverse(); 221 print(arr1[1]); // Output: 233, compliant. reverse traverses the prototype chain when the property is not found on the instance. 222} 223BehaviorChange3(); 224 225// Case 4: 226function BehaviorChange4() { 227 class MyArray extends Array {} 228 let arr1 = new MyArray(10); 229 MyArray.prototype[0] = 233; 230 MyArray.prototype[1] = 233; 231 MyArray.prototype[2] = 233; 232 233 let arr2 = new Array(10); 234 let arr3 = arr1.concat(arr2); 235 print(arr3[1]); // Output: 233, compliant. concat traverses the prototype chain when the property is not found on the instance. 236 237 let arr4 = arr1.slice(1); 238 print(arr4[0]); // Output: 233, compliant. slice traverses the prototype chain when the property is not found on the instance. 239 240 let res = arr1.at(1); 241 print(res); // Output: 233, compliant. at traverses the prototype chain when the property is not found on the instance. 242 243 const sum = arr1.reduce((accumulator, currentValue) => { 244 return accumulator + currentValue; 245 }) 246 print(sum); // Output: 699, compliant. reduce traverses the prototype chain when the property is not found on the instance. 247 248 arr1.reverse(); 249 print(arr1[1]); // Output: 233, compliant. reverse traverses the prototype chain when the property is not found on the instance. 250} 251BehaviorChange4(); 252 253 254``` 255 256**Start API Level** 257 258API 9 259 260**Change Since** 261 262OpenHarmony 5.1.0.45 263 264**Key API/Component Changes** 265 266**instance of**, **concat**, **slice**, **at**, **reduce**, and **reverse** APIs in Array 267 268**Adaptation Guide** 269 270When looking up properties on Array, pay attention to the changes in return values. 271