diff options
author | Taym Haddadi <haddadi.taym@gmail.com> | 2024-06-13 12:15:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-13 10:15:49 +0000 |
commit | 1d048f4f6a147ab1f81893f370df3447b18075ec (patch) | |
tree | 028fa6776ad105608c28dc9fa6c415230576edf0 /components | |
parent | 43df0a48ee3b7786c86d6f000e5f6acc990b61de (diff) | |
download | servo-1d048f4f6a147ab1f81893f370df3447b18075ec.tar.gz servo-1d048f4f6a147ab1f81893f370df3447b18075ec.zip |
Implement HTMLImageElement decode (#31269)
* Implement HTMLImageElement decode
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Fix Decode doc link
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Temp
* Decode HTML Image
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Fix doc link
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Move image decode to process_image_response_for_environment_change
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Update some wpt test result
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Handle multiple image decode promises
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Remove unnecessary promise calls
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Update more wpt test result
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Undo body-size-cross-origin.https.html.ini changes
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Reject decode when src and srcset are missing
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Revert "Reject decode when src and srcset are missing"
This reverts commit 1b57ab978f9fc24facafc8af97ee8851d5142533.
* Drain promises vec and run update_the_image_data when element is created
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* resolve decode promise in abort_request when request is CompletelyAvailable
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Update wpt test
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Move storing promise in decode task
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Remove the resolve logic from decode task
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Revert "Remove the resolve logic from decode task"
This reverts commit eee6096d50dbe46a22a5bbfd7f15c03988ed2f4b.
* reject or reject current promise before storing it
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
* Add comment to explain why resolve promise when state is CompletelyAvailable
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
---------
Signed-off-by: Bentaimia Haddadi <haddadi.taym@gmail.com>
Diffstat (limited to 'components')
-rw-r--r-- | components/script/dom/domexception.rs | 5 | ||||
-rw-r--r-- | components/script/dom/htmlimageelement.rs | 90 | ||||
-rw-r--r-- | components/script/dom/webidls/HTMLImageElement.webidl | 3 |
3 files changed, 97 insertions, 1 deletions
diff --git a/components/script/dom/domexception.rs b/components/script/dom/domexception.rs index c058136a8b5..2267148626f 100644 --- a/components/script/dom/domexception.rs +++ b/components/script/dom/domexception.rs @@ -41,6 +41,7 @@ pub enum DOMErrorName { TimeoutError = DOMExceptionConstants::TIMEOUT_ERR, InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR, DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR, + EncodingError, NotReadableError, OperationError, } @@ -70,6 +71,7 @@ impl DOMErrorName { "TimeoutError" => Some(DOMErrorName::TimeoutError), "InvalidNodeTypeError" => Some(DOMErrorName::InvalidNodeTypeError), "DataCloneError" => Some(DOMErrorName::DataCloneError), + "EncodingError" => Some(DOMErrorName::EncodingError), "NotReadableError" => Some(DOMErrorName::NotReadableError), "OperationError" => Some(DOMErrorName::OperationError), _ => None, @@ -115,6 +117,9 @@ impl DOMException { "The supplied node is incorrect or has an incorrect ancestor for this operation." }, DOMErrorName::DataCloneError => "The object can not be cloned.", + DOMErrorName::EncodingError => { + "The encoding operation (either encoded or decoding) failed." + }, DOMErrorName::NotReadableError => "The I/O read operation failed.", DOMErrorName::OperationError => { "The operation failed for an operation-specific reason." diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index b3c36fe5e27..1843bbf3e18 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -5,6 +5,7 @@ use std::cell::Cell; use std::collections::HashSet; use std::default::Default; +use std::rc::Rc; use std::sync::{Arc, Mutex}; use std::{char, i32, mem}; @@ -47,6 +48,8 @@ use style::values::specified::AbsoluteLength; use style_traits::ParsingMode; use url::Url; +use super::domexception::DOMErrorName; +use super::types::DOMException; use crate::document_loader::{LoadBlocker, LoadType}; use crate::dom::activation::Activatable; use crate::dom::attr::Attr; @@ -84,6 +87,7 @@ use crate::dom::node::{ UnbindContext, }; use crate::dom::performanceresourcetiming::InitiatorType; +use crate::dom::promise::Promise; use crate::dom::values::UNSIGNED_LONG_MAX; use crate::dom::virtualmethods::VirtualMethods; use crate::dom::window::Window; @@ -169,6 +173,8 @@ pub struct HTMLImageElement { #[ignore_malloc_size_of = "SourceSet"] source_set: DomRefCell<SourceSet>, last_selected_source: DomRefCell<Option<USVString>>, + #[ignore_malloc_size_of = "promises are hard"] + image_decode_promises: DomRefCell<Vec<Rc<Promise>>>, } impl HTMLImageElement { @@ -424,6 +430,7 @@ impl HTMLImageElement { LoadBlocker::terminate(&mut self.current_request.borrow_mut().blocker); // Mark the node dirty self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage); + self.resolve_image_decode_promises(); } /// Step 24 of <https://html.spec.whatwg.org/multipage/#update-the-image-data> @@ -525,6 +532,12 @@ impl HTMLImageElement { request.state = state; request.image = None; request.metadata = None; + + if matches!(state, State::Broken) { + self.reject_image_decode_promises(); + } else if matches!(state, State::CompletelyAvailable) { + self.resolve_image_decode_promises(); + } } /// <https://html.spec.whatwg.org/multipage/#update-the-source-set> @@ -1161,6 +1174,48 @@ impl HTMLImageElement { } } + // Step 2 for <https://html.spec.whatwg.org/multipage/#dom-img-decode> + fn react_to_decode_image_sync_steps(&self, promise: Rc<Promise>) { + let document = document_from_node(self); + // Step 2.1 of <https://html.spec.whatwg.org/multipage/#dom-img-decode> + if !document.is_fully_active() || + matches!(self.current_request.borrow().state, State::Broken) + { + promise.reject_native(&DOMException::new( + &document.global(), + DOMErrorName::EncodingError, + )); + } else if matches!( + self.current_request.borrow().state, + State::CompletelyAvailable + ) { + // this doesn't follow the spec, but it's been discussed in <https://github.com/whatwg/html/issues/4217> + promise.resolve_native(&()); + } else { + self.image_decode_promises + .borrow_mut() + .push(promise.clone()); + } + } + + fn resolve_image_decode_promises(&self) { + for promise in self.image_decode_promises.borrow().iter() { + promise.resolve_native(&()); + } + self.image_decode_promises.borrow_mut().clear(); + } + + fn reject_image_decode_promises(&self) { + let document = document_from_node(self); + for promise in self.image_decode_promises.borrow().iter() { + promise.reject_native(&DOMException::new( + &document.global(), + DOMErrorName::EncodingError, + )); + } + self.image_decode_promises.borrow_mut().clear(); + } + /// Step 15 for <https://html.spec.whatwg.org/multipage/#img-environment-changes> fn finish_reacting_to_environment_change( &self, @@ -1249,6 +1304,7 @@ impl HTMLImageElement { generation: Default::default(), source_set: DomRefCell::new(SourceSet::new()), last_selected_source: DomRefCell::new(None), + image_decode_promises: DomRefCell::new(vec![]), } } @@ -1291,6 +1347,10 @@ impl HTMLImageElement { image.SetHeight(h); } + // run update_the_image_data when the element is created. + // https://html.spec.whatwg.org/multipage/#when-to-obtain-images + image.update_the_image_data(); + Ok(image) } pub fn areas(&self) -> Option<Vec<DomRoot<HTMLAreaElement>>> { @@ -1347,6 +1407,11 @@ pub enum ImageElementMicrotask { elem: DomRoot<HTMLImageElement>, generation: u32, }, + DecodeTask { + elem: DomRoot<HTMLImageElement>, + #[ignore_malloc_size_of = "promises are hard"] + promise: Rc<Promise>, + }, } impl MicrotaskRunnable for ImageElementMicrotask { @@ -1368,13 +1433,20 @@ impl MicrotaskRunnable for ImageElementMicrotask { } => { elem.react_to_environment_changes_sync_steps(*generation); }, + ImageElementMicrotask::DecodeTask { + ref elem, + ref promise, + } => { + elem.react_to_decode_image_sync_steps(promise.clone()); + }, } } fn enter_realm(&self) -> JSAutoRealm { match self { &ImageElementMicrotask::StableStateUpdateImageDataTask { ref elem, .. } | - &ImageElementMicrotask::EnvironmentChangesTask { ref elem, .. } => enter_realm(&**elem), + &ImageElementMicrotask::EnvironmentChangesTask { ref elem, .. } | + &ImageElementMicrotask::DecodeTask { ref elem, .. } => enter_realm(&**elem), } } } @@ -1607,6 +1679,22 @@ impl HTMLImageElementMethods for HTMLImageElement { } } + /// <https://html.spec.whatwg.org/multipage/#dom-img-decode> + fn Decode(&self) -> Rc<Promise> { + // Step 1 + let promise = Promise::new(&self.global()); + + // Step 2 + let task = ImageElementMicrotask::DecodeTask { + elem: DomRoot::from_ref(self), + promise: promise.clone(), + }; + ScriptThread::await_stable_state(Microtask::ImageElement(task)); + + // Step 3 + promise + } + // https://html.spec.whatwg.org/multipage/#dom-img-name make_getter!(Name, "name"); diff --git a/components/script/dom/webidls/HTMLImageElement.webidl b/components/script/dom/webidls/HTMLImageElement.webidl index 0d242fefb26..faae1c8992b 100644 --- a/components/script/dom/webidls/HTMLImageElement.webidl +++ b/components/script/dom/webidls/HTMLImageElement.webidl @@ -29,6 +29,9 @@ interface HTMLImageElement : HTMLElement { readonly attribute USVString currentSrc; [CEReactions] attribute DOMString referrerPolicy; + + Promise<undefined> decode(); + // also has obsolete members }; |