mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Set descendant's attribute's owner document in Node::adopt (#35076)
* Set descendant's attribute's owner document in Node::adopt Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Add test that adopting an element into a new doc updates the attribute' owner docs 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
dabe162d44
commit
c070372d1e
4 changed files with 38 additions and 7 deletions
|
@ -160,6 +160,7 @@ use crate::task::TaskOnce;
|
||||||
// and when the element enters or leaves a browsing context container.
|
// and when the element enters or leaves a browsing context container.
|
||||||
// https://html.spec.whatwg.org/multipage/#selector-focus
|
// https://html.spec.whatwg.org/multipage/#selector-focus
|
||||||
|
|
||||||
|
/// <https://dom.spec.whatwg.org/#element>
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub(crate) struct Element {
|
pub(crate) struct Element {
|
||||||
node: Node,
|
node: Node,
|
||||||
|
|
|
@ -1886,30 +1886,46 @@ impl Node {
|
||||||
pub(crate) fn adopt(node: &Node, document: &Document) {
|
pub(crate) fn adopt(node: &Node, document: &Document) {
|
||||||
document.add_script_and_layout_blocker();
|
document.add_script_and_layout_blocker();
|
||||||
|
|
||||||
// Step 1.
|
// Step 1. Let oldDocument be node’s node document.
|
||||||
let old_doc = node.owner_doc();
|
let old_doc = node.owner_doc();
|
||||||
old_doc.add_script_and_layout_blocker();
|
old_doc.add_script_and_layout_blocker();
|
||||||
// Step 2.
|
|
||||||
|
// Step 2. If node’s parent is non-null, then remove node.
|
||||||
node.remove_self();
|
node.remove_self();
|
||||||
// Step 3.
|
|
||||||
|
// Step 3. If document is not oldDocument:
|
||||||
if &*old_doc != document {
|
if &*old_doc != document {
|
||||||
// Step 3.1.
|
// Step 3.1. For each inclusiveDescendant in node’s shadow-including inclusive descendants:
|
||||||
for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
|
for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
|
||||||
|
// Step 3.1.1 Set inclusiveDescendant’s node document to document.
|
||||||
descendant.set_owner_doc(document);
|
descendant.set_owner_doc(document);
|
||||||
|
|
||||||
|
// Step 3.1.2 If inclusiveDescendant is an element, then set the node document of each
|
||||||
|
// attribute in inclusiveDescendant’s attribute list to document.
|
||||||
|
if let Some(element) = descendant.downcast::<Element>() {
|
||||||
|
for attribute in element.attrs().iter() {
|
||||||
|
attribute.upcast::<Node>().set_owner_doc(document);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3.2 For each inclusiveDescendant in node’s shadow-including inclusive descendants
|
||||||
|
// that is custom, enqueue a custom element callback reaction with inclusiveDescendant,
|
||||||
|
// callback name "adoptedCallback", and « oldDocument, document ».
|
||||||
for descendant in node
|
for descendant in node
|
||||||
.traverse_preorder(ShadowIncluding::Yes)
|
.traverse_preorder(ShadowIncluding::Yes)
|
||||||
.filter_map(|d| d.as_custom_element())
|
.filter_map(|d| d.as_custom_element())
|
||||||
{
|
{
|
||||||
// Step 3.2.
|
|
||||||
ScriptThread::enqueue_callback_reaction(
|
ScriptThread::enqueue_callback_reaction(
|
||||||
&descendant,
|
&descendant,
|
||||||
CallbackReaction::Adopted(old_doc.clone(), DomRoot::from_ref(document)),
|
CallbackReaction::Adopted(old_doc.clone(), DomRoot::from_ref(document)),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 3.3 For each inclusiveDescendant in node’s shadow-including inclusive descendants,
|
||||||
|
// in shadow-including tree order, run the adopting steps with inclusiveDescendant and oldDocument.
|
||||||
for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
|
for descendant in node.traverse_preorder(ShadowIncluding::Yes) {
|
||||||
// Step 3.3.
|
|
||||||
vtable_for(&descendant).adopting_steps(&old_doc);
|
vtable_for(&descendant).adopting_steps(&old_doc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
tests/wpt/meta/MANIFEST.json
vendored
2
tests/wpt/meta/MANIFEST.json
vendored
|
@ -606523,7 +606523,7 @@
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
"Node-mutation-adoptNode.html": [
|
"Node-mutation-adoptNode.html": [
|
||||||
"9c9594c07b22a4ac94b3703f8ab1711b41a759e4",
|
"812a2e4d3af326c1e73115c6fc50726bc4fc4b23",
|
||||||
[
|
[
|
||||||
null,
|
null,
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -20,4 +20,18 @@ test(() => {
|
||||||
assert_equals(div.firstChild.ownerDocument, document);
|
assert_equals(div.firstChild.ownerDocument, document);
|
||||||
}, "simple append of foreign div with text");
|
}, "simple append of foreign div with text");
|
||||||
|
|
||||||
|
test(function() {
|
||||||
|
var div = document.createElement("div");
|
||||||
|
div.id = "foobar";
|
||||||
|
|
||||||
|
assert_equals(div.ownerDocument, document);
|
||||||
|
assert_equals(div.attributes[0].ownerDocument, document);
|
||||||
|
|
||||||
|
var other_doc = document.implementation.createHTMLDocument();
|
||||||
|
other_doc.body.appendChild(div);
|
||||||
|
|
||||||
|
assert_equals(div.ownerDocument, other_doc);
|
||||||
|
assert_equals(div.attributes[0].ownerDocument, other_doc);
|
||||||
|
}, "Adopting an element into a different document update's the element's owner doc as well as the owner docs of it's attributes")
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue