structured-clone-battery-of-tests-with-transferables.js (5224B)
1 structuredCloneBatteryOfTests.push({ 2 description: 'ArrayBuffer', 3 async f(runner) { 4 const buffer = new Uint8Array([1]).buffer; 5 const copy = await runner.structuredClone(buffer, [buffer]); 6 assert_equals(buffer.byteLength, 0); 7 assert_equals(copy.byteLength, 1); 8 } 9 }); 10 11 structuredCloneBatteryOfTests.push({ 12 description: 'MessagePort', 13 async f(runner) { 14 const {port1, port2} = new MessageChannel(); 15 const copy = await runner.structuredClone(port2, [port2]); 16 const msg = new Promise(resolve => port1.onmessage = resolve); 17 copy.postMessage('ohai'); 18 assert_equals((await msg).data, 'ohai'); 19 } 20 }); 21 22 // TODO: ImageBitmap 23 24 structuredCloneBatteryOfTests.push({ 25 description: 'A detached ArrayBuffer cannot be transferred', 26 async f(runner, t) { 27 const buffer = new ArrayBuffer(); 28 await runner.structuredClone(buffer, [buffer]); 29 await promise_rejects_dom( 30 t, 31 "DataCloneError", 32 runner.structuredClone(buffer, [buffer]) 33 ); 34 } 35 }); 36 37 structuredCloneBatteryOfTests.push({ 38 description: 'A detached platform object cannot be transferred', 39 async f(runner, t) { 40 const {port1} = new MessageChannel(); 41 await runner.structuredClone(port1, [port1]); 42 await promise_rejects_dom( 43 t, 44 "DataCloneError", 45 runner.structuredClone(port1, [port1]) 46 ); 47 } 48 }); 49 50 structuredCloneBatteryOfTests.push({ 51 description: 'Transferring a non-transferable platform object fails', 52 async f(runner, t) { 53 const blob = new Blob(); 54 await promise_rejects_dom( 55 t, 56 "DataCloneError", 57 runner.structuredClone(blob, [blob]) 58 ); 59 } 60 }); 61 62 structuredCloneBatteryOfTests.push({ 63 description: 'An object whose interface is deleted from the global object must still be received', 64 async f(runner) { 65 const {port1} = new MessageChannel(); 66 const messagePortInterface = globalThis.MessagePort; 67 delete globalThis.MessagePort; 68 try { 69 const transfer = await runner.structuredClone(port1, [port1]); 70 assert_true(transfer instanceof messagePortInterface); 71 } finally { 72 globalThis.MessagePort = messagePortInterface; 73 } 74 } 75 }); 76 77 structuredCloneBatteryOfTests.push({ 78 description: 'A subclass instance will be received as its closest transferable superclass', 79 async f(runner) { 80 // MessagePort doesn't have a constructor, so we must use something else. 81 82 // Make sure that ReadableStream is transferable before we test its subclasses. 83 try { 84 const stream = new ReadableStream(); 85 await runner.structuredClone(stream, [stream]); 86 } catch(err) { 87 if (err instanceof DOMException && err.code === DOMException.DATA_CLONE_ERR) { 88 throw new OptionalFeatureUnsupportedError("ReadableStream isn't transferable"); 89 } else { 90 throw err; 91 } 92 } 93 94 class ReadableStreamSubclass extends ReadableStream {} 95 const original = new ReadableStreamSubclass(); 96 const transfer = await runner.structuredClone(original, [original]); 97 assert_equals(Object.getPrototypeOf(transfer), ReadableStream.prototype); 98 } 99 }); 100 101 structuredCloneBatteryOfTests.push({ 102 description: 'Resizable ArrayBuffer is transferable', 103 async f(runner) { 104 const buffer = new ArrayBuffer(16, { maxByteLength: 1024 }); 105 const copy = await runner.structuredClone(buffer, [buffer]); 106 assert_equals(buffer.byteLength, 0); 107 assert_equals(copy.byteLength, 16); 108 assert_equals(copy.maxByteLength, 1024); 109 assert_true(copy.resizable); 110 } 111 }); 112 113 structuredCloneBatteryOfTests.push({ 114 description: 'Length-tracking TypedArray is transferable', 115 async f(runner) { 116 const ab = new ArrayBuffer(16, { maxByteLength: 1024 }); 117 const ta = new Uint8Array(ab); 118 const copy = await runner.structuredClone(ta, [ab]); 119 assert_equals(ab.byteLength, 0); 120 assert_equals(copy.buffer.byteLength, 16); 121 assert_equals(copy.buffer.maxByteLength, 1024); 122 assert_true(copy.buffer.resizable); 123 copy.buffer.resize(32); 124 assert_equals(copy.byteLength, 32); 125 } 126 }); 127 128 structuredCloneBatteryOfTests.push({ 129 description: 'Length-tracking DataView is transferable', 130 async f(runner) { 131 const ab = new ArrayBuffer(16, { maxByteLength: 1024 }); 132 const dv = new DataView(ab); 133 const copy = await runner.structuredClone(dv, [ab]); 134 assert_equals(ab.byteLength, 0); 135 assert_equals(copy.buffer.byteLength, 16); 136 assert_equals(copy.buffer.maxByteLength, 1024); 137 assert_true(copy.buffer.resizable); 138 copy.buffer.resize(32); 139 assert_equals(copy.byteLength, 32); 140 } 141 }); 142 143 structuredCloneBatteryOfTests.push({ 144 description: 'Transferring OOB TypedArray throws', 145 async f(runner, t) { 146 const ab = new ArrayBuffer(16, { maxByteLength: 1024 }); 147 const ta = new Uint8Array(ab, 8); 148 ab.resize(0); 149 await promise_rejects_dom( 150 t, 151 "DataCloneError", 152 runner.structuredClone(ta, [ab]) 153 ); 154 } 155 }); 156 157 structuredCloneBatteryOfTests.push({ 158 description: 'Transferring OOB DataView throws', 159 async f(runner, t) { 160 const ab = new ArrayBuffer(16, { maxByteLength: 1024 }); 161 const dv = new DataView(ab, 8); 162 ab.resize(0); 163 await promise_rejects_dom( 164 t, 165 "DataCloneError", 166 runner.structuredClone(dv, [ab]) 167 ); 168 } 169 });