Auto merge of #17614 - cbrewster:custom_element_reactions, r=jdm

Implement custom element reactions

<!-- Please describe your changes on the following line: -->
Initial work for implementing custom element reactions: https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reactions

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #17433 (github issue number if applicable).

<!-- Either: -->
- [X] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17614)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-07-17 22:58:53 -07:00 committed by GitHub
commit 7b134440fc
18 changed files with 616 additions and 262 deletions

View file

@ -30,6 +30,7 @@ use dom::bindings::str::{DOMString, USVString};
use dom::bindings::xmlname::namespace_from_domstring;
use dom::characterdata::{CharacterData, LayoutCharacterDataHelpers};
use dom::cssstylesheet::CSSStyleSheet;
use dom::customelementregistry::CallbackReaction;
use dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
use dom::documentfragment::DocumentFragment;
use dom::documenttype::DocumentType;
@ -66,6 +67,7 @@ use ref_slice::ref_slice;
use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData, SVGSVGData};
use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress};
use script_layout_interface::message::Msg;
use script_thread::ScriptThread;
use script_traits::DocumentActivity;
use script_traits::UntrustedNodeAddress;
use selectors::matching::{matches_selector_list, MatchingContext, MatchingMode};
@ -313,6 +315,10 @@ impl Node {
// e.g. when removing a <form>.
vtable_for(&&*node).unbind_from_tree(&context);
node.style_and_layout_data.get().map(|d| node.dispose(d));
// https://dom.spec.whatwg.org/#concept-node-remove step 14
if let Some(element) = node.as_custom_element() {
ScriptThread::enqueue_callback_reaction(&*element, CallbackReaction::Disconnected);
}
}
self.owner_doc().content_and_heritage_changed(self, NodeDamage::OtherNodeDamage);
@ -322,6 +328,15 @@ impl Node {
pub fn to_untrusted_node_address(&self) -> UntrustedNodeAddress {
UntrustedNodeAddress(self.reflector().get_jsobject().get() as *const c_void)
}
pub fn as_custom_element(&self) -> Option<Root<Element>> {
self.downcast::<Element>()
.and_then(|element| if element.get_custom_element_definition().is_some() {
Some(Root::from_ref(element))
} else {
None
})
}
}
pub struct QuerySelectorIterator {
@ -1401,13 +1416,20 @@ impl Node {
let old_doc = node.owner_doc();
// Step 2.
node.remove_self();
// Step 3.
if &*old_doc != document {
// Step 3.
// Step 3.1.
for descendant in node.traverse_preorder() {
descendant.set_owner_doc(document);
}
// Step 4.
for descendant in node.traverse_preorder() {
// Step 3.2.
if let Some(element) = node.as_custom_element() {
ScriptThread::enqueue_callback_reaction(&*element,
CallbackReaction::Adopted(old_doc.clone(), Root::from_ref(document)));
}
// Step 3.3.
vtable_for(&descendant).adopting_steps(&old_doc);
}
}
@ -1615,6 +1637,9 @@ impl Node {
// Step 7.1.
parent.add_child(*kid, child);
// Step 7.2: insertion steps.
if let Some(element) = kid.as_custom_element() {
ScriptThread::enqueue_callback_reaction(&*element, CallbackReaction::Connected);
}
}
if let SuppressObserver::Unsuppressed = suppress_observers {
vtable_for(&parent).children_changed(