Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React to env #2

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
238 changes: 224 additions & 14 deletions components/script/dom/htmlimageelement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ impl HTMLImageElement {
document.loader().fetch_async_background(request, action_sender);
}

/// Step 14 of https://html.spec.whatwg.org/multipage/#update-the-image-data
/// Step 24 of https://html.spec.whatwg.org/multipage/#update-the-image-data
fn process_image_response(&self, image: ImageResponse) {
// TODO: Handle multipart/x-mixed-replace
let (trigger_image_load, trigger_image_error) = match (image, self.image_request.get()) {
Expand Down Expand Up @@ -579,7 +579,7 @@ impl HTMLImageElement {
}

/// <https://html.spec.whatwg.org/multipage/#select-an-image-source>
fn select_image_source(&self) -> Option<(DOMString, f32)> {
fn select_image_source(&self) -> Option<(DOMString, f64)> {
// Step 1, 3
self.update_source_set();
let source_set = &*self.source_set.borrow_mut();
Expand Down Expand Up @@ -632,7 +632,7 @@ impl HTMLImageElement {
}
}
let selected_source = img_sources.remove(best_candidate.1).clone();
Some((DOMString::from_string(selected_source.url), selected_source.descriptor.den.unwrap() as f32))
Some((DOMString::from_string(selected_source.url), selected_source.descriptor.den.unwrap() as f64))
}

fn init_image_request(&self,
Expand All @@ -648,12 +648,12 @@ impl HTMLImageElement {
request.blocker = Some(LoadBlocker::new(&*document, LoadType::Image(url.clone())));
}

/// Step 12 of html.spec.whatwg.org/multipage/#update-the-image-data
/// Step 13-17 of html.spec.whatwg.org/multipage/#update-the-image-data
fn prepare_image_request(&self, url: &ServoUrl, src: &DOMString) {
match self.image_request.get() {
ImageRequestPhase::Pending => {
if let Some(pending_url) = self.pending_request.borrow().parsed_url.clone() {
// Step 12.1
// Step 13
if pending_url == *url {
return
}
Expand All @@ -662,12 +662,12 @@ impl HTMLImageElement {
ImageRequestPhase::Current => {
let mut current_request = self.current_request.borrow_mut();
let mut pending_request = self.pending_request.borrow_mut();
// step 12.4, create a new "image_request"
// step 16, create a new "image_request"
match (current_request.parsed_url.clone(), current_request.state) {
(Some(parsed_url), State::PartiallyAvailable) => {
// Step 12.2
// Step 14
if parsed_url == *url {
// 12.3 abort pending request
// 15 abort pending request
pending_request.image = None;
pending_request.parsed_url = None;
LoadBlocker::terminate(&mut pending_request.blocker);
Expand All @@ -678,11 +678,11 @@ impl HTMLImageElement {
self.init_image_request(&mut pending_request, &url, &src);
},
(_, State::Broken) | (_, State::Unavailable) => {
// Step 12.5
// Step 17
self.init_image_request(&mut current_request, &url, &src);
},
(_, _) => {
// step 12.6
// step 17
self.image_request.set(ImageRequestPhase::Pending);
self.init_image_request(&mut pending_request, &url, &src);
},
Expand All @@ -700,7 +700,7 @@ impl HTMLImageElement {
let this = Trusted::new(self);
let src = match self.select_image_source() {
Some(src) => {
// Step 8.
// Step 8
// TODO: Handle pixel density.
src.0
},
Expand Down Expand Up @@ -755,11 +755,11 @@ impl HTMLImageElement {
let parsed_url = base_url.join(&src);
match parsed_url {
Ok(url) => {
// Step 12
// Step 13
self.prepare_image_request(&url, &src);
},
Err(_) => {
// Step 11.1-11.5.
// Step 12.1-12.5.
let src = String::from(src);
// FIXME(nox): Why are errors silenced here?
let _ = task_source.queue(
Expand Down Expand Up @@ -871,6 +871,198 @@ impl HTMLImageElement {
ScriptThread::await_stable_state(Microtask::ImageElement(task));
}

/// <https://html.spec.whatwg.org/multipage/#img-environment-changes>
fn react_to_environment_changes(&self){
// Step 1
let task = ImageElementMicrotask::EnvironmentChangesTask {
elem: DomRoot::from_ref(self),
};
ScriptThread::await_stable_state(Microtask::ImageElement(task));

let elem = self.upcast::<Element>();
let document = document_from_node(elem);

}

/// Step 3-12 of https://html.spec.whatwg.org/multipage/#img-environment-changes
fn react_to_environment_changes_sync_steps(&self){
let mut selected_source = None;
let mut selected_pixel_density = None;
let elem = self.upcast::<Element>();
let document = document_from_node(elem);
let base_url = document.base_url();
match self.select_image_source() {
Some(src) => {
// Step 3
selected_source = Some(src.0);
selected_pixel_density = Some(src.1);
},
_ => ()
}

// Step 4
let src = match selected_source {
Some(src) => src,
_ => return,
};

// Step 5
let same_source = match *self.last_selected_source.borrow() {
Some(ref last_src) => *last_src == src,
_ => false,
};

let same_selected_pixel_density = match selected_pixel_density {
Some(den) => self.current_request.borrow().current_pixel_density.map_or(false,|density| density==den),
_ => self.current_request.borrow().current_pixel_density.map_or(true, |den| false),
};

if same_source && same_selected_pixel_density {
return;
}

// Step 6
if let Ok(img_url) = base_url.join(&String::from(src.clone())) {

// Step 7
let corsAttributeState = self.GetCrossOrigin();

// Step 8
let origin = document.origin().immutable().clone();

// Step 10
// TODO Handle No CORS here
let key = (img_url.clone(), corsAttributeState);

// Step 12
*self.pending_request.borrow_mut() = ImageRequest {
state: State::Unavailable,
parsed_url: Some(img_url.clone()),
source_url: None,
image: None,
metadata: None,
blocker: None,
final_url: None,
current_pixel_density: None,
};

// Step 13 ??
let window = window_from_node(self);
let image_cache = window.image_cache();
// Step 14
let response =
image_cache.find_image_or_metadata(img_url.clone().into(),
UsePlaceholder::No,
CanRequestImages::No);

if let Ok(ImageOrMetadataAvailable::ImageAvailable(_image, _url)) = response {

} else {
let window = window_from_node(self);
let image_cache = window.image_cache();
// Step 14.1
let response =
image_cache.find_image_or_metadata(img_url.clone().into(),
UsePlaceholder::Yes,
CanRequestImages::Yes);
match response {
// TODO Handle multipart/x-mixtape
Ok(ImageOrMetadataAvailable::ImageAvailable(_image, _url)) => {

}
// TODO required for making response exhaustive, but what should it return ??
Ok(ImageOrMetadataAvailable::MetadataAvailable(_m)) => {

}
// TODO what here?
Err(ImageState::Pending(_id)) => {
//add_cache_listener_for_element(image_cache.clone(), id, self);
}
// TODO what here?
Err(ImageState::NotRequested(_id)) => {
//add_cache_listener_for_element(image_cache, id, self);
//self.fetch_request(img_url, id);
}

Err(ImageState::LoadError) => {
*self.pending_request.borrow_mut() = ImageRequest {
state: State::Unavailable,
parsed_url: None,
source_url: None,
image: None,
metadata: None,
blocker: None,
final_url: None,
current_pixel_density: None,
};
}

}
}

let this = Trusted::new(self);
let new_selected_source = src.to_string();
// Step 15
let _ = window.dom_manipulation_task_source().queue(
task!(image_load_event: move || {
let this = this.root();
// Step 15.1
if this.has_relevant_mutations() {
let mut pending_request =
&*this.pending_request.borrow_mut();
pending_request = &ImageRequest {
state: State::Unavailable,
parsed_url: None,
source_url: None,
image: None,
metadata: None,
blocker: None,
final_url: None,
current_pixel_density: None,
};
return;
}

// Step 15.2
*this.last_selected_source.borrow_mut() = Some(DOMString::from_string(new_selected_source));
let mut current_request = this.current_request.borrow_mut();
current_request.current_pixel_density = selected_pixel_density;

// Step 15.3
this.current_request.borrow_mut().state = State::CompletelyAvailable;

// Step 15.4 ?

// Step 15.5
*this.current_request.borrow_mut() = *this.pending_request.borrow();
*this.pending_request.borrow_mut() = ImageRequest {
state: State::Unavailable,
parsed_url: None,
source_url: None,
image: None,
metadata: None,
blocker: None,
final_url: None,
current_pixel_density: None,
};

// Step 15.6 ?

// Step 15.7
this.upcast::<EventTarget>().fire_event(atom!("load"));

}),
window.upcast(),
);

}
return;
}

fn has_relevant_mutations(&self) -> bool {
return false;
}

fn new_inherited(local_name: LocalName, prefix: Option<Prefix>, document: &Document) -> HTMLImageElement {
HTMLImageElement {
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
Expand Down Expand Up @@ -962,7 +1154,10 @@ impl HTMLImageElement {
pub enum ImageElementMicrotask {
StableStateUpdateImageDataTask {
elem: DomRoot<HTMLImageElement>,
generation: u32,
generation: u32,
},
EnvironmentChangesTask {
elem: DomRoot<HTMLImageElement>,
}
}

Expand All @@ -976,6 +1171,21 @@ impl MicrotaskRunnable for ImageElementMicrotask {
elem.update_the_image_data_sync_steps();
}
},
&ImageElementMicrotask::EnvironmentChangesTask { ref elem } => {
// TODO: Handle multipart/x-mixed-replace
// Step 2 of https://html.spec.whatwg.org/multipage/#img-environment-changes,
let element = elem.upcast::<Element>();
let has_src = element.has_attribute(&local_name!("srcset"));
let document = document_from_node(element);
let has_pending_request = match elem.image_request.get() {
ImageRequestPhase::Pending => true,
_ => false
};

if document.is_active() && has_src && !has_pending_request {
elem.react_to_environment_changes_sync_steps();
}
},
}
}
}
Expand Down