Source code

Revision control

Copy as Markdown

Other Tools

const byteLengths = [
// Byte lengths applicable for inline storage
0, 1, 4, 16, 32, 64, 96,
// Too large for inline storage
128, 1024, 4096, 65536,
];
// Most values in |byteLengths| are powers-of-two. Add +1/-1 to test for
// off-by-one errors.
function offByOne(v) {
if (v === 0) {
return [v, v + 1];
}
return [v - 1, v, v + 1];
}
// Fast alternative to |assertEq| to avoid a slow VM-call.
// Should only be used when looping over the TypedArray contents to avoid
// unnecessary test slowdowns.
function assertEqNum(e, a) {
if (e !== a) {
assertEq(e, a);
}
}
// Inline or malloced ArrayBuffer.
{
for (let byteLength of byteLengths.flatMap(offByOne)) {
for (let newByteLength of offByOne(byteLength)) {
for (let transfer of [
ArrayBuffer.prototype.transfer,
ArrayBuffer.prototype.transferToFixedLength,
]) {
let buffer = new ArrayBuffer(byteLength);
let i8 = new Uint8Array(buffer);
for (let i = 0; i < byteLength; ++i) {
assertEqNum(i8[i], 0);
i8[i] = i;
}
assertEq(buffer.byteLength, byteLength);
assertEq(buffer.detached, false);
let copy = transfer.call(buffer, newByteLength);
assertEq(buffer.byteLength, 0);
assertEq(buffer.detached, true);
assertEq(copy.byteLength, newByteLength);
assertEq(copy.detached, false);
i8 = new Uint8Array(copy);
for (let i = 0; i < Math.min(byteLength, newByteLength); ++i) {
assertEqNum(i8[i], i & 0xff);
}
for (let i = byteLength; i < newByteLength; ++i) {
assertEqNum(i8[i], 0);
}
}
}
}
}
// External buffer.
{
for (let byteLength of byteLengths.flatMap(offByOne)) {
for (let newByteLength of offByOne(byteLength)) {
for (let transfer of [
ArrayBuffer.prototype.transfer,
ArrayBuffer.prototype.transferToFixedLength,
]) {
let buffer = createExternalArrayBuffer(byteLength);
let i8 = new Uint8Array(buffer);
for (let i = 0; i < byteLength; ++i) {
assertEqNum(i8[i], 0);
i8[i] = i;
}
assertEq(buffer.byteLength, byteLength);
assertEq(buffer.detached, false);
let copy = transfer.call(buffer, newByteLength);
assertEq(buffer.byteLength, 0);
assertEq(buffer.detached, true);
assertEq(copy.byteLength, newByteLength);
assertEq(copy.detached, false);
i8 = new Uint8Array(copy);
for (let i = 0; i < Math.min(byteLength, newByteLength); ++i) {
assertEqNum(i8[i], i & 0xff);
}
for (let i = byteLength; i < newByteLength; ++i) {
assertEqNum(i8[i], 0);
}
}
}
}
}
// User-controlled buffer.
{
for (let byteLength of byteLengths.flatMap(offByOne)) {
for (let newByteLength of offByOne(byteLength)) {
for (let transfer of [
ArrayBuffer.prototype.transfer,
ArrayBuffer.prototype.transferToFixedLength,
]) {
let buffer = createUserArrayBuffer(byteLength);
let i8 = new Uint8Array(buffer);
for (let i = 0; i < byteLength; ++i) {
assertEqNum(i8[i], 0);
i8[i] = i;
}
assertEq(buffer.byteLength, byteLength);
assertEq(buffer.detached, false);
let copy = transfer.call(buffer, newByteLength);
assertEq(buffer.byteLength, 0);
assertEq(buffer.detached, true);
assertEq(copy.byteLength, newByteLength);
assertEq(copy.detached, false);
i8 = new Uint8Array(copy);
for (let i = 0; i < Math.min(byteLength, newByteLength); ++i) {
assertEqNum(i8[i], i & 0xff);
}
for (let i = byteLength; i < newByteLength; ++i) {
assertEqNum(i8[i], 0);
}
}
}
}
}
// Mapped file buffer.
if (getBuildConfiguration("mapped-array-buffer")) {
let fileName = "arraybuffer-transfer-mapped.txt";
let fileContent = os.file.readRelativeToScript(fileName, "binary");
let byteLength = fileContent.byteLength;
assertEq(byteLength > 0, true);
for (let newByteLength of offByOne(byteLength)) {
for (let transfer of [
ArrayBuffer.prototype.transfer,
ArrayBuffer.prototype.transferToFixedLength,
]) {
let buffer = createMappedArrayBuffer(fileName);
assertEq(buffer.byteLength, byteLength);
assertEq(buffer.detached, false);
let copy = transfer.call(buffer, newByteLength);
assertEq(buffer.byteLength, 0);
assertEq(buffer.detached, true);
assertEq(copy.byteLength, newByteLength);
assertEq(copy.detached, false);
i8 = new Uint8Array(copy);
for (let i = 0; i < Math.min(byteLength, newByteLength); ++i) {
assertEqNum(i8[i], fileContent[i]);
}
for (let i = byteLength; i < newByteLength; ++i) {
assertEqNum(i8[i], 0);
}
}
}
}
// Cross-compartment
{
let g = newGlobal({ newCompartment: true });
let byteLengthGetter = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "byteLength").get;
let detachedGetter = Object.getOwnPropertyDescriptor(ArrayBuffer.prototype, "detached").get;
for (let byteLength of byteLengths) {
for (let transfer of [
ArrayBuffer.prototype.transfer,
ArrayBuffer.prototype.transferToFixedLength,
]) {
let buffer = new g.ArrayBuffer(byteLength);
assertEq(byteLengthGetter.call(buffer), byteLength);
assertEq(detachedGetter.call(buffer), false);
let copy = transfer.call(buffer);
assertEq(detachedGetter.call(buffer), true);
assertEq(byteLengthGetter.call(buffer), 0);
assertEq(detachedGetter.call(copy), false);
assertEq(byteLengthGetter.call(copy), byteLength);
// NOTE: Incorrect realm due to CallNonGenericMethod.
assertEq(copy instanceof g.ArrayBuffer, true);
}
}
}