| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <title>Blob data isolation from input ArrayBuffers</title> | |
| <link rel="help" href="https://w3c.github.io/FileAPI/#constructorBlob"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script> | |
| "use strict"; | |
| // These tests verify that Blob correctly copies its input data, so that | |
| // subsequent modifications to the input do not affect the Blob's contents. | |
| // This is especially important to test with small buffers that might trigger | |
| // buffer pool optimizations in some implementations. | |
| function readBlobAsArrayBuffer(blob) { | |
| return new Promise((resolve, reject) => { | |
| const reader = new FileReader(); | |
| reader.onload = () => resolve(reader.result); | |
| reader.onerror = () => reject(reader.error); | |
| reader.readAsArrayBuffer(blob); | |
| }); | |
| } | |
| promise_test(async () => { | |
| const input = new Uint8Array([1, 2, 3, 4]); | |
| const blob = new Blob([input]); | |
| input[0] = 99; | |
| const result = new Uint8Array(await readBlobAsArrayBuffer(blob)); | |
| assert_array_equals(result, [1, 2, 3, 4], "Blob data should not be affected by modifying the input Uint8Array"); | |
| }, "Modifying a Uint8Array after Blob construction does not affect the Blob"); | |
| promise_test(async () => { | |
| const input = new Uint8Array([5, 6, 7, 8]); | |
| const inputBuffer = input.buffer; | |
| const blob = new Blob([inputBuffer]); | |
| input[0] = 99; | |
| const result = new Uint8Array(await readBlobAsArrayBuffer(blob)); | |
| assert_array_equals(result, [5, 6, 7, 8], "Blob data should not be affected by modifying the underlying ArrayBuffer"); | |
| }, "Modifying an ArrayBuffer after Blob construction does not affect the Blob"); | |
| promise_test(async () => { | |
| // Test with a view into a larger buffer (common pattern that exercises offset handling) | |
| const largerBuffer = new ArrayBuffer(16); | |
| const view = new Uint8Array(largerBuffer, 4, 4); | |
| view.set([10, 11, 12, 13]); | |
| const blob = new Blob([view]); | |
| view[0] = 99; | |
| const result = new Uint8Array(await readBlobAsArrayBuffer(blob)); | |
| assert_array_equals(result, [10, 11, 12, 13], "Blob data should not be affected by modifying a typed array view"); | |
| }, "Modifying a typed array view after Blob construction does not affect the Blob"); | |
| promise_test(async () => { | |
| // Very small buffer - most likely to hit buffer pool optimizations | |
| const input = new Uint8Array([42]); | |
| const blob = new Blob([input]); | |
| input[0] = 0; | |
| const result = new Uint8Array(await readBlobAsArrayBuffer(blob)); | |
| assert_array_equals(result, [42], "Blob data should not be affected even with single-byte input"); | |
| }, "Modifying a single-byte Uint8Array after Blob construction does not affect the Blob"); | |
| promise_test(async () => { | |
| const blob = new Blob([new Uint8Array([1, 2, 3, 4])]); | |
| const result1 = await readBlobAsArrayBuffer(blob); | |
| new Uint8Array(result1)[0] = 99; | |
| const result2 = new Uint8Array(await readBlobAsArrayBuffer(blob)); | |
| assert_array_equals( | |
| result2, | |
| [1, 2, 3, 4], | |
| "Blob data should not be affected by modifying a previously-read ArrayBuffer" | |
| ); | |
| }, "Modifying a returned ArrayBuffer does not affect subsequent reads"); | |
| </script> |