!4923 Fix Array.prototype.sort part1

Merge pull request !4923 from xliu/fix_sort
This commit is contained in:
openharmony_ci 2023-09-27 09:22:49 +00:00 committed by Gitee
commit c7dbfbdf8d
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
13 changed files with 335 additions and 140 deletions

View File

@ -366,9 +366,9 @@ JSTaggedValue ArrayHelper::FlattenIntoArray(JSThread *thread, const JSHandle<JSO
return BuiltinsBase::GetTaggedDouble(tempArgs.start);
}
JSTaggedValue ArrayHelper::SortIndexedProperties(JSThread *thread, const JSHandle<JSObject> &thisObj,
int64_t len, const JSHandle<JSTaggedValue> &callbackFnHandle,
HolesType holes)
JSHandle<TaggedArray> ArrayHelper::SortIndexedProperties(JSThread *thread, const JSHandle<JSTaggedValue> &thisObj,
int64_t len, const JSHandle<JSTaggedValue> &callbackFnHandle,
HolesType holes)
{
// 1. Let items be a new empty List.
JSHandle<TaggedArray> items(thread->GetEcmaVM()->GetFactory()->NewTaggedArray(len));
@ -386,33 +386,34 @@ JSTaggedValue ArrayHelper::SortIndexedProperties(JSThread *thread, const JSHandl
// ii. Append kValue to items.
// e. Set k to k + 1.
bool kRead = false;
JSHandle<JSTaggedValue> thisObjVal(thisObj);
JSMutableHandle<JSTaggedValue> pk(thread, JSTaggedValue::Undefined());
int64_t index = 0;
while (k < len) {
if (holes == HolesType::SKIP_HOLES) {
pk.Update(JSTaggedValue(k));
kRead = JSTaggedValue::HasProperty(thread, thisObjVal, pk);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
pk.Update(JSTaggedValue(k));
kRead = JSTaggedValue::HasProperty(thread, thisObj, pk);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, items);
} else {
ASSERT(holes == HolesType::READ_THROUGH_HOLES);
kRead = true;
}
if (kRead) {
JSHandle<JSTaggedValue> kValue = JSArray::FastGetPropertyByValue(thread, thisObjVal, k);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
items->Set(thread, k, kValue.GetTaggedValue());
JSHandle<JSTaggedValue> kValue = JSArray::FastGetPropertyByValue(thread, thisObj, k);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, items);
items->Set(thread, index++, kValue.GetTaggedValue());
}
++k;
}
JSHandle<JSArray> array(JSArray::CreateArrayFromList(thread, items));
JSHandle<JSObject> arrayObj = JSHandle<JSObject>::Cast(array);
if (index < k) {
items->Trim(thread, index);
}
// 4. Sort items using an implementation-defined sequence of calls to SortCompare.
// If any such call returns an abrupt completion,
// stop before performing any further calls to SortCompare and return that Completion Record.
JSArray::Sort(thread, arrayObj, callbackFnHandle);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSArray::SortElements(thread, items, callbackFnHandle);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, items);
// 5. Return items.
return arrayObj.GetTaggedValue();
return items;
}
} // namespace panda::ecmascript::base

View File

@ -70,9 +70,9 @@ public:
const JSHandle<JSTaggedValue> &thisObjVal, const FlattenArgs &args,
const JSHandle<JSTaggedValue> &mapperFunctionHandle,
const JSHandle<JSTaggedValue> &thisArg);
static JSTaggedValue SortIndexedProperties(JSThread *thread, const JSHandle<JSObject> &thisObj,
int64_t len, const JSHandle<JSTaggedValue> &callbackFnHandle,
HolesType holes);
static JSHandle<TaggedArray> SortIndexedProperties(JSThread *thread, const JSHandle<JSTaggedValue> &thisObj,
int64_t len, const JSHandle<JSTaggedValue> &callbackFnHandle,
HolesType holes);
};
} // namespace panda::ecmascript::base

View File

