// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Flags: --allow-natives-syntax var tests = []; // Tests that will be called with each TypedArray constructor. tests.push(function TestConstructSmallObject(constr) { var myObject = { 0: 5, 1: 6, length: 2 }; arr = new constr(myObject); assertEquals(2, arr.length); assertEquals(5, arr[0]); assertEquals(6, arr[1]); }); tests.push(function TestConstructLargeObject(constr) { var myObject = {}; const n = 128; for (var i = 0; i < n; i++) { myObject[i] = i; } myObject.length = n; arr = new constr(myObject); assertEquals(n, arr.length); for (var i = 0; i < n; i++) { assertEquals(i, arr[i]); } }); tests.push(function TestConstructFromArrayWithSideEffects(constr) { var arr = [{ valueOf() { arr[1] = 20; return 1; }}, 2]; var ta = new constr(arr); assertEquals(1, ta[0]); assertEquals(2, ta[1]); }); tests.push(function TestConstructFromArrayWithSideEffectsHoley(constr) { var arr = [{ valueOf() { arr[1] = 20; return 1; }}, 2, , 4]; var ta = new constr(arr); assertEquals(1, ta[0]); assertEquals(2, ta[1]); // ta[2] will be the default value, but we aren't testing that here. assertEquals(4, ta[3]); }); tests.push(function TestConstructFromArrayHoleySmi(constr) { var arr = [0, 1, , 3]; var ta = new constr(arr); assertArrayEquals([0, 1, defaultValue(constr), 3], ta); }); tests.push(function TestConstructFromArrayHoleyDouble(constr) { var arr = [0.0, 1.0, , 3.0]; var ta = new constr(arr); assertArrayEquals([0, 1, defaultValue(constr), 3], ta); }); tests.push(function TestConstructFromArrayHoleySmiWithOtherPrototype(constr) { var arr = [0, 1, , 3]; Object.setPrototypeOf(arr, { 2: 2 }); var ta = new constr(arr); assertArrayEquals([0, 1, 2, 3], ta); }); tests.push(function TestConstructFromArrayWithProxyPrototype(constr) { var arr = [0, 1, , 3]; var proxy = new Proxy([], { get: function(target, name) { if (name === Symbol.iterator) return undefined; if (name == 2) return 2; return target[name]; } }); Object.setPrototypeOf(arr, proxy); var ta = new constr(arr); assertArrayEquals([0, 1, 2, 3], ta); }); tests.push(function TestConstructFromArrayHoleySmiWithSubclass(constr) { class SubArray extends Array {} var arr = new SubArray(0, 1); arr[3] = 3; var ta = new constr(arr); assertArrayEquals([0, 1, defaultValue(constr), 3], ta); }); tests.push(function TestConstructFromArrayNoIteratorWithGetter(constr) { var arr = [1, 2, 3]; arr[Symbol.iterator] = undefined; Object.defineProperty(arr, "2", { get() { return 22; } }); var ta = new constr(arr); assertArrayEquals([1, 2, 22], ta); }); tests.push(function TestConstructFromArrayNullIterator(constr) { var arr = [1, 2, 3]; arr[Symbol.iterator] = null; var ta = new Uint8Array(arr); assertArrayEquals([1, 2, 3], ta); }); tests.push(function TestConstructFromArrayUndefinedIterator(constr) { var arr = [1, 2, 3]; arr[Symbol.iterator] = undefined; var ta = new Uint8Array(arr); assertArrayEquals([1, 2, 3], ta); }); tests.push(function TestConstructFromArrayNonCallableIterator(constr) { var arr = [1, 2, 3]; arr[Symbol.iterator] = 1; assertThrows(() => new Uint8Array(arr), TypeError); }); tests.push(function TestConstructFromArray(constr) { var n = 64; var jsArray = []; for (var i = 0; i < n; i++) { jsArray[i] = i; } var arr = new constr(jsArray); assertEquals(n, arr.length); for (var i = 0; i < n; i++) { assertEquals(i, arr[i]); } }); tests.push(function TestConstructFromTypedArray(constr) { var n = 64; var ta = new constr(n); for (var i = 0; i < ta.length; i++) { ta[i] = i; } var arr = new constr(ta); assertEquals(n, arr.length); for (var i = 0; i < n; i++) { assertEquals(i, arr[i]); } }); tests.push(function TestFromTypedArraySpecies(constr) { var b = new ArrayBuffer(16); var a1 = new constr(b); var constructor_read = 0; var cons = b.constructor; Object.defineProperty(b, 'constructor', { get: function() { constructor_read++; return cons; } }); var a2 = new constr(a1); assertEquals(1, constructor_read); }); tests.push(function TestFromTypedArraySpeciesDetachsBuffer(constr) { var b = new ArrayBuffer(16); var a1 = new constr(b); var constructor_read = 0; var cons = b.constructor; Object.defineProperty(b, 'constructor', { get: function() { %ArrayBufferDetach(b); return cons; } }); assertThrows(() => new constr(a1)); }); tests.push(function TestTypedArrayMaxLength(constr) { var myObject = { 0: 5, 1: 6, length: %TypedArrayMaxLength() + 1 }; assertThrows(function() { new constr(myObject); }, RangeError); }); tests.push(function TestProxyHoleConverted(constr) { var source = {0: 0, 2: 2, length: 3}; var proxy = new Proxy(source, {}); var converted = new constr(proxy); assertArrayEquals([0, defaultValue(constr), 2], converted); }); tests.push(function TestProxyToObjectValueOfCalled(constr) { var thrower = { valueOf: function() { throw new TypeError(); } }; var source = {0: 0, 1: thrower, length: 2}; var proxy = new Proxy(source, {}); assertThrows(() => new constr(proxy), TypeError); }); tests.push(function TestObjectValueOfCalled(constr) { var thrower = { valueOf: function() { throw new TypeError(); } }; var obj = {0: 0, 1: thrower, length: 2}; assertThrows(() => new constr(obj), TypeError); }); tests.push(function TestSmiPackedArray(constr) { var ta = new constr([1, 2, 3, 4, 127]); assertEquals(5 * constr.BYTES_PER_ELEMENT, ta.byteLength); assertArrayEquals([1, 2, 3, 4, 127], ta); }); tests.push(function TestOffsetIsUsed(constr) { TestOffsetIsUsedRunner(constr, 4); TestOffsetIsUsedRunner(constr, 16); TestOffsetIsUsedRunner(constr, 32); TestOffsetIsUsedRunner(constr, 128); }); tests.push(function TestLengthIsNonSmiNegativeNumber(constr) { var ta = new constr({length: -%MaxSmi() - 2}); assertEquals(0, ta.length); }); // Helpers for above tests. function TestOffsetIsUsedRunner(constr, n) { var buffer = new ArrayBuffer(constr.BYTES_PER_ELEMENT * n); var whole_ta = new constr(buffer); assertEquals(n, whole_ta.length); for (var i = 0; i < whole_ta.length; i++) { whole_ta[i] = i; } var half_ta = new constr(buffer, constr.BYTES_PER_ELEMENT * n / 2); assertEquals(n / 2, half_ta.length); var arr = new constr(half_ta); assertEquals(n / 2, arr.length); for (var i = 0; i < arr.length; i++) { assertEquals(n / 2 + i, arr[i]); } } function defaultValue(constr) { if (constr == Float32Array || constr == Float64Array) return NaN; return 0; } tests.forEach(f => Test(f)); function Test(func) { func(Uint8Array); func(Int8Array); func(Uint16Array); func(Int16Array); func(Uint32Array); func(Int32Array); func(Float32Array); func(Float64Array); func(Uint8ClampedArray); } // Other, standalone tests. (function TestUint8ClampedIsNotBitCopied() { var arr = new Int8Array([-1.0, 0, 1.1, 255, 256]); assertArrayEquals([-1, 0, 1, -1, 0], arr); var expected = new Uint8ClampedArray([0, 0, 1, 0, 0]); var converted = new Uint8ClampedArray(arr); assertArrayEquals([0, 0, 1, 0, 0], converted); })(); (function TestInt8ArrayCopying() { var source = new Uint8Array([0, 1, 127, 128, 255, 256]); assertArrayEquals([0, 1, 127, 128, 255, 0], source); var converted = new Int8Array(source); assertArrayEquals([0, 1, 127, -128, -1, 0], converted); })(); (function TestInt16ArrayCopying() { var source = new Uint16Array([0, 1, 32767, 32768, 65535, 65536]); assertArrayEquals([0, 1, 32767, 32768, 65535, 0], source); var converted = new Int16Array(source); assertArrayEquals([0, 1, 32767, -32768, -1, 0], converted); })(); (function TestInt32ArrayCopying() { var source = new Uint32Array([0, 1, 2147483647, 2147483648, 4294967295, 4294967296]); assertArrayEquals([0, 1, 2147483647, 2147483648, 4294967295, 0], source); var converted = new Int32Array(source); assertArrayEquals([0, 1, 2147483647, -2147483648, -1, 0], converted); })();