openharmony 鸿蒙 changelogs-arkcompiler

2026-08-25 浏览 (1)

ArkCompiler Subsystem Changelog

cl.arkcompiler.1 Behavior Change for Property Lookup and Setting on Array

Access Level

Public API

Reason for Change

According 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.

Impact of the Change

This change does not require application adaptation.

Before

  • 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.
  • 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).
  • 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.
  • 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.
// Case 1:
function BehaviorChange1() {
// The following provides four methods to modify Array.prototype, making Array.prototype = [233, 233, 233]. Each code block is parallel.
// ----------------- Method 1 -----------------
    let arr1 = new Array(10);
    arr1.__proto__.length = 3;
    arr1.__proto__.fill(233, 0, 3);
// ----------------- Method 1 -----------------

// ----------------- Method 2 -----------------
    let arr1 = new Array(10);
    arr1.__proto__.push(233, 233, 233);
// ----------------- Method 2 -----------------

// ----------------- Method 3 -----------------
    let arr1 = new Array(10);
    arr1.__proto__.length = 3;
    arr1.__proto__.splice(1, 0, 233, 233, 233);
// ----------------- Method 3 -----------------

// ----------------- Method 4 -----------------
    let arr1 = new Array(10);
    arr1.__proto__.unshift(233, 233, 233);
// ----------------- Method 4 -----------------

    let arr2 = new Array(10);
    let arr3 = arr1.concat(arr2);
    print(arr3[11]); // Output: undefined, non-compliant

    let arr4 = arr1.slice(1);
    print(arr4[0]); // Output: undefined, non-compliant

    let res = arr1.at(1);
    print(res); // Output: undefined, non-compliant

    const sum = arr1.reduce((accumulator, currentValue) => {
        return accumulator + currentValue;
    })
    print(sum); // Output: undefined, non-compliant

    arr1.reverse();
    print(arr1[1]); // Output: undefined, non-compliant
}
BehaviorChange1();

// Case 2:
function BehaviorChange2() {
    class MyArray extends Array {}
    let custom = new MyArray(1, 2, 3);
    let result1 = custom.concat([4, 5]);
    print(result1 instanceof MyArray); // Output: false, non-compliant

    let result2 = custom.slice(1);
    print(result2 instanceof MyArray); // Output: false, non-compliant
}
BehaviorChange2()

// Case 3:
function BehaviorChange3() {
    class MyArray extends Array {}
    let arr1 = new MyArray(10);
    MyArray.prototype.__proto__ = [233, 233, 233];
    let arr2 = new Array(10);
    let arr3 = arr1.concat(arr2);
    print(arr3[1]); // Output: undefined, non-compliant

    let arr4 = arr1.slice(1);
    print(arr4[0]); // Output: undefined, non-compliant

    let res = arr1.at(1);
    print(res); // Output: undefined, non-compliant

    const sum = arr1.reduce((accumulator, currentValue) => {
        return accumulator + currentValue;
    })
    print(sum); // Output: undefined, non-compliant

    arr1.reverse();
    print(arr1[1]); // Output: undefined, non-compliant
}
BehaviorChange3();

// Case 4:
function BehaviorChange4() {
    class MyArray extends Array {}
    let arr1 = new MyArray(10);
    MyArray.prototype[0] = 233;
    MyArray.prototype[1] = 233;
    MyArray.prototype[2] = 233;

    let arr2 = new Array(10);
    let arr3 = arr1.concat(arr2);
    print(arr3[1]); // Output: undefined, non-compliant

    let arr4 = arr1.slice(1);
    print(arr4[0]); // Output: undefined, non-compliant

    let res = arr1.at(1);
    print(res); // Output: undefined, non-compliant

    const sum = arr1.reduce((accumulator, currentValue) => {
        return accumulator + currentValue;
    })
    print(sum); // Output: undefined, non-compliant

    arr1.reverse();
    print(arr1[1]); // Output: undefined, non-compliant
}
BehaviorChange4();

After change

  • 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)
  • 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)
  • 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)
  • 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)
