diff --git a/lib/internal/blob.js b/lib/internal/blob.js index 3f17443cb726d5..0e13184741a646 100644 --- a/lib/internal/blob.js +++ b/lib/internal/blob.js @@ -6,6 +6,7 @@ const { MathMin, ObjectDefineProperties, ObjectDefineProperty, + PromisePrototypeThen, PromiseReject, ReflectConstruct, RegExpPrototypeExec, @@ -312,6 +313,15 @@ class Blob { return dec.decode(await this.arrayBuffer()); } + bytes() { + if (!isBlob(this)) + throw new ERR_INVALID_THIS('Blob'); + + return PromisePrototypeThen( + this.arrayBuffer(), + (buffer) => new Uint8Array(buffer)); + } + /** * @returns {ReadableStream} */ diff --git a/test/fixtures/wpt/FileAPI/Blob-methods-from-detached-frame.html b/test/fixtures/wpt/FileAPI/Blob-methods-from-detached-frame.html index 37efd5ed2016b7..78f08e8270e2f6 100644 --- a/test/fixtures/wpt/FileAPI/Blob-methods-from-detached-frame.html +++ b/test/fixtures/wpt/FileAPI/Blob-methods-from-detached-frame.html @@ -27,6 +27,7 @@ assert_equals(await slicedBlob.text(), "oo"); assert_equals(charCodeBufferToString(await slicedBlob.arrayBuffer()), "oo"); + assert_equals(charCodeArrayToString(await slicedBlob.bytes()), "oo"); const reader = slicedBlob.stream().getReader(); const { value } = await reader.read(); @@ -48,6 +49,14 @@ assert_equals(charCodeBufferToString(charCodeBuffer), "bar"); }, "arrayBuffer()"); +promise_test(async () => { + const { bytes } = await BlobPrototypeFromDetachedFramePromise; + const blob = new Blob(["bar"]); + + const charCodeBytes = await bytes.call(blob); + assert_equals(charCodeArrayToString(charCodeBytes), "bar"); +}, "bytes()"); + promise_test(async () => { const { stream } = await BlobPrototypeFromDetachedFramePromise; const blob = new Blob(["baz"]); diff --git a/test/fixtures/wpt/FileAPI/META.yml b/test/fixtures/wpt/FileAPI/META.yml index 506a59fec1eb33..66227c8224bc46 100644 --- a/test/fixtures/wpt/FileAPI/META.yml +++ b/test/fixtures/wpt/FileAPI/META.yml @@ -1,6 +1,6 @@ spec: https://w3c.github.io/FileAPI/ suggested_reviewers: - inexorabletash - - zqzhang - jdm - mkruisselbrink + - annevk diff --git a/test/fixtures/wpt/FileAPI/blob/Blob-bytes.any.js b/test/fixtures/wpt/FileAPI/blob/Blob-bytes.any.js new file mode 100644 index 00000000000000..5173b3715c8054 --- /dev/null +++ b/test/fixtures/wpt/FileAPI/blob/Blob-bytes.any.js @@ -0,0 +1,45 @@ +// META: title=Blob bytes() +// META: script=../support/Blob.js +'use strict'; + +promise_test(async () => { + const input_arr = new TextEncoder().encode("PASS"); + const blob = new Blob([input_arr]); + const uint8array = await blob.bytes(); + assert_true(uint8array instanceof Uint8Array); + assert_equals_typed_array(uint8array, input_arr); +}, "Blob.bytes()") + +promise_test(async () => { + const input_arr = new TextEncoder().encode(""); + const blob = new Blob([input_arr]); + const uint8array = await blob.bytes(); + assert_true(uint8array instanceof Uint8Array); + assert_equals_typed_array(uint8array, input_arr); +}, "Blob.bytes() empty Blob data") + +promise_test(async () => { + const input_arr = new TextEncoder().encode("\u08B8\u000a"); + const blob = new Blob([input_arr]); + const uint8array = await blob.bytes(); + assert_equals_typed_array(uint8array, input_arr); +}, "Blob.bytes() non-ascii input") + +promise_test(async () => { + const input_arr = [8, 241, 48, 123, 151]; + const typed_arr = new Uint8Array(input_arr); + const blob = new Blob([typed_arr]); + const uint8array = await blob.bytes(); + assert_equals_typed_array(uint8array, typed_arr); +}, "Blob.bytes() non-unicode input") + +promise_test(async () => { + const input_arr = new TextEncoder().encode("PASS"); + const blob = new Blob([input_arr]); + const uint8array_results = await Promise.all([blob.bytes(), + blob.bytes(), blob.bytes()]); + for (let uint8array of uint8array_results) { + assert_true(uint8array instanceof Uint8Array); + assert_equals_typed_array(uint8array, input_arr); + } +}, "Blob.bytes() concurrent reads") diff --git a/test/fixtures/wpt/FileAPI/blob/Blob-constructor.any.js b/test/fixtures/wpt/FileAPI/blob/Blob-constructor.any.js index d16f760caeeb2d..6dc44e8e156cce 100644 --- a/test/fixtures/wpt/FileAPI/blob/Blob-constructor.any.js +++ b/test/fixtures/wpt/FileAPI/blob/Blob-constructor.any.js @@ -290,10 +290,11 @@ test_blob(function() { new Int16Array([0x4150, 0x5353]), new Uint32Array([0x53534150]), new Int32Array([0x53534150]), + new Float16Array([2.65625, 58.59375]), new Float32Array([0xD341500000]) ]); }, { - expected: "PASSPASSPASSPASSPASSPASSPASS", + expected: "PASSPASSPASSPASSPASSPASSPASSPASS", type: "", desc: "Passing typed arrays as elements of the blobParts array should work." }); diff --git a/test/fixtures/wpt/FileAPI/blob/Blob-stream.any.js b/test/fixtures/wpt/FileAPI/blob/Blob-stream.any.js index 87710a171a9752..453144cac964a6 100644 --- a/test/fixtures/wpt/FileAPI/blob/Blob-stream.any.js +++ b/test/fixtures/wpt/FileAPI/blob/Blob-stream.any.js @@ -70,7 +70,18 @@ promise_test(async() => { await garbageCollect(); const chunks = await read_all_chunks(stream, { perform_gc: true }); assert_array_equals(chunks, input_arr); -}, "Blob.stream() garbage collection of blob shouldn't break stream" + +}, "Blob.stream() garbage collection of blob shouldn't break stream " + + "consumption") + +promise_test(async() => { + const input_arr = [8, 241, 48, 123, 151]; + const typed_arr = new Uint8Array(input_arr); + let blob = new Blob([typed_arr]); + const chunksPromise = read_all_chunks(blob.stream()); + // It somehow matters to do GC here instead of doing `perform_gc: true` + await garbageCollect(); + assert_array_equals(await chunksPromise, input_arr); +}, "Blob.stream() garbage collection of stream shouldn't break stream " + "consumption") promise_test(async () => { diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index 2d610caa8e412a..6ba53763685b6a 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -16,7 +16,7 @@ Last update: - dom/events: https://github.com/web-platform-tests/wpt/tree/ab8999891c/dom/events - encoding: https://github.com/web-platform-tests/wpt/tree/a58bbf6d8c/encoding - fetch/data-urls/resources: https://github.com/web-platform-tests/wpt/tree/7c79d998ff/fetch/data-urls/resources -- FileAPI: https://github.com/web-platform-tests/wpt/tree/e36dbb6f00/FileAPI +- FileAPI: https://github.com/web-platform-tests/wpt/tree/cceaf3628d/FileAPI - hr-time: https://github.com/web-platform-tests/wpt/tree/34cafd797e/hr-time - html/webappapis/atob: https://github.com/web-platform-tests/wpt/tree/f267e1dca6/html/webappapis/atob - html/webappapis/microtask-queuing: https://github.com/web-platform-tests/wpt/tree/2c5c3c4c27/html/webappapis/microtask-queuing diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index ff764aae93b42f..c6d9f547995192 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -24,7 +24,7 @@ "path": "fetch/data-urls/resources" }, "FileAPI": { - "commit": "e36dbb6f00fb59f9fc792f509194432e9e6d0b6d", + "commit": "cceaf3628da950621004d9b5d8c1d1f367073347", "path": "FileAPI" }, "hr-time": {