Source code

Revision control

Copy as Markdown

Other Tools

structuredCloneBatteryOfTests.push({
description: 'ArrayBuffer',
async f(runner) {
const buffer = new Uint8Array([1]).buffer;
const copy = await runner.structuredClone(buffer, [buffer]);
assert_equals(buffer.byteLength, 0);
assert_equals(copy.byteLength, 1);
}
});
structuredCloneBatteryOfTests.push({
description: 'MessagePort',
async f(runner) {
const {port1, port2} = new MessageChannel();
const copy = await runner.structuredClone(port2, [port2]);
const msg = new Promise(resolve => port1.onmessage = resolve);
copy.postMessage('ohai');
assert_equals((await msg).data, 'ohai');
}
});
// TODO: ImageBitmap
structuredCloneBatteryOfTests.push({
description: 'A detached ArrayBuffer cannot be transferred',
async f(runner, t) {
const buffer = new ArrayBuffer();
await runner.structuredClone(buffer, [buffer]);
await promise_rejects_dom(
t,
"DataCloneError",
runner.structuredClone(buffer, [buffer])
);
}
});
structuredCloneBatteryOfTests.push({
description: 'A detached platform object cannot be transferred',
async f(runner, t) {
const {port1} = new MessageChannel();
await runner.structuredClone(port1, [port1]);
await promise_rejects_dom(
t,
"DataCloneError",
runner.structuredClone(port1, [port1])
);
}
});
structuredCloneBatteryOfTests.push({
description: 'Transferring a non-transferable platform object fails',
async f(runner, t) {
const blob = new Blob();
await promise_rejects_dom(
t,
"DataCloneError",
runner.structuredClone(blob, [blob])
);
}
});
structuredCloneBatteryOfTests.push({
description: 'An object whose interface is deleted from the global object must still be received',
async f(runner) {
const {port1} = new MessageChannel();
const messagePortInterface = globalThis.MessagePort;
delete globalThis.MessagePort;
try {
const transfer = await runner.structuredClone(port1, [port1]);
assert_true(transfer instanceof messagePortInterface);
} finally {
globalThis.MessagePort = messagePortInterface;
}
}
});
structuredCloneBatteryOfTests.push({
description: 'A subclass instance will be received as its closest transferable superclass',
async f(runner) {
// MessagePort doesn't have a constructor, so we must use something else.
// Make sure that ReadableStream is transferable before we test its subclasses.
try {
const stream = new ReadableStream();
await runner.structuredClone(stream, [stream]);
} catch(err) {
if (err instanceof DOMException && err.code === DOMException.DATA_CLONE_ERR) {
throw new OptionalFeatureUnsupportedError("ReadableStream isn't transferable");
} else {
throw err;
}
}
class ReadableStreamSubclass extends ReadableStream {}
const original = new ReadableStreamSubclass();
const transfer = await runner.structuredClone(original, [original]);
assert_equals(Object.getPrototypeOf(transfer), ReadableStream.prototype);
}
});
structuredCloneBatteryOfTests.push({
description: 'Resizable ArrayBuffer is transferable',
async f(runner) {
const buffer = new ArrayBuffer(16, { maxByteLength: 1024 });
const copy = await runner.structuredClone(buffer, [buffer]);
assert_equals(buffer.byteLength, 0);
assert_equals(copy.byteLength, 16);
assert_equals(copy.maxByteLength, 1024);
assert_true(copy.resizable);
}
});
structuredCloneBatteryOfTests.push({
description: 'Length-tracking TypedArray is transferable',
async f(runner) {
const ab = new ArrayBuffer(16, { maxByteLength: 1024 });
const ta = new Uint8Array(ab);
const copy = await runner.structuredClone(ta, [ab]);
assert_equals(ab.byteLength, 0);
assert_equals(copy.buffer.byteLength, 16);
assert_equals(copy.buffer.maxByteLength, 1024);
assert_true(copy.buffer.resizable);
copy.buffer.resize(32);
assert_equals(copy.byteLength, 32);
}
});
structuredCloneBatteryOfTests.push({
description: 'Length-tracking DataView is transferable',
async f(runner) {
const ab = new ArrayBuffer(16, { maxByteLength: 1024 });
const dv = new DataView(ab);
const copy = await runner.structuredClone(dv, [ab]);
assert_equals(ab.byteLength, 0);
assert_equals(copy.buffer.byteLength, 16);
assert_equals(copy.buffer.maxByteLength, 1024);
assert_true(copy.buffer.resizable);
copy.buffer.resize(32);
assert_equals(copy.byteLength, 32);
}
});
structuredCloneBatteryOfTests.push({
description: 'Transferring OOB TypedArray throws',
async f(runner, t) {
const ab = new ArrayBuffer(16, { maxByteLength: 1024 });
const ta = new Uint8Array(ab, 8);
ab.resize(0);
await promise_rejects_dom(
t,
"DataCloneError",
runner.structuredClone(ta, [ab])
);
}
});
structuredCloneBatteryOfTests.push({
description: 'Transferring OOB DataView throws',
async f(runner, t) {
const ab = new ArrayBuffer(16, { maxByteLength: 1024 });
const dv = new DataView(ab, 8);
ab.resize(0);
await promise_rejects_dom(
t,
"DataCloneError",
runner.structuredClone(dv, [ab])
);
}
});