diff options
Diffstat (limited to 'js/src/jit-test/tests/typedarray/arraybuffer-transfer.js')
-rw-r--r-- | js/src/jit-test/tests/typedarray/arraybuffer-transfer.js | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/typedarray/arraybuffer-transfer.js b/js/src/jit-test/tests/typedarray/arraybuffer-transfer.js new file mode 100644 index 0000000000..12bbe5bed7 --- /dev/null +++ b/js/src/jit-test/tests/typedarray/arraybuffer-transfer.js @@ -0,0 +1,207 @@ +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); + } + } +} |