Created
September 25, 2025 21:16
-
-
Save spalt08/98554a15a3cdf13ca5695c03b35bcd3f to your computer and use it in GitHub Desktop.
Reproduction of inconsistent DecompressionStream behaviour
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Console-friendly version of the script | |
| // Just paste it into the dev-tools console in Chrome/Safari/Firefox | |
| (async function test() { | |
| const plainText = "test-payload"; | |
| const plainTextBytes = new TextEncoder().encode(plainText); | |
| // Compress | |
| const compressionStream = new CompressionStream("deflate"); | |
| const compressionWriter = compressionStream.writable.getWriter(); | |
| compressionWriter.write(plainTextBytes); | |
| compressionWriter.close(); | |
| const originalCompressedBytes = await readStream(compressionStream.readable); | |
| // Add arbitrary padding to the compressed bytes | |
| const paddedCompressedBytes = padBuffer(originalCompressedBytes, 1); | |
| // Decompress | |
| const decompressionStream = new DecompressionStream("deflate"); | |
| const decompressionWriter = decompressionStream.writable.getWriter(); | |
| decompressionWriter.write(paddedCompressedBytes); | |
| decompressionWriter.close(); | |
| // In Chrome decompressedBytes are still available and fine, whereas in Safari and Firefox - not available. | |
| // Also, the output depends on input chunking which is not guaranteed. | |
| const decompressedBytes = await readStream(decompressionStream.readable); | |
| const decompressedText = new TextDecoder().decode(decompressedBytes); | |
| console.log("Decompressed text:", decompressedText); | |
| return decompressedText; | |
| })(); | |
| async function readStream(readableStream) { | |
| const chunks = []; | |
| await readableStream | |
| .pipeTo( | |
| new WritableStream({ | |
| write(chunk) { | |
| chunks.push(chunk); | |
| }, | |
| abort(reason) { | |
| console.log("abort", reason); | |
| }, | |
| }) | |
| ) | |
| .catch((error) => { | |
| console.log("error", error); | |
| }); | |
| return new Blob(chunks) | |
| .arrayBuffer() | |
| .then((buffer) => new Uint8Array(buffer)); | |
| } | |
| function padBuffer(buffer, paddingLength) { | |
| const paddedBuffer = new Uint8Array(buffer.length + paddingLength); | |
| paddedBuffer.set(buffer, 0); | |
| for (let i = 0; i < paddingLength; i++) { | |
| paddedBuffer[buffer.length + i] = Math.random() * 0xff; | |
| } | |
| return paddedBuffer; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment