github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/builtin_arrray_test.go (about) 1 package goja 2 3 import "testing" 4 5 func TestArrayProtoProp(t *testing.T) { 6 const SCRIPT = ` 7 Object.defineProperty(Array.prototype, '0', {value: 42, configurable: true, writable: false}) 8 var a = [] 9 a[0] = 1 10 a[0] 11 ` 12 13 testScript(SCRIPT, valueInt(42), t) 14 } 15 16 func TestArrayDelete(t *testing.T) { 17 const SCRIPT = ` 18 var a = [1, 2]; 19 var deleted = delete a[0]; 20 var undef = a[0] === undefined; 21 var len = a.length; 22 23 deleted && undef && len === 2; 24 ` 25 26 testScript(SCRIPT, valueTrue, t) 27 } 28 29 func TestArrayDeleteNonexisting(t *testing.T) { 30 const SCRIPT = ` 31 Array.prototype[0] = 42; 32 var a = []; 33 delete a[0] && a[0] === 42; 34 ` 35 36 testScript(SCRIPT, valueTrue, t) 37 } 38 39 func TestArraySetLength(t *testing.T) { 40 const SCRIPT = ` 41 var a = [1, 2]; 42 var assert0 = a.length == 2; 43 a.length = "1"; 44 a.length = 1.0; 45 a.length = 1; 46 var assert1 = a.length == 1; 47 a.length = 2; 48 var assert2 = a.length == 2; 49 assert0 && assert1 && assert2 && a[1] === undefined; 50 51 ` 52 53 testScript(SCRIPT, valueTrue, t) 54 } 55 56 func TestArrayReverseNonOptimisable(t *testing.T) { 57 const SCRIPT = ` 58 var a = []; 59 Object.defineProperty(a, "0", {get: function() {return 42}, set: function(v) {Object.defineProperty(a, "0", {value: v + 1, writable: true, configurable: true})}, configurable: true}) 60 a[1] = 43; 61 a.reverse(); 62 63 a.length === 2 && a[0] === 44 && a[1] === 42; 64 ` 65 66 testScript(SCRIPT, valueTrue, t) 67 } 68 69 func TestArrayPushNonOptimisable(t *testing.T) { 70 const SCRIPT = ` 71 Object.defineProperty(Object.prototype, "0", {value: 42}); 72 var a = []; 73 var thrown = false; 74 try { 75 a.push(1); 76 } catch (e) { 77 thrown = e instanceof TypeError; 78 } 79 thrown; 80 ` 81 82 testScript(SCRIPT, valueTrue, t) 83 } 84 85 func TestArraySetLengthWithPropItems(t *testing.T) { 86 const SCRIPT = ` 87 var a = [1,2,3,4]; 88 var thrown = false; 89 90 Object.defineProperty(a, "2", {value: 42, configurable: false, writable: false}); 91 try { 92 Object.defineProperty(a, "length", {value: 0, writable: false}); 93 } catch (e) { 94 thrown = e instanceof TypeError; 95 } 96 thrown && a.length === 3; 97 ` 98 99 testScript(SCRIPT, valueTrue, t) 100 } 101 102 func TestArrayFrom(t *testing.T) { 103 const SCRIPT = ` 104 function checkDestHoles(dest, prefix) { 105 assert(dest !== source, prefix + ": dest !== source"); 106 assert.sameValue(dest.length, 3, prefix + ": dest.length"); 107 assert.sameValue(dest[0], 1, prefix + ": [0]"); 108 assert.sameValue(dest[1], undefined, prefix + ": [1]"); 109 assert(dest.hasOwnProperty("1"), prefix + ': hasOwnProperty("1")'); 110 assert.sameValue(dest[2], 3, prefix + ": [2]"); 111 } 112 113 function checkDest(dest, prefix) { 114 assert(dest !== source, prefix + ": dest !== source"); 115 assert.sameValue(dest.length, 3, prefix + ": dest.length"); 116 assert.sameValue(dest[0], 1, prefix + ": [0]"); 117 assert.sameValue(dest[1], 2, prefix + ": [1]"); 118 assert.sameValue(dest[2], 3, prefix + ": [2]"); 119 } 120 121 var source = [1,2,3]; 122 var srcHoles = [1,,3]; 123 124 checkDest(Array.from(source), "std source/std dest"); 125 checkDestHoles(Array.from(srcHoles), "std source (holes)/std dest"); 126 127 function Iter() { 128 this.idx = 0; 129 } 130 Iter.prototype.next = function() { 131 if (this.idx < source.length) { 132 return {value: source[this.idx++]}; 133 } else { 134 return {done: true}; 135 } 136 } 137 138 var src = {}; 139 src[Symbol.iterator] = function() { 140 return new Iter(); 141 } 142 checkDest(Array.from(src), "iter src/std dest"); 143 144 src = {0: 1, 2: 3, length: 3}; 145 checkDestHoles(Array.from(src), "arrayLike src/std dest"); 146 147 function A() {} 148 A.from = Array.from; 149 150 checkDest(A.from(source), "std src/cust dest"); 151 checkDestHoles(A.from(srcHoles), "std src (holes)/cust dest"); 152 checkDestHoles(A.from(src), "arrayLike src/cust dest"); 153 154 function T2() { 155 Object.defineProperty(this, 0, { 156 configurable: false, 157 writable: true, 158 enumerable: true 159 }); 160 } 161 162 assert.throws(TypeError, function() { 163 Array.from.call(T2, source); 164 }); 165 166 ` 167 168 testScriptWithTestLib(SCRIPT, _undefined, t) 169 } 170 171 func TestArrayOf(t *testing.T) { 172 const SCRIPT = ` 173 function T1() { 174 Object.preventExtensions(this); 175 } 176 177 assert.throws(TypeError, function() { 178 Array.of.call(T1, 'Bob'); 179 }); 180 181 function T2() { 182 Object.defineProperty(this, 0, { 183 configurable: false, 184 writable: true, 185 enumerable: true 186 }); 187 } 188 189 assert.throws(TypeError, function() { 190 Array.of.call(T2, 'Bob'); 191 }) 192 193 result = Array.of.call(undefined); 194 assert( 195 result instanceof Array, 196 'this is not a constructor' 197 ); 198 199 result = Array.of.call(Math.cos); 200 assert( 201 result instanceof Array, 202 'this is a builtin function with no [[Construct]] slot' 203 ); 204 205 ` 206 207 testScriptWithTestLib(SCRIPT, _undefined, t) 208 } 209 210 func TestUnscopables(t *testing.T) { 211 const SCRIPT = ` 212 var keys = []; 213 var _length; 214 with (Array.prototype) { 215 _length = length; 216 keys.push('something'); 217 } 218 _length === 0 && keys.length === 1 && keys[0] === "something"; 219 ` 220 testScript(SCRIPT, valueTrue, t) 221 } 222 223 func TestArraySort(t *testing.T) { 224 const SCRIPT = ` 225 assert.throws(TypeError, function() { 226 [1,2].sort(null); 227 }, "null compare function"); 228 assert.throws(TypeError, function() { 229 [1,2].sort({}); 230 }, "non-callable compare function"); 231 ` 232 testScriptWithTestLib(SCRIPT, _undefined, t) 233 } 234 235 func TestArraySortNonStdArray(t *testing.T) { 236 const SCRIPT = ` 237 const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd']; 238 239 Object.defineProperty(array, '2', { 240 get() { 241 array.pop(); 242 array.pop(); 243 return this.foo; 244 }, 245 set(v) { 246 this.foo = v; 247 } 248 }); 249 250 array.sort(); 251 252 assert.sameValue(array[0], 'b'); 253 assert.sameValue(array[1], 'c'); 254 assert.sameValue(array[3], undefined); 255 assert.sameValue(array[4], undefined); 256 assert.sameValue('5' in array, false); 257 assert.sameValue(array.hasOwnProperty('5'), false); 258 assert.sameValue(array.length, 6); 259 assert.sameValue(array.foo, undefined); 260 261 assert.sameValue(array[2], undefined); 262 assert.sameValue(array.length, 4); 263 ` 264 testScriptWithTestLib(SCRIPT, _undefined, t) 265 } 266 267 func TestArrayConcat(t *testing.T) { 268 const SCRIPT = ` 269 var concat = Array.prototype.concat; 270 var array = [1, 2]; 271 var sparseArray = [1, , 2]; 272 var nonSpreadableArray = [1, 2]; 273 nonSpreadableArray[Symbol.isConcatSpreadable] = false; 274 var arrayLike = { 0: 1, 1: 2, length: 2 }; 275 var spreadableArrayLike = { 0: 1, 1: 2, length: 2 }; 276 spreadableArrayLike[Symbol.isConcatSpreadable] = true; 277 assert(looksNative(concat)); 278 assert(deepEqual(array.concat(), [1, 2]), '#1'); 279 assert(deepEqual(sparseArray.concat(), [1, , 2]), '#2'); 280 assert(deepEqual(nonSpreadableArray.concat(), [[1, 2]]), '#3'); 281 assert(deepEqual(concat.call(arrayLike), [{ 0: 1, 1: 2, length: 2 }]), '#4'); 282 assert(deepEqual(concat.call(spreadableArrayLike), [1, 2]), '#5'); 283 assert(deepEqual([].concat(array), [1, 2]), '#6'); 284 assert(deepEqual([].concat(sparseArray), [1, , 2]), '#7'); 285 assert(deepEqual([].concat(nonSpreadableArray), [[1, 2]]), '#8'); 286 assert(deepEqual([].concat(arrayLike), [{ 0: 1, 1: 2, length: 2 }]), '#9'); 287 assert(deepEqual([].concat(spreadableArrayLike), [1, 2]), '#10'); 288 assert(deepEqual(array.concat(sparseArray, nonSpreadableArray, arrayLike, spreadableArrayLike), [ 289 1, 2, 1, , 2, [1, 2], { 0: 1, 1: 2, length: 2 }, 1, 2, 290 ]), '#11'); 291 array = []; 292 array.constructor = {}; 293 array.constructor[Symbol.species] = function () { 294 return { foo: 1 }; 295 } 296 assert.sameValue(array.concat().foo, 1, '@@species'); 297 ` 298 testScriptWithTestLibX(SCRIPT, _undefined, t) 299 } 300 301 func TestArrayFlat(t *testing.T) { 302 const SCRIPT = ` 303 var array = [1, [2,3,[4,5,6]], [[[[7,8,9]]]]]; 304 assert(deepEqual(array.flat(), [1,2,3,[4,5,6],[[[7,8,9]]]]), '#1'); 305 assert(deepEqual(array.flat(1), [1,2,3,[4,5,6],[[[7,8,9]]]]), '#2'); 306 assert(deepEqual(array.flat(3), [1,2,3,4,5,6,[7,8,9]]), '#3'); 307 assert(deepEqual(array.flat(4), [1,2,3,4,5,6,7,8,9]), '#4'); 308 assert(deepEqual(array.flat(10), [1,2,3,4,5,6,7,8,9]), '#5'); 309 ` 310 testScriptWithTestLibX(SCRIPT, _undefined, t) 311 } 312 313 func TestArrayFlatMap(t *testing.T) { 314 const SCRIPT = ` 315 var double = function(x) { 316 if (isNaN(x)) { 317 return x 318 } 319 return x * 2 320 } 321 var array = [1, [2,3,[4,5,6]], [[[[7,8,9]]]]]; 322 assert(deepEqual(array.flatMap(double), [2,2,3,[4,5,6],[[[7,8,9]]]]), '#1'); 323 ` 324 testScriptWithTestLibX(SCRIPT, _undefined, t) 325 }