mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Don't recurse in Node::GetRootNode (#35725)
* Don't recurse in Node::GetRootNode This causes servo to crash when computing the root of deeply nested shadow roots. Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Add test case Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
ce977636f6
commit
25cc675101
7 changed files with 59 additions and 13 deletions
|
@ -2887,19 +2887,16 @@ impl NodeMethods<crate::DomTypeHolder> for Node {
|
||||||
|
|
||||||
/// <https://dom.spec.whatwg.org/#dom-node-getrootnode>
|
/// <https://dom.spec.whatwg.org/#dom-node-getrootnode>
|
||||||
fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot<Node> {
|
fn GetRootNode(&self, options: &GetRootNodeOptions) -> DomRoot<Node> {
|
||||||
if let Some(shadow_root) = self.containing_shadow_root() {
|
if !options.composed {
|
||||||
return if options.composed {
|
if let Some(shadow_root) = self.containing_shadow_root() {
|
||||||
// shadow-including root.
|
return DomRoot::upcast(shadow_root);
|
||||||
shadow_root.Host().upcast::<Node>().GetRootNode(options)
|
}
|
||||||
} else {
|
|
||||||
DomRoot::from_ref(shadow_root.upcast::<Node>())
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_in_a_document_tree() {
|
if self.is_connected() {
|
||||||
DomRoot::from_ref(self.owner_doc().upcast::<Node>())
|
DomRoot::from_ref(self.owner_doc().upcast::<Node>())
|
||||||
} else {
|
} else {
|
||||||
self.inclusive_ancestors(ShadowIncluding::No)
|
self.inclusive_ancestors(ShadowIncluding::Yes)
|
||||||
.last()
|
.last()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
13
tests/wpt/mozilla/meta/MANIFEST.json
vendored
13
tests/wpt/mozilla/meta/MANIFEST.json
vendored
|
@ -13496,14 +13496,14 @@
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"interfaces.https.html": [
|
"interfaces.https.html": [
|
||||||
"6c48986beea5c8aca4e54c6da0fb8f3b7a4390e0",
|
"81f4d942f94366d8f9ecf22cfc3e1e22fe4ab8f1",
|
||||||
[
|
[
|
||||||
null,
|
null,
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"interfaces.worker.js": [
|
"interfaces.worker.js": [
|
||||||
"4ac5c822dcc6fbb021050ac2ab2ba4d04452d945",
|
"06eb8d3ba2334951cb1e0f791527ba118d4f13ec",
|
||||||
[
|
[
|
||||||
"mozilla/interfaces.worker.html",
|
"mozilla/interfaces.worker.html",
|
||||||
{}
|
{}
|
||||||
|
@ -14337,6 +14337,15 @@
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"shadow-dom": {
|
||||||
|
"getrootnode-in-deeply-nested-shadow.html": [
|
||||||
|
"355cc270e6020f40176afac26c49a14a59b67169",
|
||||||
|
[
|
||||||
|
null,
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
"webxr": {
|
"webxr": {
|
||||||
"create_session.https.html": [
|
"create_session.https.html": [
|
||||||
"5b5d485b372bfffb22204bc162c9e182306395cb",
|
"5b5d485b372bfffb22204bc162c9e182306395cb",
|
||||||
|
|
1
tests/wpt/mozilla/meta/__dir__.ini
vendored
Normal file
1
tests/wpt/mozilla/meta/__dir__.ini
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
prefs: ["dom_imagebitmap_enabled:true", "dom_offscreen_canvas_enabled:true", "dom_shadowdom_enabled:true", "dom_xpath_enabled:true", "dom_intersection_observer_enabled:true", "dom_resize_observer_enabled:true", "dom_notification_enabled:true", "dom_fontface_enabled:true"]
|
|
@ -1,2 +0,0 @@
|
||||||
[partial_shadow_dom_layout_style.html]
|
|
||||||
expected: FAIL
|
|
|
@ -92,6 +92,7 @@ test_interfaces([
|
||||||
"FileList",
|
"FileList",
|
||||||
"FileReader",
|
"FileReader",
|
||||||
"FocusEvent",
|
"FocusEvent",
|
||||||
|
"FontFace",
|
||||||
"FontFaceSet",
|
"FontFaceSet",
|
||||||
"FormData",
|
"FormData",
|
||||||
"FormDataEvent",
|
"FormDataEvent",
|
||||||
|
@ -181,7 +182,10 @@ test_interfaces([
|
||||||
"IIRFilterNode",
|
"IIRFilterNode",
|
||||||
"ImageData",
|
"ImageData",
|
||||||
"Image",
|
"Image",
|
||||||
|
"ImageBitmap",
|
||||||
"InputEvent",
|
"InputEvent",
|
||||||
|
"IntersectionObserver",
|
||||||
|
"IntersectionObserverEntry",
|
||||||
"KeyboardEvent",
|
"KeyboardEvent",
|
||||||
"Location",
|
"Location",
|
||||||
"MediaElementAudioSourceNode",
|
"MediaElementAudioSourceNode",
|
||||||
|
@ -213,6 +217,8 @@ test_interfaces([
|
||||||
"Notification",
|
"Notification",
|
||||||
"OfflineAudioCompletionEvent",
|
"OfflineAudioCompletionEvent",
|
||||||
"OfflineAudioContext",
|
"OfflineAudioContext",
|
||||||
|
"OffscreenCanvas",
|
||||||
|
"OffscreenCanvasRenderingContext2D",
|
||||||
"Option",
|
"Option",
|
||||||
"OscillatorNode",
|
"OscillatorNode",
|
||||||
"PageTransitionEvent",
|
"PageTransitionEvent",
|
||||||
|
@ -242,6 +248,9 @@ test_interfaces([
|
||||||
"ReadableByteStreamController",
|
"ReadableByteStreamController",
|
||||||
"ReadableStreamBYOBRequest",
|
"ReadableStreamBYOBRequest",
|
||||||
"Request",
|
"Request",
|
||||||
|
"ResizeObserver",
|
||||||
|
"ResizeObserverEntry",
|
||||||
|
"ResizeObserverSize",
|
||||||
"Response",
|
"Response",
|
||||||
"Screen",
|
"Screen",
|
||||||
"SecurityPolicyViolationEvent",
|
"SecurityPolicyViolationEvent",
|
||||||
|
@ -303,6 +312,9 @@ test_interfaces([
|
||||||
"XMLHttpRequestEventTarget",
|
"XMLHttpRequestEventTarget",
|
||||||
"XMLHttpRequestUpload",
|
"XMLHttpRequestUpload",
|
||||||
"XMLSerializer",
|
"XMLSerializer",
|
||||||
|
"XPathEvaluator",
|
||||||
|
"XPathExpression",
|
||||||
|
"XPathResult",
|
||||||
"XRBoundedReferenceSpace",
|
"XRBoundedReferenceSpace",
|
||||||
"XRFrame",
|
"XRFrame",
|
||||||
"XRHand",
|
"XRHand",
|
||||||
|
|
|
@ -37,11 +37,14 @@ test_interfaces([
|
||||||
"FormData",
|
"FormData",
|
||||||
"Headers",
|
"Headers",
|
||||||
"History",
|
"History",
|
||||||
|
"ImageBitmap",
|
||||||
"ImageData",
|
"ImageData",
|
||||||
"MessageChannel",
|
"MessageChannel",
|
||||||
"MessageEvent",
|
"MessageEvent",
|
||||||
"MessagePort",
|
"MessagePort",
|
||||||
"Notification",
|
"Notification",
|
||||||
|
"OffscreenCanvas",
|
||||||
|
"OffscreenCanvasRenderingContext2D",
|
||||||
"Performance",
|
"Performance",
|
||||||
"PerformanceEntry",
|
"PerformanceEntry",
|
||||||
"PerformanceMark",
|
"PerformanceMark",
|
||||||
|
|
26
tests/wpt/mozilla/tests/shadow-dom/getrootnode-in-deeply-nested-shadow.html
vendored
Normal file
26
tests/wpt/mozilla/tests/shadow-dom/getrootnode-in-deeply-nested-shadow.html
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<!--https://github.com/servo/servo/issues/35724 -->
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
test(() => {
|
||||||
|
let original_host = document.createElement("div");
|
||||||
|
original_host.id = "original-host";
|
||||||
|
let current_host = original_host;
|
||||||
|
for (let i = 0; i < 10000; i++) {
|
||||||
|
let root = current_host.attachShadow({ mode: "open" });
|
||||||
|
let new_host = document.createElement("div");
|
||||||
|
root.appendChild(new_host);
|
||||||
|
current_host = new_host;
|
||||||
|
}
|
||||||
|
|
||||||
|
let root_of_tree = current_host.getRootNode({ composed: true });
|
||||||
|
assert_equals(root_of_tree.id, "original-host");
|
||||||
|
}, "Calling Node.getRootNode in a deeply nested shadow tree must return the correct result without crashing");
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue