compression-with-detach.window.js (1897B)
1 // META: global=window,worker,shadowrealm 2 // META: script=resources/concatenate-stream.js 3 4 'use strict'; 5 6 const kInputLength = 500000; 7 8 function createLargeRandomInput() { 9 const buffer = new ArrayBuffer(kInputLength); 10 // The getRandomValues API will only let us get 65536 bytes at a time, so call 11 // it multiple times. 12 const kChunkSize = 65536; 13 for (let offset = 0; offset < kInputLength; offset += kChunkSize) { 14 const length = 15 offset + kChunkSize > kInputLength ? kInputLength - offset : kChunkSize; 16 const view = new Uint8Array(buffer, offset, length); 17 crypto.getRandomValues(view); 18 } 19 return new Uint8Array(buffer); 20 } 21 22 function decompress(view) { 23 const ds = new DecompressionStream('deflate'); 24 const writer = ds.writable.getWriter(); 25 writer.write(view); 26 writer.close(); 27 return concatenateStream(ds.readable); 28 } 29 30 promise_test(async () => { 31 const input = createLargeRandomInput(); 32 const inputCopy = input.slice(0, input.byteLength); 33 const cs = new CompressionStream('deflate'); 34 const writer = cs.writable.getWriter(); 35 writer.write(input); 36 writer.close(); 37 // Object.prototype.then will be looked up synchronously when the promise 38 // returned by read() is resolved. 39 Object.defineProperty(Object.prototype, 'then', { 40 get() { 41 // Cause input to become detached and unreferenced. 42 try { 43 postMessage(undefined, 'nowhere', [input.buffer]); 44 } catch (e) { 45 // It's already detached. 46 } 47 } 48 }); 49 const output = await concatenateStream(cs.readable); 50 // Perform the comparison as strings since this is reasonably fast even when 51 // JITted JavaScript is running under an emulator. 52 assert_equals( 53 inputCopy.toString(), (await decompress(output)).toString(), 54 'decompressing the output should return the input'); 55 }, 'data should be correctly compressed even if input is detached partway');