fix(images): reselect picture requests after removal

This commit is contained in:
ldm0
2026-10-02 03:27:49 +08:00
parent 236835ce24
commit 1d0f471e53
3 changed files with 107 additions and 8 deletions
@@ -2554,6 +2554,7 @@ domparsing/DOMParser-parseFromString-url-pushstate.html
domparsing/DOMParser-parseFromString-url.html
domparsing/DOMParser-parseFromString-xml-doctype.html
domparsing/DOMParser-parseFromString-xml-internal-subset.html
domparsing/DOMParser-parseFromString-xml.html
domparsing/XMLSerializer-serializeToString.html
domparsing/insert_adjacent_html.html
domparsing/tentative/all-stream-methods-with-trusted-types-no-policy.html
@@ -2718,7 +2719,10 @@ focus/iframe-focus-with-same-as-top-intermediate-frame.html
font-access/permissions-policy/local-fonts-supported-by-permissions-policy.html
fullscreen/api/document-exit-fullscreen-active-document.html
fullscreen/api/document-fullscreen-enabled.html
fullscreen/api/document-onfullscreenerror.html
fullscreen/api/element-request-fullscreen-active-document.html
fullscreen/api/element-request-fullscreen-not-allowed.html
fullscreen/api/promises-reject.html
gyroscope/Gyroscope-supported-by-permissions-policy.html
hr-time/test_cross_frame_start.html
html/browsers/browsing-the-web/back-forward-cache/eligibility/dedicated-worker.html
@@ -2802,6 +2806,7 @@ html/browsers/history/the-history-interface/history_pushstate_url_rewriting.html
html/browsers/history/the-history-interface/pushstate-replacestate-empty-string/pushstate.html
html/browsers/history/the-history-interface/pushstate-replacestate-empty-string/replacestate.html
html/browsers/history/the-location-interface/assign_before_load.html
html/browsers/history/the-location-interface/document_location.html
html/browsers/history/the-location-interface/location-ancestor-origins-new-object.html
html/browsers/history/the-location-interface/location-ancestor-origins-referrerpolicy-snapshot.html
html/browsers/history/the-location-interface/location-protocol-setter-non-broken-weird.html
@@ -3007,6 +3012,7 @@ html/semantics/embedded-content/the-img-element/image-loading-lazy-in-scroller-n
html/semantics/embedded-content/the-img-element/image-loading-lazy-in-scroller-nested.html
html/semantics/embedded-content/the-img-element/image-loading-lazy-in-scroller.html
html/semantics/embedded-content/the-img-element/image-loading-lazy-in-viewport-dynamic.html
html/semantics/embedded-content/the-img-element/img-picture-ancestor.html
html/semantics/embedded-content/the-img-element/natural-size-orientation.html
html/semantics/embedded-content/the-img-element/naturalWidth-naturalHeight-width-height.html
html/semantics/embedded-content/the-img-element/relevant-mutations-lazy.html
@@ -3015,6 +3021,7 @@ html/semantics/embedded-content/the-img-element/source-media-outside-doc.html
html/semantics/embedded-content/the-img-element/source-relevant-mutations.html
html/semantics/embedded-content/the-img-element/svg-img-density-vs-zoom.html
html/semantics/embedded-content/the-img-element/update-the-image-data/current-request-microtask-002.html
html/semantics/embedded-content/the-img-element/update-the-image-data/current-request-microtask.html
html/semantics/embedded-content/the-img-element/update-the-image-data/lazy-out-of-band-load.html
html/semantics/embedded-content/the-img-element/update-the-image-data/not-broken-while-load-task-scheduled.html
html/semantics/embedded-content/the-img-element/update-the-image-data/src-then-lazy-load.html
@@ -3277,6 +3284,7 @@ old-tests/submission/Microsoft/selection/insertNodeIntoSelection.htm
old-tests/submission/Microsoft/selection/select.htm
old-tests/submission/Microsoft/selection/selectionStartEnd.htm
old-tests/submission/Microsoft/selection/setSelectionRange.htm
page-lifecycle/idlharness.html
page-visibility/iframe-session-history.html
performance-timeline/get-invalid-entries.html
performance-timeline/navigation-id-worker-created-entries.html
@@ -4094,7 +4094,6 @@ dom/xpath-result-single-node-value-nullable.html
domparsing/DOMParser-parseFromString-encoding.html
domparsing/DOMParser-parseFromString-stylesheets.html
domparsing/DOMParser-parseFromString-xml-parsererror.html
domparsing/DOMParser-parseFromString-xml.html
domparsing/createContextualFragment-in-detached-xml-document-crash.html
domparsing/createContextualFragment.html
domparsing/domparser-spurious-attributes.html
@@ -5562,10 +5561,7 @@ focus/iframe-focuses-parent-same-site.html
focus/scroll-matches-focus.html
focus/synthetic-focus-event-crash.html
fullscreen/api/document-fullscreen-enabled-active-document.html
fullscreen/api/document-onfullscreenerror.html
fullscreen/api/element-request-fullscreen-not-allowed.html
fullscreen/api/historical.html
fullscreen/api/promises-reject.html
fullscreen/crashtests/backdrop-list-item.html
fullscreen/rendering/fullscreen-pseudo-class-support.html
geolocation/non-secure-contexts.http.html
@@ -5736,7 +5732,6 @@ html/browsers/history/the-location-interface/assign-replace-from-iframe.html
html/browsers/history/the-location-interface/assign-replace-from-top-to-nested-iframe.html
html/browsers/history/the-location-interface/assign-with-nested-iframe.html
html/browsers/history/the-location-interface/assign_after_load.html
html/browsers/history/the-location-interface/document_location.html
html/browsers/history/the-location-interface/location-non-configurable-toString-valueOf.html
html/browsers/history/the-location-interface/location-pathname-setter-question-mark.html
html/browsers/history/the-location-interface/location-prevent-extensions.html
@@ -6203,7 +6198,6 @@ html/semantics/embedded-content/the-img-element/image-loading-lazy-subframe-deta
html/semantics/embedded-content/the-img-element/image-loading-lazy-to-eager.html
html/semantics/embedded-content/the-img-element/image-loading-lazy-use-list-of-available-images.html
html/semantics/embedded-content/the-img-element/img-created-in-active-document-crash.html
html/semantics/embedded-content/the-img-element/img-picture-ancestor.html
html/semantics/embedded-content/the-img-element/img-src-in-synthetic-document.html
html/semantics/embedded-content/the-img-element/img.complete.html
html/semantics/embedded-content/the-img-element/invalid-src.html
@@ -6224,7 +6218,6 @@ html/semantics/embedded-content/the-img-element/srcset/select-an-image-source.ht
html/semantics/embedded-content/the-img-element/srcset/srcset-media-dynamic.html
html/semantics/embedded-content/the-img-element/update-media.html
html/semantics/embedded-content/the-img-element/update-src-complete.html
html/semantics/embedded-content/the-img-element/update-the-image-data/current-request-microtask.html
html/semantics/embedded-content/the-img-element/update-the-image-data/fail-to-resolve.html
html/semantics/embedded-content/the-object-element/block-object-with-ruby-crash.html
html/semantics/embedded-content/the-object-element/historical.html
@@ -7932,7 +7925,6 @@ old-tests/submission/Microsoft/selection/removeAllRanges.htm
old-tests/submission/Microsoft/selection/removeRange.htm
old-tests/submission/Microsoft/selection/selectAllChildren.htm
orientation-sensor/OrientationSensor_insecure_context.html
page-lifecycle/idlharness.html
page-visibility/test_attributes_exist.html
page-visibility/test_child_document.html
page-visibility/test_default_view.html
@@ -373,6 +373,105 @@ async fn image_current_src_is_empty_while_a_replacement_request_is_pending() {
);
}
#[tokio::test]
async fn picture_source_and_image_tree_mutations_reselect_requests() {
let loader = ResourceRequestClient::new(&moli_fetch::FetchConfig::default()).expect("loader");
loader.set_image_fetch_enabled(true);
let (mut vm, _resource_completion_queue) =
new_storage_test_vm_with_loader_and_resource_completion_queue(
"https://picture-source-removal.test/page.html",
&loader,
);
vm.eval(
r#"
(() => {
if (!document.documentElement) {
document.append(document.createElement("html"));
}
if (!document.body) {
document.documentElement.append(document.createElement("body"));
}
const picture = document.createElement("picture");
const source1 = document.createElement("source");
const source2 = document.createElement("source");
const source3 = document.createElement("source");
const source4 = document.createElement("source");
const source5 = document.createElement("source");
const image1 = document.createElement("img");
const image2 = document.createElement("img");
source1.srcset = "data:,s1";
source2.srcset = "data:,s2";
source3.srcset = "data:,s3";
source4.srcset = "data:,s4";
source5.srcset = "data:,s5";
image1.src = "data:,img1";
image2.src = "data:,img2";
picture.append(source1, source2, source3, image1, image2, source4, source5);
const host = document.body;
host.append(picture);
globalThis.__pictureSourceMutation = {
host,
picture,
source1,
source2,
source3,
source4,
source5,
image1,
image2
};
})()
"#,
)
.expect("picture source mutation setup should evaluate");
let current_sources = |vm: &mut ScriptVm| {
vm.eval(
"[__pictureSourceMutation.image1.currentSrc, \
__pictureSourceMutation.image2.currentSrc].join(',')",
)
.expect("picture image current sources should evaluate")
};
assert_eq!(current_sources(&mut vm), "data:,s1,data:,s1");
vm.eval("__pictureSourceMutation.source1.remove()")
.expect("first picture source removal should evaluate");
assert_eq!(current_sources(&mut vm), "data:,s2,data:,s2");
vm.eval("__pictureSourceMutation.source2.remove()")
.expect("second picture source removal should evaluate");
assert_eq!(current_sources(&mut vm), "data:,s3,data:,s3");
vm.eval("__pictureSourceMutation.host.append(__pictureSourceMutation.source3)")
.expect("third picture source move should evaluate");
assert_eq!(current_sources(&mut vm), "data:,img1,data:,img2");
vm.eval("__pictureSourceMutation.source4.remove()")
.expect("trailing picture source removal should evaluate");
assert_eq!(current_sources(&mut vm), "data:,img1,data:,img2");
vm.eval("__pictureSourceMutation.host.append(__pictureSourceMutation.source5)")
.expect("trailing picture source move should evaluate");
assert_eq!(current_sources(&mut vm), "data:,img1,data:,img2");
vm.eval("__pictureSourceMutation.picture.prepend(__pictureSourceMutation.source2)")
.expect("second picture source reinsertion should evaluate");
assert_eq!(current_sources(&mut vm), "data:,s2,data:,s2");
vm.eval("__pictureSourceMutation.picture.prepend(__pictureSourceMutation.source1)")
.expect("first picture source reinsertion should evaluate");
assert_eq!(current_sources(&mut vm), "data:,s1,data:,s1");
vm.eval("__pictureSourceMutation.source1.replaceWith(document.createElement('div'))")
.expect("first picture source replacement should evaluate");
assert_eq!(current_sources(&mut vm), "data:,s2,data:,s2");
vm.eval("__pictureSourceMutation.image1.remove()")
.expect("first picture image removal should evaluate");
assert_eq!(current_sources(&mut vm), "data:,img1,data:,s2");
}
#[tokio::test]
async fn image_fetch_enabled_dispatches_http_error_after_resource_timing() {
let (base_url, request_rx, server) =