1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16print('======== Testing fromIndex ========'); 17{ 18 const arr = [-10, 42, 42, 42, 42, -20]; 19 const numberIndices = [ 20 4, 4.1, 4.5, 4.9, // All truncated to 4 21 -0, -0.1, -0.5, -0.9, -1 + Number.EPSILON, // All truncated to 0 22 -1, -1.1, -1.5, -1.9, -2 + Number.EPSILON, // All truncated to -1 23 1/0, -1/0, 0/0, NaN, // +inf, -inf, NaN, NaN 24 ]; 25 const objN = { valueOf() { return 2; } }; 26 const objS = { valueOf() { return "3.456" } }; 27 const objB = { valueOf() { return 4n; } }; 28 const objNN = { valueOf() { return objN; } }; 29 const nonNumberIndices = [ 30 null, undefined, 31 "1", "1.234", "2.0?", "~3.0~", 32 new Number(2), 33 objN, 34 new String("3.123"), 35 objS, 36 objNN, 37 ]; 38 const erroneousIndices = [ 39 4n, objB, 40 ]; 41 42 for (const fnName of ['indexOf', 'lastIndexOf', 'includes']) { 43 print(`---- Testing Array.prototype.${fnName} ----`); 44 const fn = Array.prototype[fnName]; 45 print(`Result with numberIndices: ${numberIndices.map((i) => fn.call(arr, 42, i))}`); 46 print(`Result with nonNumberIndices: ${nonNumberIndices.map((i) => fn.call(arr, 42, i))}`); 47 for (const i of erroneousIndices) { 48 try { 49 const result = fn.call(arr, 42, i); 50 print(`Unexpected result: ${result} (Expects: TypeError)`); 51 } catch (e) { 52 if (e instanceof TypeError) { 53 print(`OK: TypeError raised for ${typeof i} index`); 54 } else { 55 print(`ERROR: Unexpected type of exception raised`); 56 throw e; 57 } 58 } 59 } 60 } 61} 62 63print('======== Testing comparision ========'); 64{ 65 const obj = { x: 1, y: 2 }; 66 const objN = { valueOf() { return 0; } }; 67 const arr = [ 68 1, 1.0, -1.0, // 1 69 0, 0.0, -0.0, // 0 70 1/0, -1/0, // inf 71 0/0, NaN, // NaN 72 true, false, null, // Special values 73 /* hole */, 74 "1", "0", "1.0", "0.0", // string 75 1n, 0n, // bigint 76 obj, objN, // object 77 new Number(0), // Boxing number 78 new String("1"), // Boxing string 79 ]; 80 const targets = [ 81 1, 1.0, -1.0, // 1 82 0, 0.0, -0.0, // 0 83 1/0, -1/0, // inf 84 0/0, NaN, // NaN 85 true, false, null, undefined, // Special values 86 "1", "0", "1.0", "0.0", // string 87 1n, 0n, // bigint 88 obj, objN, // object 89 Math.sqrt(-1), // Another NaN 90 { x: 1, y: 2 }, // Another object 91 { valueOf() { return 0; } }, // Another object 92 new Number(0), // Boxing number 93 new String("1"), // Boxing string 94 ]; 95 for (let i = 0; i < targets.length; i++) { 96 const x = targets[i]; 97 const res1 = arr.indexOf(x); 98 const res2 = arr.lastIndexOf(x); 99 const res3 = arr.includes(x); 100 print(`[${i}] Target = ${x} (${typeof x}): indexOf => ${res1} lastIndexOf => ${res2} includes => ${res3}`); 101 } 102 // Fills the hole with undefined 103 arr[12] = undefined; 104 { 105 const res1 = arr.indexOf(undefined); 106 const res2 = arr.lastIndexOf(undefined); 107 const res3 = arr.includes(undefined); 108 print(`Index = undefined: indexOf => ${res1} lastIndexOf => ${res2} includes => ${res3}`); 109 } 110} 111 112let makeElementSeed = 0; 113function makeElement(type) { 114 makeElementSeed += 1; 115 if (type === 'int') { 116 return (makeElementSeed * 5 + 1) % 11; 117 } else if (type === 'double') { 118 return (makeElementSeed * 0.625 + 1) % 1.375; 119 } else if (type === 'string') { 120 return ((makeElementSeed * 5 + 1) % 11).toString(); 121 } else if (type === 'bigint') { 122 return BigInt((makeElementSeed * 5 + 1) % 11); 123 } else { 124 return { value: (makeElementSeed * 5 + 1) % 11 }; 125 } 126} 127 128print('======== Testing with non-generic ElementsKind ========'); 129{ 130 const intArr = []; 131 for (let i = 0; i < 11; i++) { 132 intArr[i] = makeElement('int'); 133 } 134 const doubleArr = []; 135 for (let i = 0; i < 11; i++) { 136 doubleArr[i] = makeElement('double'); 137 } 138 const strArr = []; 139 for (let i = 0; i < 11; i++) { 140 strArr[i] = makeElement('string'); 141 } 142 const bigintArr = []; 143 for (let i = 0; i < 11; i++) { 144 bigintArr[i] = makeElement('bigint'); 145 } 146 147 const targets = [ 148 1, 1.0, 1.125, '1', 1n 149 ]; 150 const allCases = [ 151 ['intArr', intArr], 152 ['doubleArr', doubleArr], 153 ['strArr', strArr], 154 ['bigintArr', bigintArr], 155 ]; 156 for (const [name, arr] of allCases) { 157 print(`ElementsKind of ${name} = ${ArkTools.getElementsKind(arr)}`); 158 for (let i = 0; i < targets.length; i++) { 159 const x = targets[i]; 160 const res1 = arr.indexOf(x); 161 const res2 = arr.lastIndexOf(x); 162 const res3 = arr.includes(x); 163 print(`[${name}] Target = ${x} (${typeof x}):`, 164 `indexOf => ${res1} lastIndexOf => ${res2} includes => ${res3}`); 165 } 166 } 167} 168