2021-05-06 10:43:37 +00:00
|
|
|
|
// Copyright 2021 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: --harmony-rab-gsab --allow-natives-syntax
|
|
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
2021-07-20 07:20:42 +00:00
|
|
|
|
function CreateResizableArrayBuffer(byteLength, maxByteLength) {
|
|
|
|
|
return new ArrayBuffer(byteLength, {maxByteLength: maxByteLength});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function CreateGrowableSharedArrayBuffer(byteLength, maxByteLength) {
|
|
|
|
|
return new SharedArrayBuffer(byteLength, {maxByteLength: maxByteLength});
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-06 10:43:37 +00:00
|
|
|
|
function resizeHelper(ab, value) {
|
|
|
|
|
const return_value = ab.resize(value);
|
|
|
|
|
assertEquals(undefined, return_value);
|
|
|
|
|
assertEquals(value, ab.byteLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function growHelper(ab, value) {
|
|
|
|
|
const return_value = ab.grow(value);
|
|
|
|
|
assertEquals(undefined, return_value);
|
|
|
|
|
assertEquals(value, ab.byteLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(function TestRABBasics() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
|
|
|
|
assertTrue(rab instanceof ArrayBuffer);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertFalse(rab instanceof SharedArrayBuffer);
|
|
|
|
|
assertEquals(10, rab.byteLength);
|
|
|
|
|
assertEquals(20, rab.maxByteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABCtorByteLengthEqualsMax() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 10);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, rab.byteLength);
|
|
|
|
|
assertEquals(10, rab.maxByteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABCtorByteLengthZero() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(0, 10);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(0, rab.byteLength);
|
|
|
|
|
assertEquals(10, rab.maxByteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABCtorByteLengthAndMaxZero() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(0, 0);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(0, rab.byteLength);
|
|
|
|
|
assertEquals(0, rab.maxByteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const ctors = [[ArrayBuffer, (b) => b.resizable],
|
|
|
|
|
[SharedArrayBuffer, (b) => b.growable]];
|
|
|
|
|
|
|
|
|
|
(function TestOptionsBagNotObject() {
|
|
|
|
|
for (let [ctor, resizable] of ctors) {
|
|
|
|
|
const buffer = new ctor(10, 'this is not an options bag');
|
|
|
|
|
assertFalse(resizable(buffer));
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestOptionsBagMaxByteLengthGetterThrows() {
|
|
|
|
|
let evil = {};
|
|
|
|
|
Object.defineProperty(evil, 'maxByteLength',
|
|
|
|
|
{get: () => { throw new Error('thrown'); }});
|
|
|
|
|
for (let [ctor, resizable] of ctors) {
|
|
|
|
|
let caught = false;
|
|
|
|
|
try {
|
|
|
|
|
new ctor(10, evil);
|
|
|
|
|
} catch(e) {
|
|
|
|
|
assertEquals('thrown', e.message);
|
|
|
|
|
caught = true;
|
|
|
|
|
}
|
|
|
|
|
assertTrue(caught);
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestMaxByteLengthNonExisting() {
|
|
|
|
|
for (let [ctor, resizable] of ctors) {
|
|
|
|
|
const buffer = new ctor(10, {});
|
|
|
|
|
assertFalse(resizable(buffer));
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestMaxByteLengthUndefinedOrNan() {
|
|
|
|
|
for (let [ctor, resizable] of ctors) {
|
|
|
|
|
const buffer1 = new ctor(10, {maxByteLength: undefined});
|
|
|
|
|
assertFalse(resizable(buffer1));
|
|
|
|
|
const buffer2 = new ctor(0, {maxByteLength: NaN});
|
|
|
|
|
assertTrue(resizable(buffer2));
|
|
|
|
|
assertEquals(0, buffer2.byteLength);
|
|
|
|
|
assertEquals(0, buffer2.maxByteLength);
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestMaxByteLengthBooleanNullOrString() {
|
|
|
|
|
for (let [ctor, resizable] of ctors) {
|
|
|
|
|
const buffer1 = new ctor(0, {maxByteLength: true});
|
|
|
|
|
assertTrue(resizable(buffer1));
|
|
|
|
|
assertEquals(0, buffer1.byteLength);
|
|
|
|
|
assertEquals(1, buffer1.maxByteLength);
|
|
|
|
|
const buffer2 = new ctor(0, {maxByteLength: false});
|
|
|
|
|
assertTrue(resizable(buffer2));
|
|
|
|
|
assertEquals(0, buffer2.byteLength);
|
|
|
|
|
assertEquals(0, buffer2.maxByteLength);
|
|
|
|
|
const buffer3 = new ctor(0, {maxByteLength: null});
|
|
|
|
|
assertTrue(resizable(buffer3));
|
|
|
|
|
assertEquals(0, buffer3.byteLength);
|
|
|
|
|
assertEquals(0, buffer3.maxByteLength);
|
|
|
|
|
const buffer4 = new ctor(0, {maxByteLength: '100'});
|
|
|
|
|
assertTrue(resizable(buffer4));
|
|
|
|
|
assertEquals(0, buffer4.byteLength);
|
|
|
|
|
assertEquals(100, buffer4.maxByteLength);
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestMaxByteLengthDouble() {
|
|
|
|
|
for (let [ctor, resizable] of ctors) {
|
|
|
|
|
const buffer1 = new ctor(0, {maxByteLength: -0.0});
|
|
|
|
|
assertTrue(resizable(buffer1));
|
|
|
|
|
assertEquals(0, buffer1.byteLength);
|
|
|
|
|
assertEquals(0, buffer1.maxByteLength);
|
|
|
|
|
const buffer2 = new ctor(0, {maxByteLength: -0.1});
|
|
|
|
|
assertTrue(resizable(buffer2));
|
|
|
|
|
assertEquals(0, buffer2.byteLength);
|
|
|
|
|
assertEquals(0, buffer2.maxByteLength);
|
|
|
|
|
const buffer3 = new ctor(0, {maxByteLength: 1.2});
|
|
|
|
|
assertTrue(resizable(buffer3));
|
|
|
|
|
assertEquals(0, buffer3.byteLength);
|
|
|
|
|
assertEquals(1, buffer3.maxByteLength);
|
|
|
|
|
assertThrows(() => { new ctor(0, {maxByteLength: -1.5}) });
|
|
|
|
|
assertThrows(() => { new ctor(0, {maxByteLength: -1}) });
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestMaxByteLengthThrows() {
|
|
|
|
|
const evil = {valueOf: () => { throw new Error('thrown');}};
|
|
|
|
|
for (let [ctor, resizable] of ctors) {
|
|
|
|
|
let caught = false;
|
|
|
|
|
try {
|
|
|
|
|
new ctor(0, {maxByteLength: evil});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
assertEquals('thrown', e.message);
|
|
|
|
|
caught = true;
|
|
|
|
|
}
|
|
|
|
|
assertTrue(caught);
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestByteLengthThrows() {
|
|
|
|
|
const evil1 = {valueOf: () => { throw new Error('byteLength throws');}};
|
|
|
|
|
const evil2 = {valueOf: () => { throw new Error('maxByteLength throws');}};
|
|
|
|
|
for (let [ctor, resizable] of ctors) {
|
|
|
|
|
let caught = false;
|
|
|
|
|
try {
|
|
|
|
|
new ctor(evil1, {maxByteLength: evil2});
|
|
|
|
|
} catch (e) {
|
|
|
|
|
assertEquals('byteLength throws', e.message);
|
|
|
|
|
caught = true;
|
|
|
|
|
}
|
|
|
|
|
assertTrue(caught);
|
|
|
|
|
}
|
2021-05-06 10:43:37 +00:00
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestAllocatingOutrageouslyMuchThrows() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
assertThrows(() => { CreateResizableArrayBuffer(0, 2 ** 100);}, RangeError);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABCtorOperationOrder() {
|
|
|
|
|
let log = '';
|
|
|
|
|
const mock_length = {valueOf: function() {
|
|
|
|
|
log += 'valueof length, '; return 10; }};
|
|
|
|
|
const mock_max_length = {valueOf: function() {
|
|
|
|
|
log += 'valueof max_length, '; return 10; }};
|
2021-07-20 07:20:42 +00:00
|
|
|
|
CreateResizableArrayBuffer(mock_length, mock_max_length);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
|
|
|
|
|
assertEquals('valueof length, valueof max_length, ', log);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABCtorOperationOrder() {
|
|
|
|
|
let log = '';
|
|
|
|
|
const mock_length = {valueOf: function() {
|
|
|
|
|
log += 'valueof length, '; return 10; }};
|
|
|
|
|
const mock_max_length = {valueOf: function() {
|
|
|
|
|
log += 'valueof max_length, '; return 10; }};
|
2021-07-20 07:20:42 +00:00
|
|
|
|
CreateResizableArrayBuffer(mock_length, mock_max_length);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
|
|
|
|
|
assertEquals('valueof length, valueof max_length, ', log);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestByteLengthGetterReceiverChecks() {
|
|
|
|
|
const name = 'byteLength';
|
|
|
|
|
const ab_getter = Object.getOwnPropertyDescriptor(
|
|
|
|
|
ArrayBuffer.prototype, name).get;
|
|
|
|
|
const sab_getter = Object.getOwnPropertyDescriptor(
|
|
|
|
|
SharedArrayBuffer.prototype, name).get;
|
|
|
|
|
|
|
|
|
|
const ab = new ArrayBuffer(40);
|
|
|
|
|
const sab = new SharedArrayBuffer(40);
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(40, 40);
|
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(40, 40);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
|
|
|
|
|
assertEquals(40, ab_getter.call(ab));
|
2021-07-20 07:20:42 +00:00
|
|
|
|
assertEquals(40, ab_getter.call(rab));
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(40, sab_getter.call(sab));
|
2021-07-20 07:20:42 +00:00
|
|
|
|
assertEquals(40, sab_getter.call(gsab));
|
2021-05-06 10:43:37 +00:00
|
|
|
|
|
|
|
|
|
assertThrows(() => { ab_getter.call(sab);});
|
|
|
|
|
assertThrows(() => { ab_getter.call(gsab);});
|
|
|
|
|
|
|
|
|
|
assertThrows(() => { sab_getter.call(ab);});
|
|
|
|
|
assertThrows(() => { sab_getter.call(rab);});
|
2021-07-16 12:26:21 +00:00
|
|
|
|
})();
|
|
|
|
|
|
2021-07-19 08:00:16 +00:00
|
|
|
|
(function TestMaxByteLengthGetterReceiverChecks() {
|
|
|
|
|
const name = 'maxByteLength';
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const ab_getter = Object.getOwnPropertyDescriptor(
|
|
|
|
|
ArrayBuffer.prototype, name).get;
|
|
|
|
|
const sab_getter = Object.getOwnPropertyDescriptor(
|
|
|
|
|
SharedArrayBuffer.prototype, name).get;
|
2021-07-16 12:26:21 +00:00
|
|
|
|
|
|
|
|
|
const ab = new ArrayBuffer(40);
|
|
|
|
|
const sab = new SharedArrayBuffer(40);
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(20, 40);
|
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(20, 40);
|
2021-07-16 12:26:21 +00:00
|
|
|
|
|
2021-07-20 07:20:42 +00:00
|
|
|
|
assertEquals(40, ab_getter.call(ab));
|
|
|
|
|
assertEquals(40, ab_getter.call(rab));
|
|
|
|
|
assertEquals(40, sab_getter.call(sab));
|
|
|
|
|
assertEquals(40, sab_getter.call(gsab));
|
2021-07-16 12:26:21 +00:00
|
|
|
|
|
2021-07-20 07:20:42 +00:00
|
|
|
|
assertThrows(() => { ab_getter.call(sab);});
|
|
|
|
|
assertThrows(() => { ab_getter.call(gsab);});
|
2021-07-16 12:26:21 +00:00
|
|
|
|
|
2021-07-20 07:20:42 +00:00
|
|
|
|
assertThrows(() => { sab_getter.call(ab);});
|
|
|
|
|
assertThrows(() => { sab_getter.call(rab);});
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestResizableGetterReceiverChecks() {
|
|
|
|
|
const ab_getter = Object.getOwnPropertyDescriptor(
|
|
|
|
|
ArrayBuffer.prototype, 'resizable').get;
|
|
|
|
|
const sab_getter = Object.getOwnPropertyDescriptor(
|
|
|
|
|
SharedArrayBuffer.prototype, 'growable').get;
|
|
|
|
|
|
|
|
|
|
const ab = new ArrayBuffer(40);
|
|
|
|
|
const sab = new SharedArrayBuffer(40);
|
|
|
|
|
const rab = CreateResizableArrayBuffer(40, 40);
|
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(40, 40);
|
|
|
|
|
|
|
|
|
|
assertEquals(false, ab_getter.call(ab));
|
|
|
|
|
assertEquals(true, ab_getter.call(rab));
|
|
|
|
|
assertEquals(false, sab_getter.call(sab));
|
|
|
|
|
assertEquals(true, sab_getter.call(gsab));
|
|
|
|
|
|
|
|
|
|
assertThrows(() => { ab_getter.call(sab);});
|
|
|
|
|
assertThrows(() => { ab_getter.call(gsab);});
|
|
|
|
|
|
|
|
|
|
assertThrows(() => { sab_getter.call(ab);});
|
|
|
|
|
assertThrows(() => { sab_getter.call(rab);});
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestByteLengthAndMaxByteLengthOfDetached() {
|
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
|
|
|
|
%ArrayBufferDetach(rab);
|
|
|
|
|
assertEquals(0, rab.byteLength);
|
|
|
|
|
assertEquals(0, rab.maxByteLength);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestResizeAndGrowReceiverChecks() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab_resize = ArrayBuffer.prototype.resize;
|
|
|
|
|
const gsab_grow = SharedArrayBuffer.prototype.grow;
|
2021-05-06 10:43:37 +00:00
|
|
|
|
|
|
|
|
|
const ab = new ArrayBuffer(40);
|
|
|
|
|
const sab = new SharedArrayBuffer(40);
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 40);
|
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 40);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
|
|
|
|
|
rab_resize.call(rab, 20);
|
|
|
|
|
gsab_grow.call(gsab, 20);
|
|
|
|
|
assertThrows(() => { rab_resize.call(ab, 30);});
|
|
|
|
|
assertThrows(() => { rab_resize.call(sab, 30);});
|
|
|
|
|
assertThrows(() => { rab_resize.call(gsab, 30);});
|
|
|
|
|
|
|
|
|
|
assertThrows(() => { gsab_grow.call(ab, 30);});
|
|
|
|
|
assertThrows(() => { gsab_grow.call(sab, 30);});
|
|
|
|
|
assertThrows(() => { gsab_grow.call(rab, 30);});
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABResizeToMax() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
resizeHelper(rab, 20);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABResizeToSameSize() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
resizeHelper(rab, 10);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABResizeToSmaller() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
resizeHelper(rab, 5);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABResizeToZero() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
resizeHelper(rab, 0);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABResizeZeroToZero() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(0, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
resizeHelper(rab, 0);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABGrowBeyondMaxThrows() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, rab.byteLength);
|
|
|
|
|
assertThrows(() => {rab.grow(21)});
|
|
|
|
|
assertEquals(10, rab.byteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABResizeMultipleTimes() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
const sizes = [15, 7, 7, 0, 8, 20, 20, 10];
|
|
|
|
|
for (let s of sizes) {
|
|
|
|
|
resizeHelper(rab, s);
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABResizeParameters() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
rab.resize('15');
|
|
|
|
|
assertEquals(15, rab.byteLength);
|
|
|
|
|
rab.resize({valueOf: function() { return 16; }});
|
|
|
|
|
assertEquals(16, rab.byteLength);
|
|
|
|
|
rab.resize(17.9);
|
|
|
|
|
assertEquals(17, rab.byteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABResizeInvalidParameters() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertThrows(() => { rab.resize(-1) }, RangeError);
|
|
|
|
|
assertThrows(() => { rab.resize({valueOf: function() {
|
|
|
|
|
throw new Error('length param'); }})});
|
|
|
|
|
assertEquals(10, rab.byteLength);
|
|
|
|
|
|
|
|
|
|
// Various non-numbers are converted to NaN which is treated as 0.
|
|
|
|
|
rab.resize('string');
|
|
|
|
|
assertEquals(0, rab.byteLength);
|
|
|
|
|
rab.resize();
|
|
|
|
|
assertEquals(0, rab.byteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABResizeDetached() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
%ArrayBufferDetach(rab);
|
|
|
|
|
assertThrows(() => { rab.resize(15) }, TypeError);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function DetachInsideResizeParameterConversion() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(40, 80);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
|
|
|
|
|
const evil = {
|
|
|
|
|
valueOf: () => { %ArrayBufferDetach(rab); return 20; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
assertThrows(() => { rab.resize(evil); });
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function ResizeInsideResizeParameterConversion() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(40, 80);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
|
|
|
|
|
const evil = {
|
|
|
|
|
valueOf: () => { rab.resize(10); return 20; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
rab.resize(evil);
|
|
|
|
|
assertEquals(20, rab.byteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(function TestRABNewMemoryAfterResizeInitializedToZero() {
|
|
|
|
|
const maybe_page_size = 4096;
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(maybe_page_size, 2 * maybe_page_size);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
const i8a = new Int8Array(rab);
|
|
|
|
|
rab.resize(2 * maybe_page_size);
|
|
|
|
|
for (let i = 0; i < 2 * maybe_page_size; ++i) {
|
|
|
|
|
assertEquals(0, i8a[i]);
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestRABMemoryInitializedToZeroAfterShrinkAndGrow() {
|
|
|
|
|
const maybe_page_size = 4096;
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const rab = CreateResizableArrayBuffer(maybe_page_size, 2 * maybe_page_size);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
const i8a = new Int8Array(rab);
|
|
|
|
|
for (let i = 0; i < maybe_page_size; ++i) {
|
|
|
|
|
i8a[i] = 1;
|
|
|
|
|
}
|
|
|
|
|
rab.resize(maybe_page_size / 2);
|
|
|
|
|
rab.resize(maybe_page_size);
|
|
|
|
|
for (let i = maybe_page_size / 2; i < maybe_page_size; ++i) {
|
|
|
|
|
assertEquals(0, i8a[i]);
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABBasics() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertFalse(gsab instanceof ArrayBuffer);
|
2021-07-20 07:20:42 +00:00
|
|
|
|
assertTrue(gsab instanceof SharedArrayBuffer);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
assertEquals(20, gsab.maxByteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABCtorByteLengthEqualsMax() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 10);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
assertEquals(10, gsab.maxByteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABCtorByteLengthZero() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(0, 10);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(0, gsab.byteLength);
|
|
|
|
|
assertEquals(10, gsab.maxByteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABCtorByteLengthAndMaxZero() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(0, 0);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(0, gsab.byteLength);
|
|
|
|
|
assertEquals(0, gsab.maxByteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestAllocatingOutrageouslyMuchThrows() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
assertThrows(() => { CreateGrowableSharedArrayBuffer(0, 2 ** 100);},
|
2021-05-06 10:43:37 +00:00
|
|
|
|
RangeError);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABGrowToMax() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
growHelper(gsab, 20);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABGrowToSameSize() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
growHelper(gsab, 10);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABGrowToSmallerThrows() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
assertThrows(() => {gsab.grow(5)});
|
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABGrowToZeroThrows() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
assertThrows(() => {gsab.grow(0)});
|
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABGrowBeyondMaxThrows() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
assertThrows(() => {gsab.grow(21)});
|
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABGrowMultipleTimes() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
const sizes = [15, 7, 7, 0, 8, 20, 20, 10];
|
|
|
|
|
for (let s of sizes) {
|
|
|
|
|
const current_size = gsab.byteLength;
|
|
|
|
|
if (s < gsab.byteLength) {
|
|
|
|
|
assertThrows(() => {gsab.grow(s)});
|
|
|
|
|
assertEquals(current_size, gsab.byteLength);
|
|
|
|
|
} else {
|
|
|
|
|
growHelper(gsab, s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABGrowParameters() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
gsab.grow('15');
|
|
|
|
|
assertEquals(15, gsab.byteLength);
|
|
|
|
|
gsab.grow({valueOf: function() { return 16; }});
|
|
|
|
|
assertEquals(16, gsab.byteLength);
|
|
|
|
|
gsab.grow(17.9);
|
|
|
|
|
assertEquals(17, gsab.byteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABGrowInvalidParameters() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(0, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertThrows(() => { gsab.grow(-1) }, RangeError);
|
|
|
|
|
assertThrows(() => { gsab.grow({valueOf: function() {
|
|
|
|
|
throw new Error('length param'); }})});
|
|
|
|
|
assertEquals(0, gsab.byteLength);
|
|
|
|
|
|
|
|
|
|
// Various non-numbers are converted to NaN which is treated as 0.
|
|
|
|
|
gsab.grow('string');
|
|
|
|
|
assertEquals(0, gsab.byteLength);
|
|
|
|
|
gsab.grow();
|
|
|
|
|
assertEquals(0, gsab.byteLength);
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function TestGSABMemoryInitializedToZeroAfterGrow() {
|
|
|
|
|
const maybe_page_size = 4096;
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(maybe_page_size,
|
2021-05-06 10:43:37 +00:00
|
|
|
|
2 * maybe_page_size);
|
|
|
|
|
const i8a = new Int8Array(gsab);
|
|
|
|
|
gsab.grow(2 * maybe_page_size);
|
|
|
|
|
assertEquals(2 * maybe_page_size, i8a.length);
|
|
|
|
|
for (let i = 0; i < 2 * maybe_page_size; ++i) {
|
|
|
|
|
assertEquals(0, i8a[i]);
|
|
|
|
|
}
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
(function GrowGSABOnADifferentThread() {
|
2021-07-20 07:20:42 +00:00
|
|
|
|
const gsab = CreateGrowableSharedArrayBuffer(10, 20);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assertEquals(10, gsab.byteLength);
|
|
|
|
|
function workerCode() {
|
|
|
|
|
function assert(thing) {
|
|
|
|
|
if (!thing) {
|
|
|
|
|
postMessage('error');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
onmessage = function(params) {
|
|
|
|
|
const gsab = params.gsab;
|
|
|
|
|
assert(!(gsab instanceof ArrayBuffer));
|
2021-07-20 07:20:42 +00:00
|
|
|
|
assert(gsab instanceof SharedArrayBuffer);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
assert(10 == gsab.byteLength);
|
2021-07-23 08:51:56 +00:00
|
|
|
|
assert(20 == gsab.maxByteLength);
|
2021-05-06 10:43:37 +00:00
|
|
|
|
gsab.grow(15);
|
|
|
|
|
postMessage('ok');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const w = new Worker(workerCode, {type: 'function'});
|
|
|
|
|
w.postMessage({gsab: gsab});
|
|
|
|
|
assertEquals('ok', w.getMessage());
|
|
|
|
|
assertEquals(15, gsab.byteLength);
|
|
|
|
|
})();
|