@ -2206,62 +2206,23 @@ JSTaggedValue BuiltinsArray::Some(EcmaRuntimeCallInfo *argv)
JSTaggedValue BuiltinsArray::Sort(EcmaRuntimeCallInfo *argv)
{
ASSERT(argv);
BUILTINS_API_TRACE(argv->GetThread(), Array, Sort);
JSThread *thread = argv->GetThread();
BUILTINS_API_TRACE(thread, Array, Sort);
[[maybe_unused]] EcmaHandleScope handleScope(thread);
// 1. Let obj be ToObject(this value).
JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
JSHandle<JSTaggedValue> callbackFnHandle = GetCallArg(argv, 0);
if (!callbackFnHandle->IsUndefined() && !callbackFnHandle->IsCallable()) {
THROW_TYPE_ERROR_AND_RETURN(thread, "Callable is false", JSTaggedValue::Exception());
}
// 2. Let len be ToLength(Get(obj, "length")).
int64_t len = ArrayHelper::GetArrayLength(thread, JSHandle<JSTaggedValue>(thisObjHandle));
// 3. ReturnIfAbrupt(len).
// 2. Let obj be ToObject(this value).
JSHandle<JSTaggedValue> thisHandle = GetThis(argv);
JSHandle<JSObject> thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSMutableHandle<JSTaggedValue> presentValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> middleValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> previousValue(thread, JSTaggedValue::Undefined());
for (int i = 1; i < len; i++) {
int beginIndex = 0;
int endIndex = i;
presentValue.Update(ObjectFastOperator::FastGetPropertyByIndex<true>(thread, thisObjHandle.GetTaggedValue(), i));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
while (beginIndex < endIndex) {
int middleIndex = (beginIndex + endIndex) / 2; // 2 : half
middleValue.Update(
ObjectFastOperator::FastGetPropertyByIndex<true>(thread, thisObjHandle.GetTaggedValue(), middleIndex));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
double compareResult = ArrayHelper::SortCompare(thread, callbackFnHandle, middleValue, presentValue);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
if (compareResult > 0) {
endIndex = middleIndex;
} else {
beginIndex = middleIndex + 1;
}
}
if (endIndex >= 0 && endIndex < i) {
for (int j = i; j > endIndex; j--) {
previousValue.Update(
ObjectFastOperator::FastGetPropertyByIndex<true>(thread, thisObjHandle.GetTaggedValue(), j - 1));
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
ObjectFastOperator::FastSetPropertyByIndex(thread, thisObjHandle.GetTaggedValue(), j,
previousValue.GetTaggedValue());
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
ObjectFastOperator::FastSetPropertyByIndex(thread, thisObjHandle.GetTaggedValue(), endIndex,
presentValue.GetTaggedValue());
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
}
}
// Array sort
JSArray::Sort(thread, JSHandle<JSTaggedValue>::Cast(thisObjHandle), callbackFnHandle);
return thisObjHandle.GetTaggedValue();
}
@ -3064,20 +3025,20 @@ JSTaggedValue BuiltinsArray::ToSorted(EcmaRuntimeCallInfo *argv)
// the following steps when called:
// a. Return ? CompareArrayElements(x, y, comparefn).
// 6. Let sortedList be ? SortIndexedProperties(O, len, SortCompare, read-through-holes).
JSTaggedValue sortedList = ArrayHelper::SortIndexedProperties(thread, thisObjHandle, len, callbackFnHandle,
base::HolesType::READ_THROUGH_HOLES);
JSHandle<TaggedArray> sortedList =
ArrayHelper::SortIndexedProperties(thread, JSHandle<JSTaggedValue>::Cast(thisObjHandle), len, callbackFnHandle,
base::HolesType::READ_THROUGH_HOLES);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSHandle<JSTaggedValue> sortedArray(thread, sortedList);
//7. Let j be 0.
int64_t j = 0;
// 8. Repeat, while j < len,
// a. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(j)), sortedList[j]).
// b. Set j to j + 1.
JSMutableHandle<JSTaggedValue> itemValue(thread, JSTaggedValue::Undefined());
while (j < len) {
JSHandle<JSTaggedValue> item = JSArray::FastGetPropertyByValue(thread, sortedArray, j);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, j, item);
itemValue.Update(sortedList->Get(j));
JSObject::CreateDataPropertyOrThrow(thread, newArrayHandle, j, itemValue);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
++j;
}

View File

