Source code

Revision control

Copy as Markdown

Other Tools

// |reftest| skip-if(!xulRuntime.shell)
/* -*- Mode: js2; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Any copyright is dedicated to the Public Domain.
*/
// Minimal test cases. Note that on 64-bit a SharedArrayBuffer is
// very expensive under these rules - a 4GB area is reserved for it.
// So don't go allocating a ton of them.
//
// These tests cannot test that sharing works across workers. There
// are or will be tests, in dom/workers, that do that.
var b;
function testSharedArrayBuffer() {
b = new SharedArrayBuffer("4096"); // Test string conversion, too
assertEq(b instanceof SharedArrayBuffer, true);
assertEq(b.byteLength, 4096);
b.fnord = "Hi there";
assertEq(b.fnord, "Hi there");
SharedArrayBuffer.prototype.abracadabra = "no wishing for wishes!";
assertEq(b.abracadabra, "no wishing for wishes!");
// SharedArrayBuffer is not a conversion operator, not even for instances of itself
assertThrowsInstanceOf(() => SharedArrayBuffer(b), TypeError);
// can't convert any other object either
assertThrowsInstanceOf(() => SharedArrayBuffer({}), TypeError);
// byteLength can be invoked as per normal, indirectly
assertEq(Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype,"byteLength").get.call(b), 4096);
// however byteLength is not generic
assertThrowsInstanceOf(() => Object.getOwnPropertyDescriptor(SharedArrayBuffer.prototype,"byteLength").get.call({}), TypeError);
}
function testSharedTypedArray() {
var x1 = new Int8Array(b);
var x2 = new Int32Array(b);
assertEq(ArrayBuffer.isView(x1), true); // ArrayBuffer.isView() works even if the buffer is a SharedArrayBuffer
assertEq(ArrayBuffer.isView(x2), true);
assertEq(ArrayBuffer.isView({}), false);
assertEq(x1.buffer, b);
assertEq(x2.buffer, b);
assertEq(x1.byteLength, b.byteLength);
assertEq(x2.byteLength, b.byteLength);
assertEq(x1.byteOffset, 0);
assertEq(x2.byteOffset, 0);
assertEq(x1.length, b.byteLength);
assertEq(x2.length, b.byteLength / 4);
var x3 = new Int8Array(b, 20);
assertEq(x3.length, b.byteLength - 20);
assertEq(x3.byteOffset, 20);
var x3 = new Int32Array(b, 20, 10);
assertEq(x3.length, 10);
assertEq(x3.byteOffset, 20);
// Mismatched type
assertThrowsInstanceOf(() => Int8Array(x2), TypeError);
// Unconvertable object
assertThrowsInstanceOf(() => Int8Array({}), TypeError);
// negative start
assertThrowsInstanceOf(() => new Int8Array(b, -7), RangeError);
// not congruent mod element size
assertThrowsInstanceOf(() => new Int32Array(b, 3), RangeError);
// start out of range
assertThrowsInstanceOf(() => new Int32Array(b, 4104), RangeError);
// end out of range
assertThrowsInstanceOf(() => new Int32Array(b, 4092, 2), RangeError);
// Views alias the storage
x2[0] = -1;
assertEq(x1[0], -1);
x1[0] = 1;
x1[1] = 1;
x1[2] = 1;
x1[3] = 1;
assertEq(x2[0], 0x01010101);
assertEq(x2[5], 0);
x3[0] = -1;
assertEq(x2[5], -1);
// Out-of-range accesses yield undefined
assertEq(x2[1023], 0);
assertEq(x2[1024], undefined);
assertEq(x2[2047], undefined);
}
function testSharedTypedArrayMethods() {
var v = new Int32Array(b);
for ( var i=0 ; i < v.length ; i++ )
v[i] = i;
// Rudimentary tests - they don't test any boundary conditions
// subarray
var w = v.subarray(10, 20);
assertEq(w.length, 10);
for ( var i=0 ; i < w.length ; i++ )
assertEq(w[i], v[i+10]);
for ( var i=0 ; i < w.length ; i++ )
w[i] = -w[i];
for ( var i=0 ; i < w.length ; i++ )
assertEq(w[i], v[i+10]);
// copyWithin
for ( var i=0 ; i < v.length ; i++ )
v[i] = i;
v.copyWithin(10, 20, 30);
for ( var i=0 ; i < 10 ; i++ )
assertEq(v[i], i);
for ( var i=10 ; i < 20 ; i++ )
assertEq(v[i], v[i+10]);
// set
for ( var i=0 ; i < v.length ; i++ )
v[i] = i;
v.set([-1,-2,-3,-4,-5,-6,-7,-8,-9,-10], 5);
for ( var i=5 ; i < 15 ; i++ )
assertEq(v[i], -i+4);
// In the following two cases the two arrays will reference the same buffer,
// so there will be an overlapping copy.
//
// Case 1: Read from lower indices than are written
v.set(v.subarray(0, 7), 1);
assertEq(v[0], 0);
assertEq(v[1], 0);
assertEq(v[2], 1);
assertEq(v[3], 2);
assertEq(v[4], 3);
assertEq(v[5], 4);
assertEq(v[6], -1);
assertEq(v[7], -2);
assertEq(v[8], -4);
assertEq(v[9], -5);
// Case 2: Read from higher indices than are written
v.set(v.subarray(1, 5), 0);
assertEq(v[0], 0);
assertEq(v[1], 1);
assertEq(v[2], 2);
assertEq(v[3], 3);
assertEq(v[4], 3);
assertEq(v[5], 4);
assertEq(v[6], -1);
assertEq(v[7], -2);
assertEq(v[8], -4);
assertEq(v[9], -5);
}
function testClone1() {
var sab1 = b;
var blob = serialize(sab1, [], {SharedArrayBuffer: 'allow'});
var sab2 = deserialize(blob, {SharedArrayBuffer: 'allow'});
if (typeof sharedAddress != "undefined")
assertEq(sharedAddress(sab1), sharedAddress(sab2));
}
function testClone2() {
var sab = b;
var ia1 = new Int32Array(sab);
var blob = serialize(ia1, [], {SharedArrayBuffer: 'allow'});
var ia2 = deserialize(blob, {SharedArrayBuffer: 'allow'});
assertEq(ia1.length, ia2.length);
assertEq(ia1.buffer instanceof SharedArrayBuffer, true);
if (typeof sharedAddress != "undefined")
assertEq(sharedAddress(ia1.buffer), sharedAddress(ia2.buffer));
ia1[10] = 37;
assertEq(ia2[10], 37);
}
// Serializing a SharedArrayBuffer should fail if we've set its flag to 'deny' or if
// the flag is bogus or if the flag is not set to 'allow' explicitly
function testNoClone() {
// This just tests the API in serialize()
assertThrowsInstanceOf(() => serialize(b, [], {SharedArrayBuffer: false}), Error);
// This tests the actual cloning functionality - should fail
assertThrowsInstanceOf(() => serialize(b, [], {SharedArrayBuffer: 'deny'}), TypeError);
// This tests that cloning a SharedArrayBuffer is not allowed by default
assertThrowsInstanceOf(() => serialize(b), TypeError);
// Ditto - should succeed
assertEq(typeof serialize(b, [], {SharedArrayBuffer: 'allow'}), "object");
let blob = serialize(b, [], {SharedArrayBuffer: 'allow'});
// This just tests the API in deserialize()
assertThrowsInstanceOf(() => deserialize(blob, {SharedArrayBuffer: false}), Error);
// This tests the actual cloning functionality - should fail
assertThrowsInstanceOf(() => deserialize(blob, {SharedArrayBuffer: 'deny'}), TypeError);
// This tests that cloning a SharedArrayBuffer is not allowed by default
assertThrowsInstanceOf(() => deserialize(blob), TypeError);
// Ditto - should succeed
assertEq(typeof deserialize(blob, {SharedArrayBuffer: 'allow'}), "object");
}
function testRedundantTransfer() {
// Throws TypeError in the shell, DataCloneError in the browser.
assertThrowsInstanceOf(() => {
var sab1 = b;
var blob = serialize(sab1, [sab1], {SharedArrayBuffer: 'allow'});
}, TypeError);
}
function testApplicable() {
var sab = b;
var x;
// Just make sure we can create all the view types on shared memory.
x = new Int32Array(sab);
assertEq(x.length, sab.byteLength / Int32Array.BYTES_PER_ELEMENT);
x = new Uint32Array(sab);
assertEq(x.length, sab.byteLength / Uint32Array.BYTES_PER_ELEMENT);
x = new Int16Array(sab);
assertEq(x.length, sab.byteLength / Int16Array.BYTES_PER_ELEMENT);
x = new Uint16Array(sab);
assertEq(x.length, sab.byteLength / Uint16Array.BYTES_PER_ELEMENT);
x = new Int8Array(sab);
assertEq(x.length, sab.byteLength / Int8Array.BYTES_PER_ELEMENT);
x = new Uint8Array(sab);
assertEq(x.length, sab.byteLength / Uint8Array.BYTES_PER_ELEMENT);
// Though the atomic operations are illegal on Uint8ClampedArray and the
// float arrays, they can still be used to create views on shared memory.
x = new Uint8ClampedArray(sab);
assertEq(x.length, sab.byteLength / Uint8ClampedArray.BYTES_PER_ELEMENT);
x = new Float32Array(sab);
assertEq(x.length, sab.byteLength / Float32Array.BYTES_PER_ELEMENT);
x = new Float64Array(sab);
assertEq(x.length, sab.byteLength / Float64Array.BYTES_PER_ELEMENT);
}
if (this.SharedArrayBuffer) {
testSharedArrayBuffer();
testSharedTypedArray();
testSharedTypedArrayMethods();
testClone1();
testClone2();
testNoClone();
testRedundantTransfer();
testApplicable();
}
reportCompare(0, 0, 'ok');