// Case 1:
function BehaviorChange1() {
// The following provides four methods to modify Array.prototype, making Array.prototype = [233, 233, 233]. Each code block is parallel.
// ----------------- Method 1 -----------------
    let arr1 = new Array(10);
    arr1.__proto__.length = 3;
    arr1.__proto__.fill(233, 0, 3);
// ----------------- Method 1 -----------------

// ----------------- Method 2 -----------------
    let arr1 = new Array(10);
    arr1.__proto__.push(233, 233, 233);
// ----------------- Method 2 -----------------

// ----------------- Method 3 -----------------
    let arr1 = new Array(10);
    arr1.__proto__.length = 3;
    arr1.__proto__.splice(1, 0, 233, 233, 233);
// ----------------- Method 3 -----------------

// ----------------- Method 4 -----------------
    let arr1 = new Array(10);
    arr1.__proto__.unshift(233, 233, 233);
// ----------------- Method 4 -----------------

    let arr2 = new Array(10);
    let arr3 = arr1.concat(arr2);
    print(arr3[11]); // Output: 233, compliant. concat traverses the prototype chain when the property is not found on the instance.

    let arr4 = arr1.slice(1);
    print(arr4[0]); // Output: 233, compliant. slice traverses the prototype chain when the property is not found on the instance.

    let res = arr1.at(1);
    print(res); // Output: 233, compliant. at traverses the prototype chain when the property is not found on the instance.

    const sum = arr1.reduce((accumulator, currentValue) => {
        return accumulator + currentValue;
    })
    print(sum); // Output: 699, compliant. reduce traverses the prototype chain when the property is not found on the instance.

    arr1.reverse();
    print(arr1[1]); // Output: 233, compliant. reverse traverses the prototype chain when the property is not found on the instance.
}
BehaviorChange1();

// Case 2:
function BehaviorChange2() {
    class MyArray extends Array {}
    let custom = new MyArray(1, 2, 3);
    let result1 = custom.concat([4, 5]);
    print(result1 instanceof MyArray); // Output: true, compliant. constructor on custom is correctly called.

    let result2 = custom.slice(1);
    print(result2 instanceof MyArray); // Output: true, compliant. constructor on custom is correctly called.
}
BehaviorChange2()

// Case 3:
function BehaviorChange3() {
    class MyArray extends Array {}
    let arr1 = new MyArray(10);
    MyArray.prototype.__proto__ = [233, 233, 233];
    let arr2 = new Array(10);
    let arr3 = arr1.concat(arr2);
    print(arr3[1]); // Output: 233, compliant. concat traverses the prototype chain when the property is not found on the instance.

    let arr4 = arr1.slice(1);
    print(arr4[0]); // Output: 233, compliant. slice traverses the prototype chain when the property is not found on the instance.

    let res = arr1.at(1);
    print(res); // Output: 233, compliant. at traverses the prototype chain when the property is not found on the instance.

    const sum = arr1.reduce((accumulator, currentValue) => {
        return accumulator + currentValue;
    })
    print(sum); // Output: 233, compliant. reduce traverses the prototype chain when the property is not found on the instance.

    arr1.reverse();
    print(arr1[1]); // Output: 233, compliant. reverse traverses the prototype chain when the property is not found on the instance.
}
BehaviorChange3();

// Case 4:
function BehaviorChange4() {
    class MyArray extends Array {}
    let arr1 = new MyArray(10);
    MyArray.prototype[0] = 233;
    MyArray.prototype[1] = 233;
    MyArray.prototype[2] = 233;

    let arr2 = new Array(10);
    let arr3 = arr1.concat(arr2);
    print(arr3[1]); // Output: 233, compliant. concat traverses the prototype chain when the property is not found on the instance.

    let arr4 = arr1.slice(1);
    print(arr4[0]); // Output: 233, compliant. slice traverses the prototype chain when the property is not found on the instance.

    let res = arr1.at(1);
    print(res); // Output: 233, compliant. at traverses the prototype chain when the property is not found on the instance.

    const sum = arr1.reduce((accumulator, currentValue) => {
        return accumulator + currentValue;
    })
    print(sum); // Output: 699, compliant. reduce traverses the prototype chain when the property is not found on the instance.

    arr1.reverse();
    print(arr1[1]); // Output: 233, compliant. reverse traverses the prototype chain when the property is not found on the instance.
}
BehaviorChange4();


Start API Level

API 9

Change Since

OpenHarmony 5.1.0.45

Key API/Component Changes

instance of, concat, slice, at, reduce, and reverse APIs in Array

Adaptation Guide

When looking up properties on Array, pay attention to the changes in return values.

你可能感兴趣的鸿蒙文章

openharmony 鸿蒙 changelogs-usbManager

  • 所属分类: 后端技术
  • 本文标签: 软件 鸿蒙
  • 版权声明: 本文链接 https://seaxiang.com/blog/60hHhCkk