@ -24,6 +24,8 @@
#include "ecmascript/object_fast_operator-inl.h"
namespace panda::ecmascript {
using base::ArrayHelper;
JSTaggedValue JSArray::LengthGetter([[maybe_unused]] JSThread *thread, const JSHandle<JSObject> &self)
{
return JSTaggedValue(JSArray::Cast(*self)->GetLength());
@ -387,30 +389,67 @@ bool JSArray::FastSetPropertyByValue(JSThread *thread, const JSHandle<JSTaggedVa
value.GetTaggedValue());
}
void JSArray::Sort(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &fn)
// ecma2024 23.1.3.20 Array.prototype.sort(comparefn)
JSTaggedValue JSArray::Sort(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &fn)
{
if (!fn->IsUndefined() && !fn->IsCallable()) {
THROW_TYPE_ERROR(thread, "Callable is false");
ASSERT(fn->IsUndefined() || fn->IsCallable());
// 3. Let len be ?LengthOfArrayLike(obj).
int64_t len = ArrayHelper::GetArrayLength(thread, obj);
// ReturnIfAbrupt(len).
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 4. Let SortCompare be a new Abstract Closure with parameters (x, y) that captures comparefn and performs
// the following steps when called:
// a. Return ? CompareArrayElements(x, y, comparefn).
// 5. Let sortedList be ? SortIndexedProperties(O, len, SortCompare, SKIP-HOLES).
JSHandle<TaggedArray> sortedList =
ArrayHelper::SortIndexedProperties(thread, obj, len, fn, base::HolesType::SKIP_HOLES);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
// 6. Let itemCount be the number of elements in sortedList.
uint32_t itemCount = sortedList->GetLength();
// 7. Let j be 0.
uint32_t j = 0;
// 8. Repeat, while j < itemCount,
// a. Perform ! Set(obj, ! ToString((j)), sortedList[j], true).
// b. Set j to j + 1.
JSMutableHandle<JSTaggedValue> item(thread, JSTaggedValue::Undefined());
while (j < itemCount) {
item.Update(sortedList->Get(j));
JSArray::FastSetPropertyByValue(thread, obj, j, item);
ASSERT_NO_ABRUPT_COMPLETION(thread);
++j;
}
// 9. NOTE: The call to SortIndexedProperties in step 5 uses SKIP-HOLES.The remaining indices are deleted to
// preserve the number of holes that were detected and excluded from the sort.
// 10. Repeat, while j < len,
// a. Perform ? DeletePropertyOrThrow(obj, ! ToString((j))).
// b. Set j to j + 1.
while (j < len) {
item.Update(JSTaggedValue(j));
JSTaggedValue::DeletePropertyOrThrow(thread, obj, item);
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
++j;
}
// 2. Let len be ToLength(Get(obj, "length")).
int64_t len = base::ArrayHelper::GetArrayLength(thread, JSHandle<JSTaggedValue>(obj));
// 3. ReturnIfAbrupt(len).
RETURN_IF_ABRUPT_COMPLETION(thread);
return obj.GetTaggedValue();
}
void JSArray::SortElements(JSThread *thread, const JSHandle<TaggedArray> &elements, const JSHandle<JSTaggedValue> &fn)
{
ASSERT(fn->IsUndefined() || fn->IsCallable());
JSMutableHandle<JSTaggedValue> presentValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> middleValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> previousValue(thread, JSTaggedValue::Undefined());
for (int64_t i = 1; i < len; i++) {
int64_t beginIndex = 0;
int64_t endIndex = i;
presentValue.Update(ObjectFastOperator::FastGetPropertyByIndex<true>(thread, obj.GetTaggedValue(), i));
RETURN_IF_ABRUPT_COMPLETION(thread);
uint32_t len = elements->GetLength();
for (uint32_t i = 1; i < len; i++) {
uint32_t beginIndex = 0;
uint32_t endIndex = i;
presentValue.Update(elements->Get(i));
while (beginIndex < endIndex) {
int64_t middleIndex = (beginIndex + endIndex) / 2; // 2 : half
middleValue.Update(
ObjectFastOperator::FastGetPropertyByIndex<true>(thread, obj.GetTaggedValue(), middleIndex));
RETURN_IF_ABRUPT_COMPLETION(thread);
uint32_t middleIndex = (beginIndex + endIndex) / 2; // 2 : half
middleValue.Update(elements->Get(middleIndex));
int32_t compareResult = base::ArrayHelper::SortCompare(thread, fn, middleValue, presentValue);
RETURN_IF_ABRUPT_COMPLETION(thread);
if (compareResult > 0) {
@ -421,17 +460,11 @@ void JSArray::Sort(JSThread *thread, const JSHandle<JSObject> &obj, const JSHand
}
if (endIndex >= 0 && endIndex < i) {
for (int64_t j = i; j > endIndex; j--) {
previousValue.Update(
ObjectFastOperator::FastGetPropertyByIndex<true>(thread, obj.GetTaggedValue(), j - 1));
RETURN_IF_ABRUPT_COMPLETION(thread);
ObjectFastOperator::FastSetPropertyByIndex(thread, obj.GetTaggedValue(), j,
previousValue.GetTaggedValue());
RETURN_IF_ABRUPT_COMPLETION(thread);
for (uint32_t j = i; j > endIndex; j--) {
previousValue.Update(elements->Get(j - 1));
elements->Set(thread, j, previousValue);
}
ObjectFastOperator::FastSetPropertyByIndex(thread, obj.GetTaggedValue(), endIndex,
presentValue.GetTaggedValue());
RETURN_IF_ABRUPT_COMPLETION(thread);
elements->Set(thread, endIndex, presentValue);
}
}
}

View File

@ -91,13 +91,15 @@ public:
static bool FastSetPropertyByValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value);
static void Sort(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &fn);
static JSTaggedValue Sort(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &fn);
static bool IncludeInSortedValue(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
const JSHandle<JSTaggedValue> &value);
static JSHandle<TaggedArray> ToTaggedArray(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
static void CheckAndCopyArray(const JSThread *thread, JSHandle<JSArray> obj);
static void SetCapacity(JSThread *thread, const JSHandle<JSObject> &array, uint32_t oldLen, uint32_t newLen,
bool isNew = false);
static void SortElements(JSThread *thread, const JSHandle<TaggedArray> &elements,
const JSHandle<JSTaggedValue> &fn);
};
class TrackInfo : public TaggedObject {

View File

@ -45,7 +45,7 @@ JSHandle<ModuleNamespace> ModuleNamespace::ModuleNamespaceCreate(JSThread *threa
// are ordered as if an Array of the same values had been sorted using
// Array.prototype.sort using undefined as comparefn.
JSHandle<JSArray> exportsArray = JSArray::CreateArrayFromList(thread, exports);
JSHandle<JSObject> sortedExports = JSHandle<JSObject>::Cast(exportsArray);
JSHandle<JSTaggedValue> sortedExports = JSHandle<JSTaggedValue>::Cast(exportsArray);
JSHandle<JSTaggedValue> fn = globalConst->GetHandledUndefined();
JSArray::Sort(thread, sortedExports, fn);
// 8. Set M.[[Exports]] to sortedExports.

View File

@ -479,12 +479,11 @@ JSTaggedValue ObjectFastOperator::FastGetPropertyByValue(JSThread *thread, JSTag
return result;
}
template<bool UseHole> // UseHole is only for Array::Sort() which requires Hole order
JSTaggedValue ObjectFastOperator::FastGetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index)
{
INTERPRETER_TRACE(thread, FastGetPropertyByIndex);
JSTaggedValue result = ObjectFastOperator::GetPropertyByIndex(thread, receiver, index);
if (result.IsHole() && !UseHole) {
if (result.IsHole()) {
return JSTaggedValue::GetProperty(thread,
JSHandle<JSTaggedValue>(thread, receiver), index).GetValue().GetTaggedValue();
}

View File

@ -55,7 +55,6 @@ public:
static inline JSTaggedValue FastGetPropertyByValue(JSThread *thread, JSTaggedValue receiver, JSTaggedValue key);
template<bool UseHole = false>
static inline JSTaggedValue FastGetPropertyByIndex(JSThread *thread, JSTaggedValue receiver, uint32_t index);
static inline JSTaggedValue FastParseDate(const EcmaString *str);
@ -105,4 +104,4 @@ private:
friend class FastRuntimeStub;
};
} // namespace panda::ecmascript
#endif // ECMASCRIPT_OBJECT_FAST_OPERATOR_H
#endif // ECMASCRIPT_OBJECT_FAST_OPERATOR_H

View File

@ -2579,45 +2579,8 @@ JSTaggedValue RuntimeStubs::RuntimeArraySort(JSThread *thread, JSHandle<JSTagged
}
}
JSMutableHandle<JSTaggedValue> presentValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> middleValue(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> previousValue(thread, JSTaggedValue::Undefined());
JSHandle<JSTaggedValue> callbackFnHandle(thread, JSTaggedValue::Undefined());
for (int i = 1; i < len; i++) {
int beginIndex = 0;
int endIndex = i;
presentValue.Update(
ObjectFastOperator::FastGetPropertyByIndex<true>(thread, thisObjHandle.GetTaggedValue(), i));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
while (beginIndex < endIndex) {
int middleIndex = beginIndex + (endIndex - beginIndex) / 2; // 2 : half
middleValue.Update(
ObjectFastOperator::FastGetPropertyByIndex<true>(thread, thisObjHandle.GetTaggedValue(), middleIndex));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
double compareResult = ArrayHelper::SortCompare(thread, callbackFnHandle, middleValue, presentValue);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
if (compareResult > 0) {
endIndex = middleIndex;
} else {
beginIndex = middleIndex + 1;
}
}
if (endIndex >= 0 && endIndex < i) {
for (int j = i; j > endIndex; j--) {
previousValue.Update(
ObjectFastOperator::FastGetPropertyByIndex<true>(thread, thisObjHandle.GetTaggedValue(), j - 1));
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
ObjectFastOperator::FastSetPropertyByIndex(thread, thisObjHandle.GetTaggedValue(), j,
previousValue.GetTaggedValue());
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
}
ObjectFastOperator::FastSetPropertyByIndex(thread, thisObjHandle.GetTaggedValue(), endIndex,
presentValue.GetTaggedValue());
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
}
}
JSArray::Sort(thread, JSHandle<JSTaggedValue>::Cast(thisObjHandle), callbackFnHandle);
return thisObjHandle.GetTaggedValue();
}

View File

@ -23,6 +23,7 @@ group("ark_js_moduletest") {
"arraytoreversed",
"arraytospliced",
"arraywith",
"arraysort",
"arrayprotochange",
"assignproxy",
"async",
@ -152,6 +153,7 @@ group("ark_asm_test") {
"arrayfindlast",
"arrayforeach",
"arrayjoin",
"arraysort",
"arrayprotochange",
"asmstackoverflow",
"assignproxy",

View File

@ -0,0 +1,18 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_moduletest_action("arraysort") {
deps = []
}

View File

@ -0,0 +1,178 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class DeepProxy {
constructor(obj, handler) {
return new Proxy(obj, handler);
}
}
class ClassB {
constructor(n) {
this.n = 0;
this.n = n;
}
}
let nextFreeId = 0;
class ClassA {
constructor(a, b) {
this.a = a;
this.b = new ClassB(b);
this.id = nextFreeId++;
}
}
// Testing the proxy situation.
let data1 = [new ClassA(1, 10), new ClassA(3, 30), new ClassA(4, 40), new ClassA(2, 20), new ClassA(11, 250)];
let objHandler1 = new DeepProxy(data1, {});
print(JSON.stringify(objHandler1));
objHandler1.sort((a, b) => {
return a.b.n - b.b.n;
})
print(JSON.stringify(objHandler1));
// Testing cases with both proxy and hole.
let data2 = [new ClassA(1, 10), , new ClassA(3, 30), , new ClassA(4, 40), new ClassA(2, 20), new ClassA(11, 250)];
let objHandler2 = new DeepProxy(data2, {
deleteProperty(target, prop) {
print(`delete ${prop.toString()}`);
return Reflect.deleteProperty(target, prop);
}
});
objHandler2.sort((a, b) => {
return a.b.n - b.b.n;
})
print(JSON.stringify(objHandler2));
/*
* Test Case Description:
* 1. This use case is used to verify the logical processing order of the binary insertion sorting algorithm.
* 2. If there are any changes to the use case, please confirm if the use case needs to be modified.
*/
let arr1 = [1, 3, 2];
arr1.sort((a, b) => {
print(`comparing a = ${a}, b = ${b}`);
return a - b;
});
print(JSON.stringify(arr1));
// Modification of objects during the comparison process.
let arr2 = [1, 3, 2];
arr2.sort((a, b) => {
if (a == 1 || b == 1) {
arr2[0] == 2;
}
return a - b;
});
print(JSON.stringify(arr2));
let arr3 = [1, 3, 2];
arr3.sort((a, b) => {
if (a == 1 || b == 1) {
arr3[4] == 2;
}
return a - b;
});
print(JSON.stringify(arr3));
// Testing the situation where this is an Object
let obj1 = {0: 1, 1: 3, a: 6, 2: 2, length: 3};
Array.prototype.sort.call(obj1, (a, b) => {
return a - b;
});
print(JSON.stringify(obj1));
let obj2 = {0: 1, 1: 3, a: 6, 2: 2, length: 3};
Array.prototype.sort.call(obj2, (a, b) => {
if (a == 1 || b == 1) {
obj2.a = 60;
}
return a - b;
});
print(obj2.a == 60);
print(JSON.stringify(obj2));
let obj3 = {0: 1, 1: 3, a: 6, 2: 2, length: 2};
Array.prototype.sort.call(obj3, (a, b) => {
return a - b;
});
print(obj3[1] == 3)
print(JSON.stringify(obj3));
let obj4 = {0: 1, 1: 3, a: 6, 3: 2, length: 4};
Array.prototype.sort.call(obj4, (a, b) => {
return a - b;
});
print(obj4[2] == 3)
print(JSON.stringify(obj4));
// Test if this is a Map type;
let map1 = new Map();
map1.set(0, 1);
map1.set(1, 3);
map1.set(2, 2);
map1.set("a", 6);
map1.set("length", 3);
Array.prototype.sort.call(map1, (a, b) => {
return a - b;
});
print(JSON.stringify(map1));
let map2 = new Map();
map2.set(0, 1);
map2.set(1, 3);
map2.set(2, 2);
map2.set("a", 6);
map2.set("length", 3);
Array.prototype.sort.call(map2, (a, b) => {
if (a == 1 || b == 1) {
map2.set("a", 60);
}
return a - b;
});
print(JSON.stringify(map2));
// Test prototype
let child1 = [1, 3, 2];
let proto1 = [4, 7, 5];
child1.__proto__ = proto1;
child1.sort((a, b) => {
return a - b;
});
print(JSON.stringify(child1));
let child2 = [1, , 2];
child2.__proto__ = proto1;
child2.sort((a, b) => {
return a - b;
});
print(child2.hasOwnProperty('1'));
print(JSON.stringify(child2));
let child3 = [1, 3, 2];
let proto2 = [4, , 5];
child3.__proto__ = proto2;
child3.sort((a, b) => {
return a - b;
});
print(JSON.stringify(child3));
let child4 = [1, , 2];
child4.__proto__ = proto2;
child4.sort((a, b) => {
return a - b;
});
print(child4.hasOwnProperty('2'));
print(JSON.stringify(child4));

View File

@ -0,0 +1,39 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[{"a":1,"b":{"n":10},"id":0},{"a":3,"b":{"n":30},"id":1},{"a":4,"b":{"n":40},"id":2},{"a":2,"b":{"n":20},"id":3},{"a":11,"b":{"n":250},"id":4}]
[{"a":1,"b":{"n":10},"id":0},{"a":2,"b":{"n":20},"id":3},{"a":3,"b":{"n":30},"id":1},{"a":4,"b":{"n":40},"id":2},{"a":11,"b":{"n":250},"id":4}]
delete 5
delete 6
[{"a":1,"b":{"n":10},"id":5},{"a":2,"b":{"n":20},"id":8},{"a":3,"b":{"n":30},"id":6},{"a":4,"b":{"n":40},"id":7},{"a":11,"b":{"n":250},"id":9},null,null]
comparing a = 1, b = 3
comparing a = 3, b = 2
comparing a = 1, b = 2
[1,2,3]
[1,2,3]
[1,2,3]
{"0":1,"1":2,"2":3,"a":6,"length":3}
true
{"0":1,"1":2,"2":3,"a":60,"length":3}
true
{"0":1,"1":3,"2":2,"a":6,"length":2}
true
{"0":1,"1":2,"2":3,"a":6,"length":4}
{}
{}
[1,2,3]
true
[1,2,7]
[1,2,3]
false
[1,2,5]