1// Copyright 2015 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// Flags: --harmony-sharedarraybuffer --harmony-tostring 29 30 31// SharedArrayBuffer 32 33function TestByteLength(param, expectedByteLength) { 34 var sab = new SharedArrayBuffer(param); 35 assertSame(expectedByteLength, sab.byteLength); 36} 37 38function TestArrayBufferCreation() { 39 TestByteLength(1, 1); 40 TestByteLength(256, 256); 41 TestByteLength(2.567, 2); 42 43 TestByteLength("abc", 0); 44 45 TestByteLength(0, 0); 46 47 assertThrows(function() { new SharedArrayBuffer(-10); }, RangeError); 48 assertThrows(function() { new SharedArrayBuffer(-2.567); }, RangeError); 49 50/* TODO[dslomov]: Reenable the test 51 assertThrows(function() { 52 var ab1 = new SharedArrayBuffer(0xFFFFFFFFFFFF) 53 }, RangeError); 54*/ 55 56 var sab = new SharedArrayBuffer(); 57 assertSame(0, sab.byteLength); 58 assertEquals("[object SharedArrayBuffer]", 59 Object.prototype.toString.call(sab)); 60} 61 62TestArrayBufferCreation(); 63 64function TestByteLengthNotWritable() { 65 var sab = new SharedArrayBuffer(1024); 66 assertSame(1024, sab.byteLength); 67 68 assertThrows(function() { "use strict"; sab.byteLength = 42; }, TypeError); 69} 70 71TestByteLengthNotWritable(); 72 73function TestArrayBufferNoSlice() { 74 var sab = new SharedArrayBuffer(10); 75 assertEquals(undefined, sab.slice); 76} 77 78TestArrayBufferNoSlice(); 79 80// Typed arrays using SharedArrayBuffers 81 82// TODO(binji): how many of these tests are necessary if there are no new 83// TypedArray types? 84 85function MakeSharedTypedArray(constr, numElements) { 86 var sab = new SharedArrayBuffer(constr.BYTES_PER_ELEMENT * numElements); 87 return new constr(sab); 88} 89 90function TestTypedArray(constr, elementSize, typicalElement) { 91 assertSame(elementSize, constr.BYTES_PER_ELEMENT); 92 93 var sab = new SharedArrayBuffer(256*elementSize); 94 95 var a0 = new constr(30); 96 assertEquals("[object " + constr.name + "]", 97 Object.prototype.toString.call(a0)); 98 99 // TODO(binji): Should this return false here? It is a view, but it doesn't 100 // view a SharedArrayBuffer... 101 assertTrue(SharedArrayBuffer.isView(a0)); 102 assertSame(elementSize, a0.BYTES_PER_ELEMENT); 103 assertSame(30, a0.length); 104 assertSame(30*elementSize, a0.byteLength); 105 assertSame(0, a0.byteOffset); 106 assertSame(30*elementSize, a0.buffer.byteLength); 107 108 var aOverBufferLen0 = new constr(sab, 128*elementSize, 0); 109 assertSame(sab, aOverBufferLen0.buffer); 110 assertSame(elementSize, aOverBufferLen0.BYTES_PER_ELEMENT); 111 assertSame(0, aOverBufferLen0.length); 112 assertSame(0, aOverBufferLen0.byteLength); 113 assertSame(128*elementSize, aOverBufferLen0.byteOffset); 114 115 var a1 = new constr(sab, 128*elementSize, 128); 116 assertSame(sab, a1.buffer); 117 assertSame(elementSize, a1.BYTES_PER_ELEMENT); 118 assertSame(128, a1.length); 119 assertSame(128*elementSize, a1.byteLength); 120 assertSame(128*elementSize, a1.byteOffset); 121 122 123 var a2 = new constr(sab, 64*elementSize, 128); 124 assertSame(sab, a2.buffer); 125 assertSame(elementSize, a2.BYTES_PER_ELEMENT); 126 assertSame(128, a2.length); 127 assertSame(128*elementSize, a2.byteLength); 128 assertSame(64*elementSize, a2.byteOffset); 129 130 var a3 = new constr(sab, 192*elementSize); 131 assertSame(sab, a3.buffer); 132 assertSame(64, a3.length); 133 assertSame(64*elementSize, a3.byteLength); 134 assertSame(192*elementSize, a3.byteOffset); 135 136 var a4 = new constr(sab); 137 assertSame(sab, a4.buffer); 138 assertSame(256, a4.length); 139 assertSame(256*elementSize, a4.byteLength); 140 assertSame(0, a4.byteOffset); 141 142 143 var i; 144 for (i = 0; i < 128; i++) { 145 a1[i] = typicalElement; 146 } 147 148 for (i = 0; i < 128; i++) { 149 assertSame(typicalElement, a1[i]); 150 } 151 152 for (i = 0; i < 64; i++) { 153 assertSame(0, a2[i]); 154 } 155 156 for (i = 64; i < 128; i++) { 157 assertSame(typicalElement, a2[i]); 158 } 159 160 for (i = 0; i < 64; i++) { 161 assertSame(typicalElement, a3[i]); 162 } 163 164 for (i = 0; i < 128; i++) { 165 assertSame(0, a4[i]); 166 } 167 168 for (i = 128; i < 256; i++) { 169 assertSame(typicalElement, a4[i]); 170 } 171 172 var aAtTheEnd = new constr(sab, 256*elementSize); 173 assertSame(elementSize, aAtTheEnd.BYTES_PER_ELEMENT); 174 assertSame(0, aAtTheEnd.length); 175 assertSame(0, aAtTheEnd.byteLength); 176 assertSame(256*elementSize, aAtTheEnd.byteOffset); 177 178 assertThrows(function () { new constr(sab, 257*elementSize); }, RangeError); 179 assertThrows( 180 function () { new constr(sab, 128*elementSize, 192); }, 181 RangeError); 182 183 if (elementSize !== 1) { 184 assertThrows(function() { new constr(sab, 128*elementSize - 1, 10); }, 185 RangeError); 186 var unalignedArrayBuffer = new SharedArrayBuffer(10*elementSize + 1); 187 var goodArray = new constr(unalignedArrayBuffer, 0, 10); 188 assertSame(10, goodArray.length); 189 assertSame(10*elementSize, goodArray.byteLength); 190 assertThrows(function() { new constr(unalignedArrayBuffer)}, RangeError); 191 assertThrows(function() { new constr(unalignedArrayBuffer, 5*elementSize)}, 192 RangeError); 193 } 194 195 var abLen0 = new SharedArrayBuffer(0); 196 var aOverAbLen0 = new constr(abLen0); 197 assertSame(abLen0, aOverAbLen0.buffer); 198 assertSame(elementSize, aOverAbLen0.BYTES_PER_ELEMENT); 199 assertSame(0, aOverAbLen0.length); 200 assertSame(0, aOverAbLen0.byteLength); 201 assertSame(0, aOverAbLen0.byteOffset); 202 203 var a = new constr(sab, 64*elementSize, 128); 204 assertEquals("[object " + constr.name + "]", 205 Object.prototype.toString.call(a)); 206 var desc = Object.getOwnPropertyDescriptor( 207 constr.prototype.__proto__, Symbol.toStringTag); 208 assertTrue(desc.configurable); 209 assertFalse(desc.enumerable); 210 assertFalse(!!desc.writable); 211 assertFalse(!!desc.set); 212 assertEquals("function", typeof desc.get); 213} 214 215TestTypedArray(Uint8Array, 1, 0xFF); 216TestTypedArray(Int8Array, 1, -0x7F); 217TestTypedArray(Uint16Array, 2, 0xFFFF); 218TestTypedArray(Int16Array, 2, -0x7FFF); 219TestTypedArray(Uint32Array, 4, 0xFFFFFFFF); 220TestTypedArray(Int32Array, 4, -0x7FFFFFFF); 221TestTypedArray(Float32Array, 4, 0.5); 222TestTypedArray(Float64Array, 8, 0.5); 223TestTypedArray(Uint8ClampedArray, 1, 0xFF); 224 225 226function SubarrayTestCase(constructor, item, expectedResultLen, 227 expectedStartIndex, initialLen, start, end) { 228 var a = MakeSharedTypedArray(constructor, initialLen); 229 var s = a.subarray(start, end); 230 assertSame(constructor, s.constructor); 231 assertSame(expectedResultLen, s.length); 232 if (s.length > 0) { 233 s[0] = item; 234 assertSame(item, a[expectedStartIndex]); 235 } 236} 237 238function TestSubArray(constructor, item) { 239 SubarrayTestCase(constructor, item, 512, 512, 1024, 512, 1024); 240 SubarrayTestCase(constructor, item, 512, 512, 1024, 512); 241 242 SubarrayTestCase(constructor, item, 0, undefined, 0, 1, 20); 243 SubarrayTestCase(constructor, item, 100, 0, 100, 0, 100); 244 SubarrayTestCase(constructor, item, 100, 0, 100, 0, 1000); 245 SubarrayTestCase(constructor, item, 0, undefined, 100, 5, 1); 246 247 SubarrayTestCase(constructor, item, 1, 89, 100, -11, -10); 248 SubarrayTestCase(constructor, item, 9, 90, 100, -10, 99); 249 SubarrayTestCase(constructor, item, 0, undefined, 100, -10, 80); 250 SubarrayTestCase(constructor, item, 10,80, 100, 80, -10); 251 252 SubarrayTestCase(constructor, item, 10,90, 100, 90, "100"); 253 SubarrayTestCase(constructor, item, 10,90, 100, "90", "100"); 254 255 SubarrayTestCase(constructor, item, 0, undefined, 100, 90, "abc"); 256 SubarrayTestCase(constructor, item, 10,0, 100, "abc", 10); 257 258 SubarrayTestCase(constructor, item, 10,0, 100, 0.96, 10.96); 259 SubarrayTestCase(constructor, item, 10,0, 100, 0.96, 10.01); 260 SubarrayTestCase(constructor, item, 10,0, 100, 0.01, 10.01); 261 SubarrayTestCase(constructor, item, 10,0, 100, 0.01, 10.96); 262 263 264 SubarrayTestCase(constructor, item, 10,90, 100, 90); 265 SubarrayTestCase(constructor, item, 10,90, 100, -10); 266} 267 268TestSubArray(Uint8Array, 0xFF); 269TestSubArray(Int8Array, -0x7F); 270TestSubArray(Uint16Array, 0xFFFF); 271TestSubArray(Int16Array, -0x7FFF); 272TestSubArray(Uint32Array, 0xFFFFFFFF); 273TestSubArray(Int32Array, -0x7FFFFFFF); 274TestSubArray(Float32Array, 0.5); 275TestSubArray(Float64Array, 0.5); 276TestSubArray(Uint8ClampedArray, 0xFF); 277 278function TestTypedArrayOutOfRange(constructor, value, result) { 279 var a = MakeSharedTypedArray(constructor, 1); 280 a[0] = value; 281 assertSame(result, a[0]); 282} 283 284TestTypedArrayOutOfRange(Uint8Array, 0x1FA, 0xFA); 285TestTypedArrayOutOfRange(Uint8Array, -1, 0xFF); 286 287TestTypedArrayOutOfRange(Int8Array, 0x1FA, 0x7A - 0x80); 288 289TestTypedArrayOutOfRange(Uint16Array, 0x1FFFA, 0xFFFA); 290TestTypedArrayOutOfRange(Uint16Array, -1, 0xFFFF); 291TestTypedArrayOutOfRange(Int16Array, 0x1FFFA, 0x7FFA - 0x8000); 292 293TestTypedArrayOutOfRange(Uint32Array, 0x1FFFFFFFA, 0xFFFFFFFA); 294TestTypedArrayOutOfRange(Uint32Array, -1, 0xFFFFFFFF); 295TestTypedArrayOutOfRange(Int32Array, 0x1FFFFFFFA, 0x7FFFFFFA - 0x80000000); 296 297TestTypedArrayOutOfRange(Uint8ClampedArray, 0x1FA, 0xFF); 298TestTypedArrayOutOfRange(Uint8ClampedArray, -1, 0); 299 300var typedArrayConstructors = [ 301 Uint8Array, 302 Int8Array, 303 Uint16Array, 304 Int16Array, 305 Uint32Array, 306 Int32Array, 307 Uint8ClampedArray, 308 Float32Array, 309 Float64Array]; 310 311function TestPropertyTypeChecks(constructor) { 312 function CheckProperty(name) { 313 var d = Object.getOwnPropertyDescriptor(constructor.prototype.__proto__, 314 name); 315 var o = {}; 316 assertThrows(function() {d.get.call(o);}, TypeError); 317 for (var i = 0; i < typedArrayConstructors.length; i++) { 318 var ctor = typedArrayConstructors[i]; 319 var a = MakeSharedTypedArray(ctor, 10); 320 d.get.call(a); // shouldn't throw 321 } 322 } 323 324 CheckProperty("buffer"); 325 CheckProperty("byteOffset"); 326 CheckProperty("byteLength"); 327 CheckProperty("length"); 328} 329 330for(i = 0; i < typedArrayConstructors.length; i++) { 331 TestPropertyTypeChecks(typedArrayConstructors[i]); 332} 333 334function TestTypedArraySet() { 335 // Test array.set in different combinations. 336 337 function assertArrayPrefix(expected, array) { 338 for (var i = 0; i < expected.length; ++i) { 339 assertEquals(expected[i], array[i]); 340 } 341 } 342 343 // SharedTypedArrays don't allow initialization via array-like 344 function initializeFromArray(constructor, array) { 345 var buffer = MakeSharedTypedArray(constructor, array.length); 346 for (var i = 0; i < array.length; ++i) { 347 buffer[i] = array[i]; 348 } 349 return buffer; 350 } 351 352 var a11 = initializeFromArray(Int16Array, [1, 2, 3, 4, 0, -1]) 353 var a12 = MakeSharedTypedArray(Uint16Array, 15); 354 a12.set(a11, 3) 355 assertArrayPrefix([0, 0, 0, 1, 2, 3, 4, 0, 0xffff, 0, 0], a12) 356 assertThrows(function(){ a11.set(a12) }) 357 358 var a21 = [1, undefined, 10, NaN, 0, -1, {valueOf: function() {return 3}}] 359 var a22 = MakeSharedTypedArray(Int32Array, 12) 360 a22.set(a21, 2) 361 assertArrayPrefix([0, 0, 1, 0, 10, 0, 0, -1, 3, 0], a22) 362 363 var a31 = initializeFromArray(Float32Array, [2, 4, 6, 8, 11, NaN, 1/0, -3]) 364 var a32 = a31.subarray(2, 6) 365 a31.set(a32, 4) 366 assertArrayPrefix([2, 4, 6, 8, 6, 8, 11, NaN], a31) 367 assertArrayPrefix([6, 8, 6, 8], a32) 368 369 var a4 = initializeFromArray(Uint8ClampedArray, [3,2,5,6]) 370 a4.set(a4) 371 assertArrayPrefix([3, 2, 5, 6], a4) 372 373 // Cases with overlapping backing store but different element sizes. 374 var b = new SharedArrayBuffer(4) 375 var a5 = new Int16Array(b) 376 var a50 = new Int8Array(b) 377 var a51 = new Int8Array(b, 0, 2) 378 var a52 = new Int8Array(b, 1, 2) 379 var a53 = new Int8Array(b, 2, 2) 380 381 a5.set([0x5050, 0x0a0a]) 382 assertArrayPrefix([0x50, 0x50, 0x0a, 0x0a], a50) 383 assertArrayPrefix([0x50, 0x50], a51) 384 assertArrayPrefix([0x50, 0x0a], a52) 385 assertArrayPrefix([0x0a, 0x0a], a53) 386 387 a50.set([0x50, 0x50, 0x0a, 0x0a]) 388 a51.set(a5) 389 assertArrayPrefix([0x50, 0x0a, 0x0a, 0x0a], a50) 390 391 a50.set([0x50, 0x50, 0x0a, 0x0a]) 392 a52.set(a5) 393 assertArrayPrefix([0x50, 0x50, 0x0a, 0x0a], a50) 394 395 a50.set([0x50, 0x50, 0x0a, 0x0a]) 396 a53.set(a5) 397 assertArrayPrefix([0x50, 0x50, 0x50, 0x0a], a50) 398 399 a50.set([0x50, 0x51, 0x0a, 0x0b]) 400 a5.set(a51) 401 assertArrayPrefix([0x0050, 0x0051], a5) 402 403 a50.set([0x50, 0x51, 0x0a, 0x0b]) 404 a5.set(a52) 405 assertArrayPrefix([0x0051, 0x000a], a5) 406 407 a50.set([0x50, 0x51, 0x0a, 0x0b]) 408 a5.set(a53) 409 assertArrayPrefix([0x000a, 0x000b], a5) 410 411 // Mixed types of same size. 412 var a61 = initializeFromArray(Float32Array, [1.2, 12.3]) 413 var a62 = MakeSharedTypedArray(Int32Array, 2) 414 a62.set(a61) 415 assertArrayPrefix([1, 12], a62) 416 a61.set(a62) 417 assertArrayPrefix([1, 12], a61) 418 419 // Invalid source 420 var a = MakeSharedTypedArray(Uint16Array, 50); 421 var expected = []; 422 for (i = 0; i < 50; i++) { 423 a[i] = i; 424 expected.push(i); 425 } 426 a.set({}); 427 assertArrayPrefix(expected, a); 428 assertThrows(function() { a.set.call({}) }, TypeError); 429 assertThrows(function() { a.set.call([]) }, TypeError); 430 431 assertThrows(function() { a.set(0); }, TypeError); 432 assertThrows(function() { a.set(0, 1); }, TypeError); 433} 434 435TestTypedArraySet(); 436 437function TestTypedArraysWithIllegalIndices() { 438 var a = MakeSharedTypedArray(Int32Array, 100); 439 440 a[-10] = 10; 441 assertEquals(undefined, a[-10]); 442 a["-10"] = 10; 443 assertEquals(undefined, a["-10"]); 444 445 var s = " -10"; 446 a[s] = 10; 447 assertEquals(10, a[s]); 448 var s1 = " -10 "; 449 a[s] = 10; 450 assertEquals(10, a[s]); 451 452 a["-1e2"] = 10; 453 assertEquals(10, a["-1e2"]); 454 assertEquals(undefined, a[-1e2]); 455 456 a["-0"] = 256; 457 var s2 = " -0"; 458 a[s2] = 255; 459 assertEquals(undefined, a["-0"]); 460 assertEquals(255, a[s2]); 461 assertEquals(0, a[-0]); 462 463 /* Chromium bug: 424619 464 * a[-Infinity] = 50; 465 * assertEquals(undefined, a[-Infinity]); 466 */ 467 a[1.5] = 10; 468 assertEquals(undefined, a[1.5]); 469 var nan = Math.sqrt(-1); 470 a[nan] = 5; 471 assertEquals(undefined, a[nan]); 472 473 var x = 0; 474 var y = -0; 475 assertEquals(Infinity, 1/x); 476 assertEquals(-Infinity, 1/y); 477 a[x] = 5; 478 a[y] = 27; 479 assertEquals(27, a[x]); 480 assertEquals(27, a[y]); 481} 482 483TestTypedArraysWithIllegalIndices(); 484 485function TestTypedArraysWithIllegalIndicesStrict() { 486 'use strict'; 487 var a = MakeSharedTypedArray(Int32Array, 100); 488 489 a[-10] = 10; 490 assertEquals(undefined, a[-10]); 491 a["-10"] = 10; 492 assertEquals(undefined, a["-10"]); 493 494 var s = " -10"; 495 a[s] = 10; 496 assertEquals(10, a[s]); 497 var s1 = " -10 "; 498 a[s] = 10; 499 assertEquals(10, a[s]); 500 501 a["-1e2"] = 10; 502 assertEquals(10, a["-1e2"]); 503 assertEquals(undefined, a[-1e2]); 504 505 a["-0"] = 256; 506 var s2 = " -0"; 507 a[s2] = 255; 508 assertEquals(undefined, a["-0"]); 509 assertEquals(255, a[s2]); 510 assertEquals(0, a[-0]); 511 512 /* Chromium bug: 424619 513 * a[-Infinity] = 50; 514 * assertEquals(undefined, a[-Infinity]); 515 */ 516 a[1.5] = 10; 517 assertEquals(undefined, a[1.5]); 518 var nan = Math.sqrt(-1); 519 a[nan] = 5; 520 assertEquals(undefined, a[nan]); 521 522 var x = 0; 523 var y = -0; 524 assertEquals(Infinity, 1/x); 525 assertEquals(-Infinity, 1/y); 526 a[x] = 5; 527 a[y] = 27; 528 assertEquals(27, a[x]); 529 assertEquals(27, a[y]); 530} 531 532TestTypedArraysWithIllegalIndicesStrict(); 533 534// General tests for properties 535 536// Test property attribute [[Enumerable]] 537function TestEnumerable(func, obj) { 538 function props(x) { 539 var array = []; 540 for (var p in x) array.push(p); 541 return array.sort(); 542 } 543 assertArrayEquals([], props(func)); 544 assertArrayEquals([], props(func.prototype)); 545 if (obj) 546 assertArrayEquals([], props(obj)); 547} 548TestEnumerable(ArrayBuffer, new SharedArrayBuffer()); 549for(i = 0; i < typedArrayConstructors.length; i++) { 550 TestEnumerable(typedArrayConstructors[i]); 551} 552 553// Test arbitrary properties on ArrayBuffer 554function TestArbitrary(m) { 555 function TestProperty(map, property, value) { 556 map[property] = value; 557 assertEquals(value, map[property]); 558 } 559 for (var i = 0; i < 20; i++) { 560 TestProperty(m, 'key' + i, 'val' + i); 561 TestProperty(m, 'foo' + i, 'bar' + i); 562 } 563} 564TestArbitrary(new SharedArrayBuffer(256)); 565for(i = 0; i < typedArrayConstructors.length; i++) { 566 TestArbitrary(MakeSharedTypedArray(typedArrayConstructors[i], 10)); 567} 568 569// Test direct constructor call 570assertThrows(function() { SharedArrayBuffer(); }, TypeError); 571for(i = 0; i < typedArrayConstructors.length; i++) { 572 assertThrows(function(i) { typedArrayConstructors[i](); }.bind(this, i), 573 TypeError); 574} 575