diff options
author | Kousuke Takaki <98276492+yoseio@users.noreply.github.com> | 2025-05-19 20:55:06 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-19 11:55:06 +0000 |
commit | ec448b14230668f9e38f0d727661b6d94e184168 (patch) | |
tree | 4ad5ec5d298847589ba7f698a7ca041965c31af1 | |
parent | 6e97fc0bc47b6c3c5af9b1750f01f268b6b200f5 (diff) | |
download | servo-ec448b14230668f9e38f0d727661b6d94e184168.tar.gz servo-ec448b14230668f9e38f0d727661b6d94e184168.zip |
script: Make `Blob.ArrayBuffer()` more specification-compliant (#35748)
I have modified the Blob.ArrayBuffer implementation to comply with the
specification part of #25209.
See also: #35151.
Testing: This does not seem to affect tested behavior, so no new tests.
Signed-off-by: yoseio <98276492+yoseio@users.noreply.github.com>
-rw-r--r-- | components/script/dom/blob.rs | 71 | ||||
-rw-r--r-- | components/script_bindings/codegen/Bindings.conf | 2 |
2 files changed, 44 insertions, 29 deletions
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs index c5c5c480707..18e968aaa70 100644 --- a/components/script/dom/blob.rs +++ b/components/script/dom/blob.rs @@ -12,11 +12,10 @@ use dom_struct::dom_struct; use encoding_rs::UTF_8; use js::jsapi::JSObject; use js::rust::HandleObject; -use js::typedarray::Uint8; +use js::typedarray::{ArrayBufferU8, Uint8}; use net_traits::filemanager_thread::RelativePos; use uuid::Uuid; -use crate::body::{FetchedData, run_array_buffer_data_algorithm}; use crate::dom::bindings::buffer_source::create_buffer_source; use crate::dom::bindings::codegen::Bindings::BlobBinding; use crate::dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; @@ -226,7 +225,7 @@ impl BlobMethods<crate::DomTypeHolder> for Blob { Blob::new(&global, blob_impl, can_gc) } - // https://w3c.github.io/FileAPI/#text-method-algo + /// <https://w3c.github.io/FileAPI/#text-method-algo> fn Text(&self, can_gc: CanGc) -> Rc<Promise> { let global = self.global(); let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); @@ -250,35 +249,51 @@ impl BlobMethods<crate::DomTypeHolder> for Blob { } // https://w3c.github.io/FileAPI/#arraybuffer-method-algo - fn ArrayBuffer(&self, can_gc: CanGc) -> Rc<Promise> { - let global = self.global(); - let in_realm_proof = AlreadyInRealm::assert::<crate::DomTypeHolder>(); - let p = Promise::new_in_current_realm(InRealm::Already(&in_realm_proof), can_gc); + fn ArrayBuffer(&self, in_realm: InRealm, can_gc: CanGc) -> Rc<Promise> { + let cx = GlobalScope::get_cx(); + let global = GlobalScope::from_safe_context(cx, in_realm); + let promise = Promise::new_in_current_realm(in_realm, can_gc); - let id = self.get_blob_url_id(); + // 1. Let stream be the result of calling get stream on this. + let stream = self.get_stream(can_gc); - global.read_file_async( - id, - p.clone(), - Box::new(|promise, bytes| { - match bytes { - Ok(b) => { - let cx = GlobalScope::get_cx(); - let result = run_array_buffer_data_algorithm(cx, b, CanGc::note()); - - match result { - Ok(FetchedData::ArrayBuffer(a)) => { - promise.resolve_native(&a, CanGc::note()) - }, - Err(e) => promise.reject_error(e, CanGc::note()), - _ => panic!("Unexpected result from run_array_buffer_data_algorithm"), - } - }, - Err(e) => promise.reject_error(e, CanGc::note()), - }; + // 2. Let reader be the result of getting a reader from stream. + // If that threw an exception, return a new promise rejected with that exception. + let reader = match stream.and_then(|s| s.acquire_default_reader(can_gc)) { + Ok(reader) => reader, + Err(error) => { + promise.reject_error(error, can_gc); + return promise; + }, + }; + + // 3. Let promise be the result of reading all bytes from stream with reader. + let success_promise = promise.clone(); + let failure_promise = promise.clone(); + reader.read_all_bytes( + cx, + &global, + Rc::new(move |bytes| { + rooted!(in(*cx) let mut js_object = ptr::null_mut::<JSObject>()); + // 4. Return the result of transforming promise by a fulfillment handler that returns a new + // [ArrayBuffer] + let array_buffer = create_buffer_source::<ArrayBufferU8>( + cx, + bytes, + js_object.handle_mut(), + can_gc, + ) + .expect("Converting input to ArrayBufferU8 should never fail"); + success_promise.resolve_native(&array_buffer, can_gc); }), + Rc::new(move |cx, value| { + failure_promise.reject(cx, value, can_gc); + }), + in_realm, + can_gc, ); - p + + promise } /// <https://w3c.github.io/FileAPI/#dom-blob-bytes> diff --git a/components/script_bindings/codegen/Bindings.conf b/components/script_bindings/codegen/Bindings.conf index 92871bc54aa..d89b65c646d 100644 --- a/components/script_bindings/codegen/Bindings.conf +++ b/components/script_bindings/codegen/Bindings.conf @@ -39,7 +39,7 @@ DOMInterfaces = { 'Blob': { 'weakReferenceable': True, 'canGc': ['Slice', 'Text', 'ArrayBuffer', 'Stream', 'Bytes'], - 'inRealms': ['Bytes'], + 'inRealms': ['Bytes', 'ArrayBuffer'], }, 'Bluetooth': { |