Bug 1140152 - Copy elements' underlying bit patterns in TypedArray.prototype.slice. r=till

This commit is contained in:
André Bargull 2018-05-02 09:52:05 -07:00
Родитель 36648e7085
Коммит efedb00226
6 изменённых файлов: 880 добавлений и 15 удалений

Просмотреть файл

@ -1025,13 +1025,8 @@ function TypedArraySlice(start, end) {
// Step 9.
var A = TypedArraySpeciesCreateWithLength(O, count);
// Steps 10-13 (Not implemented, bug 1140152).
// Steps 14-15.
if (count > 0) {
// Step 14.a.
var n = 0;
// Steps 14.b.ii, 15.b.
if (buffer === null) {
// A typed array previously using inline storage may acquire a
@ -1042,13 +1037,20 @@ function TypedArraySlice(start, end) {
if (IsDetachedBuffer(buffer))
ThrowTypeError(JSMSG_TYPED_ARRAY_DETACHED);
// Step 14.b.
while (k < final) {
// Steps 14.b.i-v.
A[n++] = O[k++];
}
// Steps 10-13, 15.
var sliced = TypedArrayBitwiseSlice(O, A, k | 0, count | 0);
// FIXME: Implement step 15 (bug 1140152).
// Step 14.
if (!sliced) {
// Step 14.a.
var n = 0;
// Step 14.b.
while (k < final) {
// Steps 14.b.i-v.
A[n++] = O[k++];
}
}
}
// Step 16.

Просмотреть файл

@ -145,9 +145,6 @@ skip script test262/built-ins/TypedArrayConstructors/internals/Set/key-is-not-in
skip script test262/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds.js
skip script test262/built-ins/TypedArrayConstructors/internals/Set/tonumber-value-throws.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1140152
skip script test262/built-ins/TypedArray/prototype/slice/bit-precision.js
# https://bugzilla.mozilla.org/show_bug.cgi?id=1317405
skip script test262/language/computed-property-names/class/static/method-number.js
skip script test262/language/computed-property-names/class/static/method-string.js

Просмотреть файл

@ -0,0 +1,153 @@
// Copies bytes bit-wise if source and target type are the same.
// Only detectable when using floating point typed arrays.
const float32Constructors = anyTypedArrayConstructors.filter(isFloatConstructor)
.filter(c => c.BYTES_PER_ELEMENT === 4);
const float64Constructors = anyTypedArrayConstructors.filter(isFloatConstructor)
.filter(c => c.BYTES_PER_ELEMENT === 8);
// Also test with cross-compartment typed arrays.
const otherGlobal = newGlobal();
float32Constructors.push(otherGlobal.Float32Array);
float64Constructors.push(otherGlobal.Float64Array);
function* p(xs, ys) {
for (let x of xs) {
for (let y of ys) {
yield [x, y];
}
}
}
const isLittleEndian = new Uint8Array(new Uint16Array([1]).buffer)[0] !== 0;
function geti64(i32, i) {
return [i32[2 * i + isLittleEndian], i32[2 * i + !isLittleEndian]];
}
function seti64(i32, i, [hi, lo]) {
i32[i * 2 + isLittleEndian] = hi;
i32[i * 2 + !isLittleEndian] = lo;
}
const NaNs = {
Float32: [
0x7F800001|0, // smallest SNaN
0x7FBFFFFF|0, // largest SNaN
0x7FC00000|0, // smallest QNaN
0x7FFFFFFF|0, // largest QNaN
0xFF800001|0, // smallest SNaN, sign-bit set
0xFFBFFFFF|0, // largest SNaN, sign-bit set
0xFFC00000|0, // smallest QNaN, sign-bit set
0xFFFFFFFF|0, // largest QNaN, sign-bit set
],
Float64: [
[0x7FF00000|0, 0x00000001|0], // smallest SNaN
[0x7FF7FFFF|0, 0xFFFFFFFF|0], // largest SNaN
[0x7FF80000|0, 0x00000000|0], // smallest QNaN
[0x7FFFFFFF|0, 0xFFFFFFFF|0], // largest QNaN
[0xFFF00000|0, 0x00000001|0], // smallest SNaN, sign-bit set
[0xFFF7FFFF|0, 0xFFFFFFFF|0], // largest SNaN, sign-bit set
[0xFFF80000|0, 0x00000000|0], // smallest QNaN, sign-bit set
[0xFFFFFFFF|0, 0xFFFFFFFF|0], // largest QNaN, sign-bit set
],
};
const cNaN = {
Float32: new Int32Array(new Float32Array([NaN]).buffer)[0],
Float64: geti64(new Int32Array(new Float64Array([NaN]).buffer), 0),
};
// Float32 -> Float32
for (let [sourceConstructor, targetConstructor] of p(float32Constructors, float32Constructors)) {
let len = NaNs.Float32.length;
let f32 = new sourceConstructor(len);
let i32 = new Int32Array(f32.buffer);
f32.constructor = targetConstructor;
for (let i = 0; i < len; ++i) {
i32[i] = NaNs.Float32[i];
}
let rf32 = f32.slice(0);
let ri32 = new Int32Array(rf32.buffer);
assertEq(rf32.length, len);
assertEq(ri32.length, len);
// Same bits.
for (let i = 0; i < len; ++i) {
assertEq(ri32[i], NaNs.Float32[i]);
}
}
// Float32 -> Float64
for (let [sourceConstructor, targetConstructor] of p(float32Constructors, float64Constructors)) {
let len = NaNs.Float32.length;
let f32 = new sourceConstructor(len);
let i32 = new Int32Array(f32.buffer);
f32.constructor = targetConstructor;
for (let i = 0; i < len; ++i) {
i32[i] = NaNs.Float32[i];
}
let rf64 = f32.slice(0);
let ri32 = new Int32Array(rf64.buffer);
assertEq(rf64.length, len);
assertEq(ri32.length, 2 * len);
// NaN bits canonicalized.
for (let i = 0; i < len; ++i) {
assertEqArray(geti64(ri32, i), cNaN.Float64);
}
}
// Float64 -> Float64
for (let [sourceConstructor, targetConstructor] of p(float64Constructors, float64Constructors)) {
let len = NaNs.Float64.length;
let f64 = new sourceConstructor(len);
let i32 = new Int32Array(f64.buffer);
f64.constructor = targetConstructor;
for (let i = 0; i < len; ++i) {
seti64(i32, i, NaNs.Float64[i]);
}
let rf64 = f64.slice(0);
let ri32 = new Int32Array(rf64.buffer);
assertEq(rf64.length, len);
assertEq(ri32.length, 2 * len);
// Same bits.
for (let i = 0; i < len; ++i) {
assertEqArray(geti64(ri32, i), NaNs.Float64[i]);
}
}
// Float64 -> Float32
for (let [sourceConstructor, targetConstructor] of p(float64Constructors, float32Constructors)) {
let len = NaNs.Float64.length;
let f64 = new sourceConstructor(len);
let i32 = new Int32Array(f64.buffer);
f64.constructor = targetConstructor;
for (let i = 0; i < len; ++i) {
seti64(i32, i, NaNs.Float64[i]);
}
let rf32 = f64.slice(0);
let ri32 = new Int32Array(rf32.buffer);
assertEq(rf32.length, len);
assertEq(ri32.length, len);
// NaN bits canonicalized.
for (let i = 0; i < len; ++i) {
assertEqArray(ri32[i], cNaN.Float32);
}
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,515 @@
// Test conversions to different element types.
let tests = [
/* Int8Array */
{
from: Int8Array,
to: Int8Array,
values: [-129, -128, -127, -1, 0, 1, 127, 128, 129],
expected: [127, -128, -127, -1, 0, 1, 127, -128, -127],
},
{
from: Int8Array,
to: Uint8Array,
values: [-129, -128, -127, -1, 0, 1, 127, 128, 129],
expected: [127, 128, 129, 255, 0, 1, 127, 128, 129],
},
{
from: Int8Array,
to: Uint8ClampedArray,
values: [-129, -128, -127, -1, 0, 1, 127, 128, 129],
expected: [127, 0, 0, 0, 0, 1, 127, 0, 0],
},
{
from: Int8Array,
to: Int16Array,
values: [-129, -128, -127, -1, 0, 1, 127, 128, 129],
expected: [127, -128, -127, -1, 0, 1, 127, -128, -127],
},
{
from: Int8Array,
to: Uint16Array,
values: [-129, -128, -127, -1, 0, 1, 127, 128, 129],
expected: [127, 65408, 65409, 65535, 0, 1, 127, 65408, 65409],
},
{
from: Int8Array,
to: Int32Array,
values: [-129, -128, -127, -1, 0, 1, 127, 128, 129],
expected: [127, -128, -127, -1, 0, 1, 127, -128, -127],
},
{
from: Int8Array,
to: Uint32Array,
values: [-129, -128, -127, -1, 0, 1, 127, 128, 129],
expected: [127, 4294967168, 4294967169, 4294967295, 0, 1, 127, 4294967168, 4294967169],
},
{
from: Int8Array,
to: Float32Array,
values: [-129, -128, -127, -1, 0, 1, 127, 128, 129],
expected: [127, -128, -127, -1, 0, 1, 127, -128, -127],
},
{
from: Int8Array,
to: Float64Array,
values: [-129, -128, -127, -1, 0, 1, 127, 128, 129],
expected: [127, -128, -127, -1, 0, 1, 127, -128, -127],
},
/* Uint8Array */
{
from: Uint8Array,
to: Int8Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, -128, -127, -2, -1, 0],
},
{
from: Uint8Array,
to: Uint8Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 0],
},
{
from: Uint8Array,
to: Uint8ClampedArray,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 0],
},
{
from: Uint8Array,
to: Int16Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 0],
},
{
from: Uint8Array,
to: Uint16Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 0],
},
{
from: Uint8Array,
to: Int32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 0],
},
{
from: Uint8Array,
to: Uint32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 0],
},
{
from: Uint8Array,
to: Float32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 0],
},
{
from: Uint8Array,
to: Float64Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 0],
},
/* Uint8ClampedArray */
{
from: Uint8ClampedArray,
to: Int8Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, -128, -127, -2, -1, -1],
},
{
from: Uint8ClampedArray,
to: Uint8Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 255],
},
{
from: Uint8ClampedArray,
to: Uint8ClampedArray,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 255],
},
{
from: Uint8ClampedArray,
to: Int16Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 255],
},
{
from: Uint8ClampedArray,
to: Uint16Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 255],
},
{
from: Uint8ClampedArray,
to: Int32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 255],
},
{
from: Uint8ClampedArray,
to: Uint32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 255],
},
{
from: Uint8ClampedArray,
to: Float32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 255],
},
{
from: Uint8ClampedArray,
to: Float64Array,
values: [0, 1, 127, 128, 129, 254, 255, 256],
expected: [0, 1, 127, 128, 129, 254, 255, 255],
},
/* Int16Array */
{
from: Int16Array,
to: Int8Array,
values: [-32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769],
expected: [-1, 0, 1, 127, -128, -127, -1, 0, 1, 127, -128, -127, -1, 0, 1],
},
{
from: Int16Array,
to: Uint8Array,
values: [-32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769],
expected: [255, 0, 1, 127, 128, 129, 255, 0, 1, 127, 128, 129, 255, 0, 1],
},
{
from: Int16Array,
to: Uint8ClampedArray,
values: [-32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769],
expected: [255, 0, 0, 0, 0, 0, 0, 0, 1, 127, 128, 129, 255, 0, 0],
},
{
from: Int16Array,
to: Int16Array,
values: [-32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769],
expected: [32767, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, -32768, -32767],
},
{
from: Int16Array,
to: Uint16Array,
values: [-32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769],
expected: [32767, 32768, 32769, 65407, 65408, 65409, 65535, 0, 1, 127, 128, 129, 32767, 32768, 32769],
},
{
from: Int16Array,
to: Int32Array,
values: [-32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769],
expected: [32767, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, -32768, -32767],
},
{
from: Int16Array,
to: Uint32Array,
values: [-32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769],
expected: [32767, 4294934528, 4294934529, 4294967167, 4294967168, 4294967169, 4294967295, 0, 1, 127, 128, 129, 32767, 4294934528, 4294934529],
},
{
from: Int16Array,
to: Float32Array,
values: [-32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769],
expected: [32767, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, -32768, -32767],
},
{
from: Int16Array,
to: Float64Array,
values: [-32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769],
expected: [32767, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, -32768, -32767],
},
/* Uint16Array */
{
from: Uint16Array,
to: Int8Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536],
expected: [0, 1, 127, -128, -127, -2, -1, 0, -1, 0, 1, -2, -1, 0],
},
{
from: Uint16Array,
to: Uint8Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536],
expected: [0, 1, 127, 128, 129, 254, 255, 0, 255, 0, 1, 254, 255, 0],
},
{
from: Uint16Array,
to: Uint8ClampedArray,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536],
expected: [0, 1, 127, 128, 129, 254, 255, 255, 255, 255, 255, 255, 255, 0],
},
{
from: Uint16Array,
to: Int16Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, -32768, -32767, -2, -1, 0],
},
{
from: Uint16Array,
to: Uint16Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 0],
},
{
from: Uint16Array,
to: Int32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 0],
},
{
from: Uint16Array,
to: Uint32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 0],
},
{
from: Uint16Array,
to: Float32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 0],
},
{
from: Uint16Array,
to: Float64Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 0],
},
/* Int32Array */
{
from: Int32Array,
to: Int8Array,
values: [-2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
expected: [-1, 0, 1, -1, 0, 1, 127, -128, -127, -1, 0, 1, 127, -128, -127, -1, 0, 1, -1, 0, 1],
},
{
from: Int32Array,
to: Uint8Array,
values: [-2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
expected: [255, 0, 1, 255, 0, 1, 127, 128, 129, 255, 0, 1, 127, 128, 129, 255, 0, 1, 255, 0, 1],
},
{
from: Int32Array,
to: Uint8ClampedArray,
values: [-2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
expected: [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 127, 128, 129, 255, 255, 255, 255, 0, 0],
},
{
from: Int32Array,
to: Int16Array,
values: [-2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
expected: [-1, 0, 1, 32767, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, -32768, -32767, -1, 0, 1],
},
{
from: Int32Array,
to: Uint16Array,
values: [-2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
expected: [65535, 0, 1, 32767, 32768, 32769, 65407, 65408, 65409, 65535, 0, 1, 127, 128, 129, 32767, 32768, 32769, 65535, 0, 1],
},
{
from: Int32Array,
to: Int32Array,
values: [-2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
expected: [2147483647, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, -2147483648, -2147483647],
},
{
from: Int32Array,
to: Uint32Array,
values: [-2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
expected: [2147483647, 2147483648, 2147483649, 4294934527, 4294934528, 4294934529, 4294967167, 4294967168, 4294967169, 4294967295, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
},
{
from: Int32Array,
to: Float32Array,
values: [-2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
expected: [2147483648, -2147483648, -2147483648, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483648, -2147483648, -2147483648],
},
{
from: Int32Array,
to: Float64Array,
values: [-2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649],
expected: [2147483647, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, 0, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, -2147483648, -2147483647],
},
/* Uint32Array */
{
from: Uint32Array,
to: Int8Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 4294967296],
expected: [0, 1, 127, -128, -127, -2, -1, 0, -1, 0, 1, -2, -1, 0, -1, 0, 1, -2, -1, 0],
},
{
from: Uint32Array,
to: Uint8Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 4294967296],
expected: [0, 1, 127, 128, 129, 254, 255, 0, 255, 0, 1, 254, 255, 0, 255, 0, 1, 254, 255, 0],
},
{
from: Uint32Array,
to: Uint8ClampedArray,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 4294967296],
expected: [0, 1, 127, 128, 129, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0],
},
{
from: Uint32Array,
to: Int16Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 4294967296],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, -32768, -32767, -2, -1, 0, -1, 0, 1, -2, -1, 0],
},
{
from: Uint32Array,
to: Uint16Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 4294967296],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 0, 65535, 0, 1, 65534, 65535, 0],
},
{
from: Uint32Array,
to: Int32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 4294967296],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, -2147483648, -2147483647, -2, -1, 0],
},
{
from: Uint32Array,
to: Uint32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 4294967296],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 0],
},
{
from: Uint32Array,
to: Float32Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 4294967296],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483648, 2147483648, 2147483648, 4294967296, 4294967296, 0],
},
{
from: Uint32Array,
to: Float64Array,
values: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 4294967296],
expected: [0, 1, 127, 128, 129, 254, 255, 256, 32767, 32768, 32769, 65534, 65535, 65536, 2147483647, 2147483648, 2147483649, 4294967294, 4294967295, 0],
},
/* Float32Array */
{
from: Float32Array,
to: Int8Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 0, 0, 0, -1, 0, 1, 127, -128, -127, -1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 127, -128, -127, -1, 0, 1, 0, 0, 0, 0, 0],
},
{
from: Float32Array,
to: Uint8Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 0, 0, 0, 255, 0, 1, 127, 128, 129, 255, 255, 255, 255, 0, 0, 1, 1, 1, 1, 127, 128, 129, 255, 0, 1, 0, 0, 0, 0, 0],
},
{
from: Float32Array,
to: Uint8ClampedArray,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 127, 128, 129, 255, 255, 255, 255, 255, 255, 255, 0],
},
{
from: Float32Array,
to: Int16Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 0, 0, 0, 32767, -32768, -32767, -129, -128, -127, -1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 127, 128, 129, 32767, -32768, -32767, 0, 0, 0, 0, 0],
},
{
from: Float32Array,
to: Uint16Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 0, 0, 0, 32767, 32768, 32769, 65407, 65408, 65409, 65535, 65535, 65535, 65535, 0, 0, 1, 1, 1, 1, 127, 128, 129, 32767, 32768, 32769, 0, 0, 0, 0, 0],
},
{
from: Float32Array,
to: Int32Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, -2147483648, -2147483648, -2147483648, -32769, -32768, -32767, -129, -128, -127, -1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 127, 128, 129, 32767, 32768, 32769, -2147483648, -2147483648, -2147483648, 0, 0],
},
{
from: Float32Array,
to: Uint32Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 2147483648, 2147483648, 2147483648, 4294934527, 4294934528, 4294934529, 4294967167, 4294967168, 4294967169, 4294967295, 4294967295, 4294967295, 4294967295, 0, 0, 1, 1, 1, 1, 127, 128, 129, 32767, 32768, 32769, 2147483648, 2147483648, 2147483648, 0, 0],
},
{
from: Float32Array,
to: Float32Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [-Infinity, -2147483648, -2147483648, -2147483648, -32769, -32768, -32767, -129, -128, -127, -1.600000023841858, -1.5, -1.399999976158142, -1, -0, 0, 1, 1.399999976158142, 1.5, 1.600000023841858, 127, 128, 129, 32767, 32768, 32769, 2147483648, 2147483648, 2147483648, Infinity, NaN],
},
{
from: Float32Array,
to: Float64Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [-Infinity, -2147483648, -2147483648, -2147483648, -32769, -32768, -32767, -129, -128, -127, -1.600000023841858, -1.5, -1.399999976158142, -1, -0, 0, 1, 1.399999976158142, 1.5, 1.600000023841858, 127, 128, 129, 32767, 32768, 32769, 2147483648, 2147483648, 2147483648, Infinity, NaN],
},
/* Float64Array */
{
from: Float64Array,
to: Int8Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, -1, 0, 1, -1, 0, 1, 127, -128, -127, -1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 127, -128, -127, -1, 0, 1, -1, 0, 1, 0, 0],
},
{
from: Float64Array,
to: Uint8Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 255, 0, 1, 255, 0, 1, 127, 128, 129, 255, 255, 255, 255, 0, 0, 1, 1, 1, 1, 127, 128, 129, 255, 0, 1, 255, 0, 1, 0, 0],
},
{
from: Float64Array,
to: Uint8ClampedArray,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 127, 128, 129, 255, 255, 255, 255, 255, 255, 255, 0],
},
{
from: Float64Array,
to: Int16Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, -1, 0, 1, 32767, -32768, -32767, -129, -128, -127, -1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 127, 128, 129, 32767, -32768, -32767, -1, 0, 1, 0, 0],
},
{
from: Float64Array,
to: Uint16Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 65535, 0, 1, 32767, 32768, 32769, 65407, 65408, 65409, 65535, 65535, 65535, 65535, 0, 0, 1, 1, 1, 1, 127, 128, 129, 32767, 32768, 32769, 65535, 0, 1, 0, 0],
},
{
from: Float64Array,
to: Int32Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 2147483647, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, -2147483648, -2147483647, 0, 0],
},
{
from: Float64Array,
to: Uint32Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [0, 2147483647, 2147483648, 2147483649, 4294934527, 4294934528, 4294934529, 4294967167, 4294967168, 4294967169, 4294967295, 4294967295, 4294967295, 4294967295, 0, 0, 1, 1, 1, 1, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, 0, 0],
},
{
from: Float64Array,
to: Float32Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [-Infinity, -2147483648, -2147483648, -2147483648, -32769, -32768, -32767, -129, -128, -127, -1.600000023841858, -1.5, -1.399999976158142, -1, -0, 0, 1, 1.399999976158142, 1.5, 1.600000023841858, 127, 128, 129, 32767, 32768, 32769, 2147483648, 2147483648, 2147483648, Infinity, NaN],
},
{
from: Float64Array,
to: Float64Array,
values: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
expected: [-Infinity, -2147483649, -2147483648, -2147483647, -32769, -32768, -32767, -129, -128, -127, -1.6, -1.5, -1.4, -1, -0, 0, 1, 1.4, 1.5, 1.6, 127, 128, 129, 32767, 32768, 32769, 2147483647, 2147483648, 2147483649, Infinity, NaN],
},
];
for (let {from, to, values, expected} of tests) {
let ta = new from(values);
ta.constructor = to;
assertEqArray(ta.slice(0), expected, `${from.name} -> ${to.name}`);
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,84 @@
const otherGlobal = newGlobal();
// Create with new ArrayBuffer and offset.
for (var constructor of typedArrayConstructors) {
const elementSize = constructor.BYTES_PER_ELEMENT;
let ab = new constructor(10).map((v, i) => i).buffer;
let ta = new constructor(ab, 2 * elementSize, 6);
ta.constructor = {
[Symbol.species]: function(len) {
return new constructor(new ArrayBuffer((len + 4) * elementSize), 4 * elementSize);
}
};
let tb = ta.slice(0);
assertEqArray(ta, [2, 3, 4, 5, 6, 7]);
assertEqArray(tb, [2, 3, 4, 5, 6, 7]);
}
// Source and target arrays use the same ArrayBuffer, target range before source range.
for (var constructor of typedArrayConstructors) {
const elementSize = constructor.BYTES_PER_ELEMENT;
let ab = new constructor(10).map((v, i) => i).buffer;
let ta = new constructor(ab, 2 * elementSize, 6);
ta.constructor = {
[Symbol.species]: function(len) {
return new constructor(ab, 0, len);
}
};
let tb = ta.slice(0);
assertEqArray(ta, [4, 5, 6, 7, 6, 7]);
assertEqArray(tb, [2, 3, 4, 5, 6, 7]);
assertEqArray(new constructor(ab), [2, 3, 4, 5, 6, 7, 6, 7, 8, 9]);
}
// Source and target arrays use the same ArrayBuffer, target range after source range.
for (var constructor of typedArrayConstructors) {
const elementSize = constructor.BYTES_PER_ELEMENT;
let ab = new constructor(10).map((v, i) => i + 1).buffer;
let ta = new constructor(ab, 0, 6);
ta.constructor = {
[Symbol.species]: function(len) {
return new constructor(ab, 2 * elementSize, len);
}
};
let tb = ta.slice(0);
assertEqArray(ta, [1, 2, 1, 2, 1, 2]);
assertEqArray(tb, [1, 2, 1, 2, 1, 2]);
assertEqArray(new constructor(ab), [1, 2, 1, 2, 1, 2, 1, 2, 9, 10]);
}
// Tricky: Same as above, but with SharedArrayBuffer and different compartments.
if (typeof setSharedArrayBuffer === "function") {
for (var constructor of typedArrayConstructors) {
const elementSize = constructor.BYTES_PER_ELEMENT;
let ts = new constructor(new SharedArrayBuffer(10 * elementSize));
for (let i = 0; i < ts.length; i++) {
ts[i] = i + 1;
}
let ab = ts.buffer;
let ta = new constructor(ab, 0, 6);
ta.constructor = {
[Symbol.species]: function(len) {
setSharedArrayBuffer(ab);
try {
return otherGlobal.eval(`
new ${constructor.name}(getSharedArrayBuffer(), ${2 * elementSize}, ${len});
`);
} finally {
setSharedArrayBuffer(null);
}
}
};
let tb = ta.slice(0);
assertEqArray(ta, [1, 2, 1, 2, 1, 2]);
assertEqArray(tb, [1, 2, 1, 2, 1, 2]);
assertEqArray(new constructor(ab), [1, 2, 1, 2, 1, 2, 1, 2, 9, 10]);
}
}
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -1252,8 +1252,13 @@ DangerouslyUnwrapTypedArray(JSContext* cx, JSObject* obj)
// An unwrapped pointer to an object potentially on the other side of a
// compartment boundary! Isn't this such fun?
JSObject* unwrapped = CheckedUnwrap(obj);
if (!unwrapped) {
ReportAccessDenied(cx);
return nullptr;
}
if (!unwrapped->is<TypedArrayObject>()) {
// By *appearances* this can't happen, as self-hosted TypedArraySet
// By *appearances* this can't happen, as self-hosted code
// checked this. But. Who's to say a GC couldn't happen between
// the check that this value was a typed array, and this extraction
// occurring? A GC might turn a cross-compartment wrapper |obj| into
@ -1588,6 +1593,113 @@ intrinsic_SetOverlappingTypedElements(JSContext* cx, unsigned argc, Value* vp)
return true;
}
// The specification requires us to perform bitwise copying when |sourceType|
// and |targetType| are the same (ES2017, §22.2.3.24, step 15). Additionally,
// as an optimization, we can also perform bitwise copying when |sourceType|
// and |targetType| have compatible bit-level representations.
static bool
IsTypedArrayBitwiseSlice(Scalar::Type sourceType, Scalar::Type targetType)
{
switch (sourceType) {
case Scalar::Int8:
return targetType == Scalar::Int8 || targetType == Scalar::Uint8;
case Scalar::Uint8:
case Scalar::Uint8Clamped:
return targetType == Scalar::Int8 || targetType == Scalar::Uint8 ||
targetType == Scalar::Uint8Clamped;
case Scalar::Int16:
case Scalar::Uint16:
return targetType == Scalar::Int16 || targetType == Scalar::Uint16;
case Scalar::Int32:
case Scalar::Uint32:
return targetType == Scalar::Int32 || targetType == Scalar::Uint32;
case Scalar::Float32:
return targetType == Scalar::Float32;
case Scalar::Float64:
return targetType == Scalar::Float64;
default:
MOZ_CRASH("IsTypedArrayBitwiseSlice with a bogus typed array type");
}
}
static bool
intrinsic_TypedArrayBitwiseSlice(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 4);
MOZ_ASSERT(args[0].isObject());
MOZ_ASSERT(args[1].isObject());
MOZ_ASSERT(args[2].isInt32());
MOZ_ASSERT(args[3].isInt32());
Rooted<TypedArrayObject*> source(cx, &args[0].toObject().as<TypedArrayObject>());
MOZ_ASSERT(!source->hasDetachedBuffer());
// As directed by |DangerouslyUnwrapTypedArray|, sigil this pointer and all
// variables derived from it to counsel extreme caution here.
Rooted<TypedArrayObject*> unsafeTypedArrayCrossCompartment(cx);
unsafeTypedArrayCrossCompartment = DangerouslyUnwrapTypedArray(cx, &args[1].toObject());
if (!unsafeTypedArrayCrossCompartment)
return false;
MOZ_ASSERT(!unsafeTypedArrayCrossCompartment->hasDetachedBuffer());
Scalar::Type sourceType = source->type();
if (!IsTypedArrayBitwiseSlice(sourceType, unsafeTypedArrayCrossCompartment->type())) {
args.rval().setBoolean(false);
return true;
}
MOZ_ASSERT(args[2].toInt32() >= 0);
uint32_t sourceOffset = uint32_t(args[2].toInt32());
MOZ_ASSERT(args[3].toInt32() >= 0);
uint32_t count = uint32_t(args[3].toInt32());
MOZ_ASSERT(count > 0 && count <= source->length());
MOZ_ASSERT(sourceOffset <= source->length() - count);
MOZ_ASSERT(count <= unsafeTypedArrayCrossCompartment->length());
size_t elementSize = TypedArrayElemSize(sourceType);
MOZ_ASSERT(elementSize == TypedArrayElemSize(unsafeTypedArrayCrossCompartment->type()));
SharedMem<uint8_t*> sourceData =
source->viewDataEither().cast<uint8_t*>() + sourceOffset * elementSize;
SharedMem<uint8_t*> unsafeTargetDataCrossCompartment =
unsafeTypedArrayCrossCompartment->viewDataEither().cast<uint8_t*>();
uint32_t byteLength = count * elementSize;
// The same-type case requires exact copying preserving the bit-level
// encoding of the source data, so use memcpy if possible. If source and
// target are the same buffer, we can't use memcpy (or memmove), because
// the specification requires sequential copying of the values. This case
// is only possible if a @@species constructor created a specifically
// crafted typed array. It won't happen in normal code and hence doesn't
// need to be optimized.
if (!TypedArrayObject::sameBuffer(source, unsafeTypedArrayCrossCompartment)) {
jit::AtomicOperations::memcpySafeWhenRacy(unsafeTargetDataCrossCompartment,
sourceData,
byteLength);
} else {
using namespace jit;
for (; byteLength > 0; byteLength--) {
AtomicOperations::storeSafeWhenRacy(unsafeTargetDataCrossCompartment++,
AtomicOperations::loadSafeWhenRacy(sourceData++));
}
}
args.rval().setBoolean(true);
return true;
}
static bool
intrinsic_RegExpCreate(JSContext* cx, unsigned argc, Value* vp)
{
@ -2473,6 +2585,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_INLINABLE_FN("SetDisjointTypedElements",intrinsic_SetDisjointTypedElements,3,0,
IntrinsicSetDisjointTypedElements),
JS_FN("TypedArrayBitwiseSlice", intrinsic_TypedArrayBitwiseSlice, 4, 0),
JS_FN("CallArrayBufferMethodIfWrapped",
CallNonGenericSelfhostedMethod<Is<ArrayBufferObject>>, 2, 0),
JS_FN("CallSharedArrayBufferMethodIfWrapped",