aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorTaym Haddadi <haddadi.taym@gmail.com>2024-06-13 12:15:49 +0200
committerGitHub <noreply@github.com>2024-06-13 10:15:49 +0000
commit1d048f4f6a147ab1f81893f370df3447b18075ec (patch)
tree028fa6776ad105608c28dc9fa6c415230576edf0 /components
parent43df0a48ee3b7786c86d6f000e5f6acc990b61de (diff)
downloadservo-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.rs5
-rw-r--r--components/script/dom/htmlimageelement.rs90
-rw-r--r--components/script/dom/webidls/HTMLImageElement.webidl3
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
};