LibWeb: Use the node document realm for image requests
An HTMLImageElement can be adopted across documents while an image update is still pending. In that case the element's wrapper realm can still be the old iframe realm, but the image request must be created and fetched using the element's current node document. Using the old iframe realm associates the request with the removed iframe's document-owned image request cache, so the adopted image can fail to complete in the parent document. Use document().realm() when creating/updating/fetching image requests so adopted images continue loading in their new document. Add a regression for an image created in an iframe, then adopted into the parent after the iframe is removed. Chromium and Webkit do not fire a load event for the test, but Firefox does. All load the image, where we previously did not. See: https://github.com/whatwg/html/issues/8492
This commit is contained in:
parent
7e6d4b7b7b
commit
2a2b0bf91a
4 changed files with 43 additions and 11 deletions
|
|
@ -723,7 +723,7 @@ void HTMLImageElement::update_the_image_data_impl(bool restart_animations, bool
|
|||
m_pending_request = nullptr;
|
||||
|
||||
// 4. Set the current request to a new image request whose image data is that of the entry and whose state is completely available.
|
||||
m_current_request = ImageRequest::create(realm(), document().page());
|
||||
m_current_request = ImageRequest::create(document().realm(), document().page());
|
||||
m_current_request->set_image_data(entry->image_data);
|
||||
m_current_request->set_state(ImageRequest::State::CompletelyAvailable);
|
||||
m_current_frame_index = 0;
|
||||
|
|
@ -750,7 +750,7 @@ void HTMLImageElement::update_the_image_data_impl(bool restart_animations, bool
|
|||
restart_the_animation();
|
||||
|
||||
// 2. Set the current request's current URL to urlString.
|
||||
m_current_request->set_current_url(realm(), *url_string);
|
||||
m_current_request->set_current_url(document().realm(), *url_string);
|
||||
|
||||
set_needs_style_update(true);
|
||||
set_needs_layout_update_or_repaint_after_image_data_change(*this, DOM::SetNeedsLayoutReason::HTMLImageElementUpdateTheImageData);
|
||||
|
|
@ -808,7 +808,7 @@ after_step_7:
|
|||
}
|
||||
|
||||
// 1. Change the current request's current URL to the empty string.
|
||||
m_current_request->set_current_url(realm(), String {});
|
||||
m_current_request->set_current_url(document().realm(), String {});
|
||||
|
||||
// 2. If all of the following conditions are true:
|
||||
// - the element has a src attribute or it uses srcset or picture; and
|
||||
|
|
@ -849,7 +849,7 @@ after_step_7:
|
|||
}
|
||||
|
||||
// 1. Change the current request's current URL to selected source.
|
||||
m_current_request->set_current_url(realm(), selected_source.value().url);
|
||||
m_current_request->set_current_url(document().realm(), selected_source.value().url);
|
||||
|
||||
// 2. If maybe omit events is not set or previousURL is not equal to selected source, then fire an event named error at the img element.
|
||||
if (!maybe_omit_events || previous_url != selected_source.value().url)
|
||||
|
|
@ -885,8 +885,8 @@ after_step_7:
|
|||
// multiple image elements (as well as CSS background-images, etc.)
|
||||
|
||||
// 17. Set image request to a new image request whose current URL is urlString.
|
||||
auto image_request = ImageRequest::create(realm(), document().page());
|
||||
image_request->set_current_url(realm(), *url_string);
|
||||
auto image_request = ImageRequest::create(document().realm(), document().page());
|
||||
image_request->set_current_url(document().realm(), *url_string);
|
||||
|
||||
// 18. If the current request's state is unavailable or broken, then set the current request to image request.
|
||||
// Otherwise, set the pending request to image request.
|
||||
|
|
@ -934,7 +934,7 @@ after_step_7:
|
|||
if (will_lazy_load_element()) {
|
||||
// 1. Set the img's lazy load resumption steps to the rest of this algorithm starting with the step labeled fetch the image.
|
||||
set_lazy_load_resumption_steps([this, request, image_request]() {
|
||||
image_request->fetch_image(realm(), request);
|
||||
image_request->fetch_image(document().realm(), request);
|
||||
});
|
||||
|
||||
// 2. Start intersection-observing a lazy loading element for the img element.
|
||||
|
|
@ -944,7 +944,7 @@ after_step_7:
|
|||
return;
|
||||
}
|
||||
|
||||
image_request->fetch_image(realm(), request);
|
||||
image_request->fetch_image(document().realm(), request);
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
@ -1115,8 +1115,8 @@ void HTMLImageElement::react_to_changes_in_the_environment()
|
|||
key.origin = document().origin();
|
||||
|
||||
// 12. ⌛ Let image request be a new image request whose current URL is urlString
|
||||
auto image_request = ImageRequest::create(realm(), document().page());
|
||||
image_request->set_current_url(realm(), *url_string);
|
||||
auto image_request = ImageRequest::create(document().realm(), document().page());
|
||||
image_request->set_current_url(document().realm(), *url_string);
|
||||
|
||||
// 13. ⌛ Set the element's pending request to image request.
|
||||
m_pending_request = image_request;
|
||||
|
|
@ -1216,7 +1216,7 @@ void HTMLImageElement::react_to_changes_in_the_environment()
|
|||
});
|
||||
|
||||
// 5. Let response be the result of fetching request.
|
||||
image_request->fetch_image(realm(), request);
|
||||
image_request->fetch_image(document().realm(), request);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ Text/input/wpt-import/webstorage/event_session_storagearea.html
|
|||
Text/input/wpt-import/webstorage/storage_session_window_open.window.html
|
||||
Text/input/navigation/navigation-navigate.html
|
||||
Text/input/navigation/location-reload-fetch.html
|
||||
Text/input/HTML/image-load-after-adoption-from-removed-iframe.html
|
||||
Text/input/HTML/session-storage-event-fired-to-lazy-window.html
|
||||
Text/input/HTML/parser-streams-bytes.html
|
||||
Text/input/HTML/parser-streams-with-document-write.html
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
image loaded after adoption
|
||||
width=120 height=120 naturalWidth=120 naturalHeight=120 complete=true
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="../include.js"></script>
|
||||
<script>
|
||||
asyncTest(done => {
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.onload = () => {
|
||||
const img = iframe.contentDocument.createElement("img");
|
||||
|
||||
// See: https://github.com/whatwg/html/issues/8492
|
||||
img.onload = () => {
|
||||
println("image loaded after adoption");
|
||||
println(`width=${img.width} height=${img.height} naturalWidth=${img.naturalWidth} naturalHeight=${img.naturalHeight} complete=${img.complete}`);
|
||||
done();
|
||||
};
|
||||
img.onerror = () => {
|
||||
println("image errored after adoption");
|
||||
done();
|
||||
};
|
||||
|
||||
img.src = new URL("../../../Assets/120.png", document.baseURI).href;
|
||||
iframe.contentDocument.body.appendChild(img);
|
||||
|
||||
iframe.remove();
|
||||
document.body.appendChild(document.adoptNode(img));
|
||||
};
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
</script>
|
||||
Loading…
Reference in a new issue