1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
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])
);
}
});
|