From 901a2028f13b3e21e93114ea8ee6e58436547f00 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 19 Jun 2017 13:56:10 -0600 Subject: [PATCH 1/4] Store lifecycle callbacks when CEs are defined This implements steps 10.3 - 10.4 of the CustomElementRegistry.define steps. --- .../script/dom/customelementregistry.rs | 96 ++++++++++++++++--- .../CustomElementRegistry.html.ini | 9 -- .../custom-element-registry/define.html.ini | 48 ---------- 3 files changed, 84 insertions(+), 69 deletions(-) diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index 94f580f7be9..5437371f75c 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -26,7 +26,7 @@ use dom::window::Window; use dom_struct::dom_struct; use html5ever::{LocalName, Prefix}; use js::conversions::ToJSValConvertible; -use js::jsapi::{Construct1, IsConstructor, HandleValueArray, HandleObject}; +use js::jsapi::{Construct1, IsCallable, IsConstructor, HandleValueArray, HandleObject, MutableHandleValue}; use js::jsapi::{JS_GetProperty, JSAutoCompartment, JSContext}; use js::jsval::{JSVal, ObjectValue, UndefinedValue}; use std::cell::Cell; @@ -94,15 +94,14 @@ impl CustomElementRegistry { /// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define /// Steps 10.1, 10.2 #[allow(unsafe_code)] - fn check_prototype(&self, constructor: HandleObject) -> ErrorResult { + fn check_prototype(&self, constructor: HandleObject, prototype: MutableHandleValue) -> ErrorResult { let global_scope = self.window.upcast::(); - rooted!(in(global_scope.get_cx()) let mut prototype = UndefinedValue()); unsafe { // Step 10.1 if !JS_GetProperty(global_scope.get_cx(), constructor, b"prototype\0".as_ptr() as *const _, - prototype.handle_mut()) { + prototype) { return Err(Error::JSFailed); } @@ -113,6 +112,45 @@ impl CustomElementRegistry { } Ok(()) } + + /// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define + /// Steps 10.3, 10.4 + fn get_callbacks(&self, prototype: HandleObject) -> Fallible { + let cx = self.window.get_cx(); + + // Step 4 + Ok(LifecycleCallbacks { + connected_callback: get_callback(cx, prototype, b"connectedCallback\0")?, + disconnected_callback: get_callback(cx, prototype, b"disconnectedCallback\0")?, + adopted_callback: get_callback(cx, prototype, b"adoptedCallback\0")?, + attribute_changed_callback: get_callback(cx, prototype, b"attributeChangedCallback\0")?, + }) + } +} + +/// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define +/// Step 10.4 +#[allow(unsafe_code)] +fn get_callback(cx: *mut JSContext, prototype: HandleObject, name: &[u8]) -> Fallible>> { + rooted!(in(cx) let mut callback = UndefinedValue()); + + // Step 10.4.1 + if unsafe { !JS_GetProperty(cx, + prototype, + name.as_ptr() as *const _, + callback.handle_mut()) } { + return Err(Error::JSFailed); + } + + // Step 10.4.2 + if !callback.is_undefined() { + if !callback.is_object() || unsafe { !IsCallable(callback.to_object()) } { + return Err(Error::Type("Lifecycle callback is not callable".to_owned())); + } + Ok(Some(Function::new(cx, callback.to_object()))) + } else { + Ok(None) + } } impl CustomElementRegistryMethods for CustomElementRegistry { @@ -173,22 +211,38 @@ impl CustomElementRegistryMethods for CustomElementRegistry { self.element_definition_is_running.set(true); // Steps 10.1 - 10.2 - let result = { + rooted!(in(global_scope.get_cx()) let mut prototype = UndefinedValue()); + { let _ac = JSAutoCompartment::new(global_scope.get_cx(), constructor.get()); - self.check_prototype(constructor.handle()) + if let Err(error) = self.check_prototype(constructor.handle(), prototype.handle_mut()) { + self.element_definition_is_running.set(false); + return Err(error); + } }; - // TODO: Steps 10.3 - 10.6 - // 10.3 - 10.4 Handle lifecycle callbacks - // 10.5 - 10.6 Get observed attributes from the constructor + // Steps 10.3 - 10.4 + rooted!(in(global_scope.get_cx()) let proto_object = prototype.to_object()); + let callbacks = { + let _ac = JSAutoCompartment::new(global_scope.get_cx(), proto_object.get()); + match self.get_callbacks(proto_object.handle()) { + Ok(callbacks) => callbacks, + Err(error) => { + self.element_definition_is_running.set(false); + return Err(error); + }, + } + }; + + // TODO: Steps 10.5 - 10.6 + // Get observed attributes from the constructor self.element_definition_is_running.set(false); - result?; // Step 11 let definition = CustomElementDefinition::new(name.clone(), local_name, - constructor_); + constructor_, + callbacks); // Step 12 self.definitions.borrow_mut().insert(name.clone(), Rc::new(definition)); @@ -254,6 +308,21 @@ impl CustomElementRegistryMethods for CustomElementRegistry { } } +#[derive(HeapSizeOf, JSTraceable, Clone)] +pub struct LifecycleCallbacks { + #[ignore_heap_size_of = "Rc"] + connected_callback: Option>, + + #[ignore_heap_size_of = "Rc"] + disconnected_callback: Option>, + + #[ignore_heap_size_of = "Rc"] + adopted_callback: Option>, + + #[ignore_heap_size_of = "Rc"] + attribute_changed_callback: Option>, +} + /// https://html.spec.whatwg.org/multipage/#custom-element-definition #[derive(HeapSizeOf, JSTraceable, Clone)] pub struct CustomElementDefinition { @@ -263,14 +332,17 @@ pub struct CustomElementDefinition { #[ignore_heap_size_of = "Rc"] pub constructor: Rc, + + pub callbacks: LifecycleCallbacks, } impl CustomElementDefinition { - fn new(name: LocalName, local_name: LocalName, constructor: Rc) -> CustomElementDefinition { + fn new(name: LocalName, local_name: LocalName, constructor: Rc, callbacks: LifecycleCallbacks) -> CustomElementDefinition { CustomElementDefinition { name: name, local_name: local_name, constructor: constructor, + callbacks: callbacks, } } diff --git a/tests/wpt/metadata/custom-elements/CustomElementRegistry.html.ini b/tests/wpt/metadata/custom-elements/CustomElementRegistry.html.ini index 72117493595..cef53cf203f 100644 --- a/tests/wpt/metadata/custom-elements/CustomElementRegistry.html.ini +++ b/tests/wpt/metadata/custom-elements/CustomElementRegistry.html.ini @@ -1,14 +1,5 @@ [CustomElementRegistry.html] type: testharness - [customElements.define must get callbacks of the constructor prototype] - expected: FAIL - - [customElements.define must rethrow an exception thrown while getting callbacks on the constructor prototype] - expected: FAIL - - [customElements.define must rethrow an exception thrown while converting a callback value to Function callback type] - expected: FAIL - [customElements.define must get "observedAttributes" property on the constructor prototype when "attributeChangedCallback" is present] expected: FAIL diff --git a/tests/wpt/metadata/custom-elements/custom-element-registry/define.html.ini b/tests/wpt/metadata/custom-elements/custom-element-registry/define.html.ini index a04a32d8f5e..14558fa24b2 100644 --- a/tests/wpt/metadata/custom-elements/custom-element-registry/define.html.ini +++ b/tests/wpt/metadata/custom-elements/custom-element-registry/define.html.ini @@ -3,51 +3,3 @@ [If constructor is arrow function, should throw a TypeError] expected: FAIL - [If constructor.prototype.connectedCallback throws, should rethrow] - expected: FAIL - - [If constructor.prototype.connectedCallback is null, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.connectedCallback is object, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.connectedCallback is integer, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.disconnectedCallback throws, should rethrow] - expected: FAIL - - [If constructor.prototype.disconnectedCallback is null, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.disconnectedCallback is object, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.disconnectedCallback is integer, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.adoptedCallback throws, should rethrow] - expected: FAIL - - [If constructor.prototype.adoptedCallback is null, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.adoptedCallback is object, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.adoptedCallback is integer, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.attributeChangedCallback throws, should rethrow] - expected: FAIL - - [If constructor.prototype.attributeChangedCallback is null, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.attributeChangedCallback is object, should throw a TypeError] - expected: FAIL - - [If constructor.prototype.attributeChangedCallback is integer, should throw a TypeError] - expected: FAIL - From 596ed557d2a44174572eec28b9945f317f1310de Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 19 Jun 2017 14:34:31 -0600 Subject: [PATCH 2/4] Get observed attributes when a CE is defined Implements steps 10.5 - 10.6 of CustomElementRegistry.define --- .../script/dom/customelementregistry.rs | 67 ++++++++++++++++--- .../CustomElementRegistry.html.ini | 15 ----- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index 5437371f75c..6da43780082 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::CustomElementRegistryBinding::CustomElemen use dom::bindings::codegen::Bindings::CustomElementRegistryBinding::ElementDefinitionOptions; use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use dom::bindings::codegen::Bindings::FunctionBinding::Function; -use dom::bindings::conversions::{ConversionResult, FromJSValConvertible}; +use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior}; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, Root}; @@ -126,6 +126,33 @@ impl CustomElementRegistry { attribute_changed_callback: get_callback(cx, prototype, b"attributeChangedCallback\0")?, }) } + + /// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define + /// Step 10.6 + #[allow(unsafe_code)] + fn get_observed_attributes(&self, constructor: HandleObject) -> Fallible> { + let cx = self.window.get_cx(); + rooted!(in(cx) let mut observed_attributes = UndefinedValue()); + if unsafe { !JS_GetProperty(cx, + constructor, + b"observedAttributes\0".as_ptr() as *const _, + observed_attributes.handle_mut()) } { + return Err(Error::JSFailed); + } + + if observed_attributes.is_undefined() { + return Ok(Vec::new()); + } + + let conversion = unsafe { + FromJSValConvertible::from_jsval(cx, observed_attributes.handle(), StringificationBehavior::Default) + }; + match conversion { + Ok(ConversionResult::Success(attributes)) => Ok(attributes), + Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into())), + _ => Err(Error::JSFailed), + } + } } /// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define @@ -157,8 +184,8 @@ impl CustomElementRegistryMethods for CustomElementRegistry { #[allow(unsafe_code, unrooted_must_root)] /// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define fn Define(&self, name: DOMString, constructor_: Rc, options: &ElementDefinitionOptions) -> ErrorResult { - let global_scope = self.window.upcast::(); - rooted!(in(global_scope.get_cx()) let constructor = constructor_.callback()); + let cx = self.window.get_cx(); + rooted!(in(cx) let constructor = constructor_.callback()); let name = LocalName::from(&*name); // Step 1 @@ -211,9 +238,9 @@ impl CustomElementRegistryMethods for CustomElementRegistry { self.element_definition_is_running.set(true); // Steps 10.1 - 10.2 - rooted!(in(global_scope.get_cx()) let mut prototype = UndefinedValue()); + rooted!(in(cx) let mut prototype = UndefinedValue()); { - let _ac = JSAutoCompartment::new(global_scope.get_cx(), constructor.get()); + let _ac = JSAutoCompartment::new(cx, constructor.get()); if let Err(error) = self.check_prototype(constructor.handle(), prototype.handle_mut()) { self.element_definition_is_running.set(false); return Err(error); @@ -221,9 +248,9 @@ impl CustomElementRegistryMethods for CustomElementRegistry { }; // Steps 10.3 - 10.4 - rooted!(in(global_scope.get_cx()) let proto_object = prototype.to_object()); + rooted!(in(cx) let proto_object = prototype.to_object()); let callbacks = { - let _ac = JSAutoCompartment::new(global_scope.get_cx(), proto_object.get()); + let _ac = JSAutoCompartment::new(cx, proto_object.get()); match self.get_callbacks(proto_object.handle()) { Ok(callbacks) => callbacks, Err(error) => { @@ -233,8 +260,19 @@ impl CustomElementRegistryMethods for CustomElementRegistry { } }; - // TODO: Steps 10.5 - 10.6 - // Get observed attributes from the constructor + // Step 10.5 - 10.6 + let observed_attributes = if callbacks.attribute_changed_callback.is_some() { + let _ac = JSAutoCompartment::new(cx, constructor.get()); + match self.get_observed_attributes(constructor.handle()) { + Ok(attributes) => attributes, + Err(error) => { + self.element_definition_is_running.set(false); + return Err(error); + }, + } + } else { + Vec::new() + }; self.element_definition_is_running.set(false); @@ -242,6 +280,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry { let definition = CustomElementDefinition::new(name.clone(), local_name, constructor_, + observed_attributes, callbacks); // Step 12 @@ -333,15 +372,23 @@ pub struct CustomElementDefinition { #[ignore_heap_size_of = "Rc"] pub constructor: Rc, + pub observed_attributes: Vec, + pub callbacks: LifecycleCallbacks, } impl CustomElementDefinition { - fn new(name: LocalName, local_name: LocalName, constructor: Rc, callbacks: LifecycleCallbacks) -> CustomElementDefinition { + fn new(name: LocalName, + local_name: LocalName, + constructor: Rc, + observed_attributes: Vec, + callbacks: LifecycleCallbacks) + -> CustomElementDefinition { CustomElementDefinition { name: name, local_name: local_name, constructor: constructor, + observed_attributes: observed_attributes, callbacks: callbacks, } } diff --git a/tests/wpt/metadata/custom-elements/CustomElementRegistry.html.ini b/tests/wpt/metadata/custom-elements/CustomElementRegistry.html.ini index cef53cf203f..7b1502e90f5 100644 --- a/tests/wpt/metadata/custom-elements/CustomElementRegistry.html.ini +++ b/tests/wpt/metadata/custom-elements/CustomElementRegistry.html.ini @@ -1,20 +1,5 @@ [CustomElementRegistry.html] type: testharness - [customElements.define must get "observedAttributes" property on the constructor prototype when "attributeChangedCallback" is present] - expected: FAIL - - [customElements.define must rethrow an exception thrown while getting observedAttributes on the constructor prototype] - expected: FAIL - - [customElements.define must rethrow an exception thrown while converting the value of observedAttributes to sequence] - expected: FAIL - - [customElements.define must rethrow an exception thrown while iterating over observedAttributes to sequence] - expected: FAIL - - [customElements.define must rethrow an exception thrown while retrieving Symbol.iterator on observedAttributes] - expected: FAIL - [customElements.define must upgrade elements in the shadow-including tree order] expected: FAIL From 46659915036bb44e73e7ef2696ea9f35105f1659 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Wed, 21 Jun 2017 14:40:34 -0600 Subject: [PATCH 3/4] Support custom element callback reactions --- components/script/dom/attr.rs | 15 +- components/script/dom/create.rs | 5 +- .../script/dom/customelementregistry.rs | 202 +++++++++++++++++- components/script/dom/element.rs | 58 ++++- components/script/dom/node.rs | 29 ++- components/script/script_thread.rs | 15 ++ tests/unit/script/size_of.rs | 8 +- .../custom-elements/adopted-callback.html.ini | 45 ---- .../connected-callbacks.html.ini | 24 --- .../disconnected-callbacks.html.ini | 48 ----- .../reactions/ChildNode.html.ini | 23 -- .../reactions/Document.html.ini | 12 -- .../reactions/Element.html.ini | 12 -- .../reactions/HTMLOptionsCollection.html.ini | 9 - .../reactions/HTMLSelectElement.html.ini | 6 - .../reactions/HTMLTitleElement.html.ini | 5 - .../custom-elements/reactions/Node.html.ini | 21 -- .../reactions/ParentNode.html.ini | 14 -- .../custom-elements/reactions/Range.html.ini | 15 -- 19 files changed, 314 insertions(+), 252 deletions(-) delete mode 100644 tests/wpt/metadata/custom-elements/reactions/ChildNode.html.ini delete mode 100644 tests/wpt/metadata/custom-elements/reactions/HTMLTitleElement.html.ini delete mode 100644 tests/wpt/metadata/custom-elements/reactions/ParentNode.html.ini diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index af5f0107ae4..bf2ecd6e910 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -9,6 +9,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::js::{LayoutJS, MutNullableJS, Root, RootedReference}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; +use dom::customelementregistry::CallbackReaction; use dom::element::{AttributeMutation, Element}; use dom::mutationobserver::{Mutation, MutationObserver}; use dom::node::Node; @@ -16,6 +17,7 @@ use dom::virtualmethods::vtable_for; use dom::window::Window; use dom_struct::dom_struct; use html5ever::{Prefix, LocalName, Namespace}; +use script_thread::ScriptThread; use servo_atoms::Atom; use std::borrow::ToOwned; use std::cell::Ref; @@ -175,9 +177,20 @@ impl Attr { let name = self.local_name().clone(); let namespace = self.namespace().clone(); let old_value = DOMString::from(&**self.value()); - let mutation = Mutation::Attribute { name, namespace, old_value }; + let new_value = DOMString::from(&*value); + let mutation = Mutation::Attribute { + name: name.clone(), + namespace: namespace.clone(), + old_value: old_value.clone(), + }; + MutationObserver::queue_a_mutation_record(owner.upcast::(), mutation); + if owner.get_custom_element_definition().is_some() { + let reaction = CallbackReaction::AttributeChanged(name, Some(old_value), Some(new_value), namespace); + ScriptThread::enqueue_callback_reaction(owner, reaction); + } + assert!(Some(owner) == self.owner().r()); owner.will_mutate_attr(self); self.swap_value(&mut value); diff --git a/components/script/dom/create.rs b/components/script/dom/create.rs index e22e28a886e..5f03a3adb98 100644 --- a/components/script/dom/create.rs +++ b/components/script/dom/create.rs @@ -131,7 +131,10 @@ fn create_html_element(name: QualName, CustomElementCreationMode::Synchronous => { let local_name = name.local.clone(); return match definition.create_element(document, prefix.clone()) { - Ok(element) => element, + Ok(element) => { + element.set_custom_element_definition(definition.clone()); + element + }, Err(error) => { // Step 6. Recovering from exception. let global = GlobalScope::current().unwrap_or_else(|| document.global()); diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index 6da43780082..6077130c6c4 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::callback::CallbackContainer; +use dom::bindings::callback::{CallbackContainer, ExceptionHandling}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CustomElementRegistryBinding; use dom::bindings::codegen::Bindings::CustomElementRegistryBinding::CustomElementRegistryMethods; @@ -24,13 +24,14 @@ use dom::node::Node; use dom::promise::Promise; use dom::window::Window; use dom_struct::dom_struct; -use html5ever::{LocalName, Prefix}; +use html5ever::{LocalName, Namespace, Prefix}; use js::conversions::ToJSValConvertible; use js::jsapi::{Construct1, IsCallable, IsConstructor, HandleValueArray, HandleObject, MutableHandleValue}; -use js::jsapi::{JS_GetProperty, JSAutoCompartment, JSContext}; -use js::jsval::{JSVal, ObjectValue, UndefinedValue}; +use js::jsapi::{Heap, JS_GetProperty, JSAutoCompartment, JSContext}; +use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue}; use std::cell::Cell; -use std::collections::HashMap; +use std::collections::{HashMap, VecDeque}; +use std::ops::Deref; use std::ptr; use std::rc::Rc; @@ -449,6 +450,197 @@ impl CustomElementDefinition { } } +#[derive(HeapSizeOf, JSTraceable)] +#[must_root] +pub enum CustomElementReaction { + // TODO: Support upgrade reactions + Callback( + #[ignore_heap_size_of = "Rc"] + Rc, + Box<[Heap]> + ), +} + +impl CustomElementReaction { + /// https://html.spec.whatwg.org/multipage/#invoke-custom-element-reactions + #[allow(unsafe_code)] + pub fn invoke(&self, element: &Element) { + // Step 2.1 + match *self { + CustomElementReaction::Callback(ref callback, ref arguments) => { + let arguments = arguments.iter().map(|arg| arg.handle()).collect(); + let _ = callback.Call_(&*element, arguments, ExceptionHandling::Report); + } + } + } +} + +pub enum CallbackReaction { + Connected, + Disconnected, + Adopted(Root, Root), + AttributeChanged(LocalName, Option, Option, Namespace), +} + +/// https://html.spec.whatwg.org/multipage/#processing-the-backup-element-queue +#[derive(HeapSizeOf, JSTraceable, Eq, PartialEq, Clone, Copy)] +enum BackupElementQueueFlag { + Processing, + NotProcessing, +} + +/// https://html.spec.whatwg.org/multipage/#custom-element-reactions-stack +#[derive(HeapSizeOf, JSTraceable)] +#[must_root] +pub struct CustomElementReactionStack { + backup_queue: ElementQueue, + processing_backup_element_queue: Cell, +} + +impl CustomElementReactionStack { + pub fn new() -> CustomElementReactionStack { + CustomElementReactionStack { + backup_queue: ElementQueue::new(), + processing_backup_element_queue: Cell::new(BackupElementQueueFlag::NotProcessing), + } + } + + /// https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue + /// Step 4 + pub fn invoke_backup_element_queue(&self) { + // Step 4.1 + self.backup_queue.invoke_reactions(); + + // Step 4.2 + self.processing_backup_element_queue.set(BackupElementQueueFlag::NotProcessing); + } + + /// https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue + pub fn enqueue_element(&self, element: &Element) { + // TODO: Steps 1 - 2 + // Support multiple queues + + // Step 1.1 + self.backup_queue.append_element(element); + + // Step 1.2 + if self.processing_backup_element_queue.get() == BackupElementQueueFlag::Processing { + return; + } + + // Step 1.3 + self.processing_backup_element_queue.set(BackupElementQueueFlag::Processing); + + // Step 4 + // TODO: Invoke Microtask + + // Step 4.1 + self.backup_queue.invoke_reactions(); + + // Step 4.2 + self.processing_backup_element_queue.set(BackupElementQueueFlag::NotProcessing); + } + + /// https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction + #[allow(unsafe_code)] + pub fn enqueue_callback_reaction(&self, element: &Element, reaction: CallbackReaction) { + // Step 1 + let definition = match element.get_custom_element_definition() { + Some(definition) => definition, + None => return, + }; + + // Step 2 + let (callback, args) = match reaction { + CallbackReaction::Connected => (definition.callbacks.connected_callback.clone(), Vec::new()), + CallbackReaction::Disconnected => (definition.callbacks.disconnected_callback.clone(), Vec::new()), + CallbackReaction::Adopted(ref old_doc, ref new_doc) => { + let args = vec![Heap::default(), Heap::default()]; + args[0].set(ObjectValue(old_doc.reflector().get_jsobject().get())); + args[1].set(ObjectValue(new_doc.reflector().get_jsobject().get())); + (definition.callbacks.adopted_callback.clone(), args) + }, + CallbackReaction::AttributeChanged(local_name, old_val, val, namespace) => { + // Step 4 + if !definition.observed_attributes.iter().any(|attr| *attr == *local_name) { + return; + } + + let cx = element.global().get_cx(); + + let local_name = DOMString::from(&*local_name); + rooted!(in(cx) let mut name_value = UndefinedValue()); + unsafe { local_name.to_jsval(cx, name_value.handle_mut()); } + + rooted!(in(cx) let mut old_value = NullValue()); + if let Some(old_val) = old_val { + unsafe { old_val.to_jsval(cx, old_value.handle_mut()); } + } + + rooted!(in(cx) let mut value = NullValue()); + if let Some(val) = val { + unsafe { val.to_jsval(cx, value.handle_mut()); } + } + + let namespace = DOMString::from(&*namespace); + rooted!(in(cx) let mut namespace_value = UndefinedValue()); + unsafe { namespace.to_jsval(cx, namespace_value.handle_mut()); } + + let args = vec![Heap::default(), Heap::default(), Heap::default(), Heap::default()]; + args[0].set(name_value.get()); + args[1].set(old_value.get()); + args[2].set(value.get()); + args[3].set(namespace_value.get()); + + (definition.callbacks.attribute_changed_callback.clone(), args) + }, + }; + + // Step 3 + let callback = match callback { + Some(callback) => callback, + None => return, + }; + + // Step 5 + element.push_callback_reaction(callback, args.into_boxed_slice()); + + // Step 6 + self.enqueue_element(element); + } +} + +/// https://html.spec.whatwg.org/multipage/#element-queue +#[derive(HeapSizeOf, JSTraceable)] +#[must_root] +struct ElementQueue { + queue: DOMRefCell>>, +} + +impl ElementQueue { + fn new() -> ElementQueue { + ElementQueue { + queue: Default::default(), + } + } + + /// https://html.spec.whatwg.org/multipage/#invoke-custom-element-reactions + fn invoke_reactions(&self) { + // Steps 1-2 + while let Some(element) = self.next_element() { + element.invoke_reactions() + } + } + + fn next_element(&self) -> Option> { + self.queue.borrow_mut().pop_front().as_ref().map(JS::deref).map(Root::from_ref) + } + + fn append_element(&self, element: &Element) { + self.queue.borrow_mut().push_back(JS::from_ref(element)); + } +} + /// https://html.spec.whatwg.org/multipage/#valid-custom-element-name fn is_valid_custom_element_name(name: &str) -> bool { // Custom elment names must match: diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index a78520426e0..067549421af 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -13,6 +13,7 @@ use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::ElementBinding; use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use dom::bindings::codegen::Bindings::EventBinding::EventMethods; +use dom::bindings::codegen::Bindings::FunctionBinding::Function; use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOptions}; @@ -30,6 +31,7 @@ use dom::bindings::xmlname::{namespace_from_domstring, validate_and_extract, xml use dom::bindings::xmlname::XMLName::InvalidXMLName; use dom::characterdata::CharacterData; use dom::create::create_element; +use dom::customelementregistry::{CallbackReaction, CustomElementDefinition, CustomElementReaction}; use dom::document::{Document, LayoutDocumentHelpers}; use dom::documentfragment::DocumentFragment; use dom::domrect::DOMRect; @@ -80,11 +82,12 @@ use html5ever::serialize; use html5ever::serialize::SerializeOpts; use html5ever::serialize::TraversalScope; use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode}; -use js::jsapi::{HandleValue, JSAutoCompartment}; +use js::jsapi::{HandleValue, Heap, JSAutoCompartment}; +use js::jsval::JSVal; use net_traits::request::CorsSettings; use ref_filter_map::ref_filter_map; use script_layout_interface::message::ReflowQueryType; -use script_thread::Runnable; +use script_thread::{Runnable, ScriptThread}; use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity}; use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, MatchingMode}; use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS}; @@ -141,6 +144,11 @@ pub struct Element { /// when it has exclusive access to the element. #[ignore_heap_size_of = "bitflags defined in rust-selectors"] selector_flags: Cell, + /// https://html.spec.whatwg.org/multipage/#custom-element-reaction-queue + custom_element_reaction_queue: DOMRefCell>, + /// https://dom.spec.whatwg.org/#concept-element-custom-element-definition + #[ignore_heap_size_of = "Rc"] + custom_element_definition: DOMRefCell>>, } impl fmt::Debug for Element { @@ -244,6 +252,8 @@ impl Element { class_list: Default::default(), state: Cell::new(state), selector_flags: Cell::new(ElementSelectorFlags::empty()), + custom_element_reaction_queue: Default::default(), + custom_element_definition: Default::default(), } } @@ -278,6 +288,26 @@ impl Element { self.is.borrow().clone() } + pub fn set_custom_element_definition(&self, definition: Rc) { + *self.custom_element_definition.borrow_mut() = Some(definition); + } + + pub fn get_custom_element_definition(&self) -> Option> { + (*self.custom_element_definition.borrow()).clone() + } + + pub fn push_callback_reaction(&self, function: Rc, args: Box<[Heap]>) { + self.custom_element_reaction_queue.borrow_mut().push(CustomElementReaction::Callback(function, args)); + } + + pub fn invoke_reactions(&self) { + let mut reaction_queue = self.custom_element_reaction_queue.borrow_mut(); + for reaction in reaction_queue.iter() { + reaction.invoke(self); + } + reaction_queue.clear(); + } + // https://drafts.csswg.org/cssom-view/#css-layout-box // Elements that have a computed value of the display property // that is table-column or table-column-group @@ -1036,10 +1066,20 @@ impl Element { pub fn push_attribute(&self, attr: &Attr) { let name = attr.local_name().clone(); let namespace = attr.namespace().clone(); - let old_value = DOMString::from(&**attr.value()); - let mutation = Mutation::Attribute { name, namespace, old_value }; + let value = DOMString::from(&**attr.value()); + let mutation = Mutation::Attribute { + name: name.clone(), + namespace: namespace.clone(), + old_value: value.clone(), + }; + MutationObserver::queue_a_mutation_record(&self.node, mutation); + if self.get_custom_element_definition().is_some() { + let reaction = CallbackReaction::AttributeChanged(name, None, Some(value), namespace); + ScriptThread::enqueue_callback_reaction(self, reaction); + } + assert!(attr.GetOwnerElement().r() == Some(self)); self.will_mutate_attr(attr); self.attrs.borrow_mut().push(JS::from_ref(attr)); @@ -1171,9 +1211,17 @@ impl Element { let name = attr.local_name().clone(); let namespace = attr.namespace().clone(); let old_value = DOMString::from(&**attr.value()); - let mutation = Mutation::Attribute { name, namespace, old_value, }; + let mutation = Mutation::Attribute { + name: name.clone(), + namespace: namespace.clone(), + old_value: old_value.clone(), + }; + MutationObserver::queue_a_mutation_record(&self.node, mutation); + let reaction = CallbackReaction::AttributeChanged(name, Some(old_value), None, namespace); + ScriptThread::enqueue_callback_reaction(self, reaction); + self.attrs.borrow_mut().remove(idx); attr.set_owner(None); if attr.namespace() == &ns!() { diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index bf24682ede7..03a4ac59f16 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -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
. 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> { + self.downcast::() + .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( diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 641d761b373..1953f5691bd 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -39,6 +39,7 @@ use dom::bindings::str::DOMString; use dom::bindings::structuredclone::StructuredCloneData; use dom::bindings::trace::JSTraceable; use dom::bindings::utils::WRAP_CALLBACKS; +use dom::customelementregistry::{CallbackReaction, CustomElementReactionStack}; use dom::document::{Document, DocumentSource, FocusType, HasBrowsingContext, IsHTMLDocument, TouchEventResult}; use dom::element::Element; use dom::event::{Event, EventBubbles, EventCancelable}; @@ -510,6 +511,9 @@ pub struct ScriptThread { /// A list of nodes with in-progress CSS transitions, which roots them for the duration /// of the transition. transitioning_nodes: DOMRefCell>>, + + /// https://html.spec.whatwg.org/multipage/#custom-element-reactions-stack + custom_element_reaction_stack: CustomElementReactionStack, } /// In the event of thread panic, all data on the stack runs its destructor. However, there @@ -742,6 +746,15 @@ impl ScriptThread { let _ = window.layout_chan().send(msg); } + pub fn enqueue_callback_reaction(element:&Element, reaction: CallbackReaction) { + SCRIPT_THREAD_ROOT.with(|root| { + if let Some(script_thread) = root.get() { + let script_thread = unsafe { &*script_thread }; + script_thread.custom_element_reaction_stack.enqueue_callback_reaction(element, reaction); + } + }) + } + /// Creates a new script thread. pub fn new(state: InitialScriptState, port: Receiver, @@ -827,6 +840,8 @@ impl ScriptThread { docs_with_no_blocking_loads: Default::default(), transitioning_nodes: Default::default(), + + custom_element_reaction_stack: CustomElementReactionStack::new(), } } diff --git a/tests/unit/script/size_of.rs b/tests/unit/script/size_of.rs index c4d5c939663..4fecfe1f5cf 100644 --- a/tests/unit/script/size_of.rs +++ b/tests/unit/script/size_of.rs @@ -31,10 +31,10 @@ macro_rules! sizeof_checker ( // Update the sizes here sizeof_checker!(size_event_target, EventTarget, 40); sizeof_checker!(size_node, Node, 184); -sizeof_checker!(size_element, Element, 376); -sizeof_checker!(size_htmlelement, HTMLElement, 392); -sizeof_checker!(size_div, HTMLDivElement, 392); -sizeof_checker!(size_span, HTMLSpanElement, 392); +sizeof_checker!(size_element, Element, 424); +sizeof_checker!(size_htmlelement, HTMLElement, 440); +sizeof_checker!(size_div, HTMLDivElement, 440); +sizeof_checker!(size_span, HTMLSpanElement, 440); sizeof_checker!(size_text, Text, 216); sizeof_checker!(size_characterdata, CharacterData, 216); sizeof_checker!(size_servothreadsafelayoutnode, ServoThreadSafeLayoutNode, 16); diff --git a/tests/wpt/metadata/custom-elements/adopted-callback.html.ini b/tests/wpt/metadata/custom-elements/adopted-callback.html.ini index 6e0ecac11eb..c823a05e4ec 100644 --- a/tests/wpt/metadata/custom-elements/adopted-callback.html.ini +++ b/tests/wpt/metadata/custom-elements/adopted-callback.html.ini @@ -1,14 +1,5 @@ [adopted-callback.html] type: testharness - [Inserting a custom element into the owner document must not enqueue and invoke adoptedCallback] - expected: FAIL - - [Inserting a custom element into the document of the template elements must enqueue and invoke adoptedCallback] - expected: FAIL - - [Moving a custom element from the owner document into the document of the template elements must enqueue and invoke adoptedCallback] - expected: FAIL - [Inserting an ancestor of custom element into the document of the template elements must enqueue and invoke adoptedCallback] expected: FAIL @@ -27,12 +18,6 @@ [Inserting a custom element into a detached shadow tree that belongs to the document of the template elements must enqueue and invoke adoptedCallback] expected: FAIL - [Inserting a custom element into a new document must enqueue and invoke adoptedCallback] - expected: FAIL - - [Moving a custom element from the owner document into a new document must enqueue and invoke adoptedCallback] - expected: FAIL - [Inserting an ancestor of custom element into a new document must enqueue and invoke adoptedCallback] expected: FAIL @@ -51,12 +36,6 @@ [Inserting a custom element into a detached shadow tree that belongs to a new document must enqueue and invoke adoptedCallback] expected: FAIL - [Inserting a custom element into a cloned document must enqueue and invoke adoptedCallback] - expected: FAIL - - [Moving a custom element from the owner document into a cloned document must enqueue and invoke adoptedCallback] - expected: FAIL - [Inserting an ancestor of custom element into a cloned document must enqueue and invoke adoptedCallback] expected: FAIL @@ -75,12 +54,6 @@ [Inserting a custom element into a detached shadow tree that belongs to a cloned document must enqueue and invoke adoptedCallback] expected: FAIL - [Inserting a custom element into a document created by createHTMLDocument must enqueue and invoke adoptedCallback] - expected: FAIL - - [Moving a custom element from the owner document into a document created by createHTMLDocument must enqueue and invoke adoptedCallback] - expected: FAIL - [Inserting an ancestor of custom element into a document created by createHTMLDocument must enqueue and invoke adoptedCallback] expected: FAIL @@ -99,12 +72,6 @@ [Inserting a custom element into a detached shadow tree that belongs to a document created by createHTMLDocument must enqueue and invoke adoptedCallback] expected: FAIL - [Inserting a custom element into an HTML document created by createDocument must enqueue and invoke adoptedCallback] - expected: FAIL - - [Moving a custom element from the owner document into an HTML document created by createDocument must enqueue and invoke adoptedCallback] - expected: FAIL - [Inserting an ancestor of custom element into an HTML document created by createDocument must enqueue and invoke adoptedCallback] expected: FAIL @@ -123,12 +90,6 @@ [Inserting a custom element into a detached shadow tree that belongs to an HTML document created by createDocument must enqueue and invoke adoptedCallback] expected: FAIL - [Inserting a custom element into the document of an iframe must enqueue and invoke adoptedCallback] - expected: FAIL - - [Moving a custom element from the owner document into the document of an iframe must enqueue and invoke adoptedCallback] - expected: FAIL - [Inserting an ancestor of custom element into the document of an iframe must enqueue and invoke adoptedCallback] expected: FAIL @@ -147,12 +108,6 @@ [Inserting a custom element into a detached shadow tree that belongs to the document of an iframe must enqueue and invoke adoptedCallback] expected: FAIL - [Inserting a custom element into an HTML document fetched by XHR must enqueue and invoke adoptedCallback] - expected: FAIL - - [Moving a custom element from the owner document into an HTML document fetched by XHR must enqueue and invoke adoptedCallback] - expected: FAIL - [Inserting an ancestor of custom element into an HTML document fetched by XHR must enqueue and invoke adoptedCallback] expected: FAIL diff --git a/tests/wpt/metadata/custom-elements/connected-callbacks.html.ini b/tests/wpt/metadata/custom-elements/connected-callbacks.html.ini index adb9b9c8072..656964b574c 100644 --- a/tests/wpt/metadata/custom-elements/connected-callbacks.html.ini +++ b/tests/wpt/metadata/custom-elements/connected-callbacks.html.ini @@ -1,8 +1,5 @@ [connected-callbacks.html] type: testharness - [Inserting a custom element into the document must enqueue and invoke connectedCallback] - expected: FAIL - [Inserting an ancestor of custom element into the document must enqueue and invoke connectedCallback] expected: FAIL @@ -15,9 +12,6 @@ [Inserting a custom element into a detached shadow tree that belongs to the document must not enqueue and invoke connectedCallback] expected: FAIL - [Inserting a custom element into the document of the template elements must enqueue and invoke connectedCallback] - expected: FAIL - [Inserting an ancestor of custom element into the document of the template elements must enqueue and invoke connectedCallback] expected: FAIL @@ -30,9 +24,6 @@ [Inserting a custom element into a detached shadow tree that belongs to the document of the template elements must not enqueue and invoke connectedCallback] expected: FAIL - [Inserting a custom element into a new document must enqueue and invoke connectedCallback] - expected: FAIL - [Inserting an ancestor of custom element into a new document must enqueue and invoke connectedCallback] expected: FAIL @@ -45,9 +36,6 @@ [Inserting a custom element into a detached shadow tree that belongs to a new document must not enqueue and invoke connectedCallback] expected: FAIL - [Inserting a custom element into a cloned document must enqueue and invoke connectedCallback] - expected: FAIL - [Inserting an ancestor of custom element into a cloned document must enqueue and invoke connectedCallback] expected: FAIL @@ -60,9 +48,6 @@ [Inserting a custom element into a detached shadow tree that belongs to a cloned document must not enqueue and invoke connectedCallback] expected: FAIL - [Inserting a custom element into a document created by createHTMLDocument must enqueue and invoke connectedCallback] - expected: FAIL - [Inserting an ancestor of custom element into a document created by createHTMLDocument must enqueue and invoke connectedCallback] expected: FAIL @@ -75,9 +60,6 @@ [Inserting a custom element into a detached shadow tree that belongs to a document created by createHTMLDocument must not enqueue and invoke connectedCallback] expected: FAIL - [Inserting a custom element into an HTML document created by createDocument must enqueue and invoke connectedCallback] - expected: FAIL - [Inserting an ancestor of custom element into an HTML document created by createDocument must enqueue and invoke connectedCallback] expected: FAIL @@ -90,9 +72,6 @@ [Inserting a custom element into a detached shadow tree that belongs to an HTML document created by createDocument must not enqueue and invoke connectedCallback] expected: FAIL - [Inserting a custom element into the document of an iframe must enqueue and invoke connectedCallback] - expected: FAIL - [Inserting an ancestor of custom element into the document of an iframe must enqueue and invoke connectedCallback] expected: FAIL @@ -105,9 +84,6 @@ [Inserting a custom element into a detached shadow tree that belongs to the document of an iframe must not enqueue and invoke connectedCallback] expected: FAIL - [Inserting a custom element into an HTML document fetched by XHR must enqueue and invoke connectedCallback] - expected: FAIL - [Inserting an ancestor of custom element into an HTML document fetched by XHR must enqueue and invoke connectedCallback] expected: FAIL diff --git a/tests/wpt/metadata/custom-elements/disconnected-callbacks.html.ini b/tests/wpt/metadata/custom-elements/disconnected-callbacks.html.ini index 7b713889aa1..55ac810a899 100644 --- a/tests/wpt/metadata/custom-elements/disconnected-callbacks.html.ini +++ b/tests/wpt/metadata/custom-elements/disconnected-callbacks.html.ini @@ -1,11 +1,5 @@ [disconnected-callbacks.html] type: testharness - [Removing a custom element from the document must enqueue and invoke disconnectedCallback] - expected: FAIL - - [Removing an ancestor of custom element from the document must enqueue and invoke disconnectedCallback] - expected: FAIL - [Removing a custom element from a shadow tree in the document must enqueue and invoke disconnectedCallback] expected: FAIL @@ -15,12 +9,6 @@ [Removing a custom element from a detached shadow tree that belongs to the document must not enqueue and invoke disconnectedCallback] expected: FAIL - [Removing a custom element from the document of the template elements must enqueue and invoke disconnectedCallback] - expected: FAIL - - [Removing an ancestor of custom element from the document of the template elements must enqueue and invoke disconnectedCallback] - expected: FAIL - [Removing a custom element from a shadow tree in the document of the template elements must enqueue and invoke disconnectedCallback] expected: FAIL @@ -30,12 +18,6 @@ [Removing a custom element from a detached shadow tree that belongs to the document of the template elements must not enqueue and invoke disconnectedCallback] expected: FAIL - [Removing a custom element from a new document must enqueue and invoke disconnectedCallback] - expected: FAIL - - [Removing an ancestor of custom element from a new document must enqueue and invoke disconnectedCallback] - expected: FAIL - [Removing a custom element from a shadow tree in a new document must enqueue and invoke disconnectedCallback] expected: FAIL @@ -45,12 +27,6 @@ [Removing a custom element from a detached shadow tree that belongs to a new document must not enqueue and invoke disconnectedCallback] expected: FAIL - [Removing a custom element from a cloned document must enqueue and invoke disconnectedCallback] - expected: FAIL - - [Removing an ancestor of custom element from a cloned document must enqueue and invoke disconnectedCallback] - expected: FAIL - [Removing a custom element from a shadow tree in a cloned document must enqueue and invoke disconnectedCallback] expected: FAIL @@ -60,12 +36,6 @@ [Removing a custom element from a detached shadow tree that belongs to a cloned document must not enqueue and invoke disconnectedCallback] expected: FAIL - [Removing a custom element from a document created by createHTMLDocument must enqueue and invoke disconnectedCallback] - expected: FAIL - - [Removing an ancestor of custom element from a document created by createHTMLDocument must enqueue and invoke disconnectedCallback] - expected: FAIL - [Removing a custom element from a shadow tree in a document created by createHTMLDocument must enqueue and invoke disconnectedCallback] expected: FAIL @@ -75,12 +45,6 @@ [Removing a custom element from a detached shadow tree that belongs to a document created by createHTMLDocument must not enqueue and invoke disconnectedCallback] expected: FAIL - [Removing a custom element from an HTML document created by createDocument must enqueue and invoke disconnectedCallback] - expected: FAIL - - [Removing an ancestor of custom element from an HTML document created by createDocument must enqueue and invoke disconnectedCallback] - expected: FAIL - [Removing a custom element from a shadow tree in an HTML document created by createDocument must enqueue and invoke disconnectedCallback] expected: FAIL @@ -90,12 +54,6 @@ [Removing a custom element from a detached shadow tree that belongs to an HTML document created by createDocument must not enqueue and invoke disconnectedCallback] expected: FAIL - [Removing a custom element from the document of an iframe must enqueue and invoke disconnectedCallback] - expected: FAIL - - [Removing an ancestor of custom element from the document of an iframe must enqueue and invoke disconnectedCallback] - expected: FAIL - [Removing a custom element from a shadow tree in the document of an iframe must enqueue and invoke disconnectedCallback] expected: FAIL @@ -105,12 +63,6 @@ [Removing a custom element from a detached shadow tree that belongs to the document of an iframe must not enqueue and invoke disconnectedCallback] expected: FAIL - [Removing a custom element from an HTML document fetched by XHR must enqueue and invoke disconnectedCallback] - expected: FAIL - - [Removing an ancestor of custom element from an HTML document fetched by XHR must enqueue and invoke disconnectedCallback] - expected: FAIL - [Removing a custom element from a shadow tree in an HTML document fetched by XHR must enqueue and invoke disconnectedCallback] expected: FAIL diff --git a/tests/wpt/metadata/custom-elements/reactions/ChildNode.html.ini b/tests/wpt/metadata/custom-elements/reactions/ChildNode.html.ini deleted file mode 100644 index 4265435e3b6..00000000000 --- a/tests/wpt/metadata/custom-elements/reactions/ChildNode.html.ini +++ /dev/null @@ -1,23 +0,0 @@ -[ChildNode.html] - type: testharness - [before on ChildNode must enqueue a connected reaction] - expected: FAIL - - [before on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - - [after on ChildNode must enqueue a connected reaction] - expected: FAIL - - [after on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - - [replaceWith on ChildNode must enqueue a connected reaction] - expected: FAIL - - [replaceWith on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - - [replaceWith on ChildNode must enqueue a disconnected reaction] - expected: FAIL - diff --git a/tests/wpt/metadata/custom-elements/reactions/Document.html.ini b/tests/wpt/metadata/custom-elements/reactions/Document.html.ini index 07e68da69b7..10b24674200 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Document.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Document.html.ini @@ -1,14 +1,8 @@ [Document.html] type: testharness - [adoptNode on Document must enqueue an adopted reaction when importing a custom element] - expected: FAIL - [execCommand on Document must enqueue a disconnected reaction when deleting a custom element from a contenteditable element] expected: FAIL - [title on Document must enqueue disconnectedCallback when removing a custom element] - expected: FAIL - [body on Document must enqueue disconnectedCallback when removing a custom element] expected: FAIL @@ -21,15 +15,9 @@ [write on Document must enqueue disconnectedCallback when removing a custom element] expected: FAIL - [write on Document must enqueue connectedCallback after constructing a custom element] - expected: FAIL - [writeln on Document must enqueue disconnectedCallback when removing a custom element] expected: FAIL - [writeln on Document must enqueue connectedCallback after constructing a custom element] - expected: FAIL - [importNode on Document must construct a new custom element when importing a custom element from a template] expected: FAIL diff --git a/tests/wpt/metadata/custom-elements/reactions/Element.html.ini b/tests/wpt/metadata/custom-elements/reactions/Element.html.ini index fa721851548..bf8e6529090 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Element.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Element.html.ini @@ -51,30 +51,18 @@ [removeAttributeNode on Element must enqueue an attributeChanged reaction when removing an existing attribute] expected: FAIL - [insertAdjacentElement on Element must enqueue a connected reaction] - expected: FAIL - - [insertAdjacentElement on Element must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - [innerHTML on Element must enqueue a connected reaction for a newly constructed custom element] expected: FAIL [innerHTML on Element must enqueue a attributeChanged reaction for a newly constructed custom element] expected: FAIL - [innerHTML on Element must enqueue a disconnected reaction] - expected: FAIL - [outerHTML on Element must enqueue a connected reaction for a newly constructed custom element] expected: FAIL [outerHTML on Element must enqueue a attributeChanged reaction for a newly constructed custom element] expected: FAIL - [outerHTML on Element must enqueue a disconnected reaction] - expected: FAIL - [insertAdjacentHTML on Element must enqueue a connected reaction for a newly constructed custom element] expected: FAIL diff --git a/tests/wpt/metadata/custom-elements/reactions/HTMLOptionsCollection.html.ini b/tests/wpt/metadata/custom-elements/reactions/HTMLOptionsCollection.html.ini index bf68ae508ac..88525dabcb3 100644 --- a/tests/wpt/metadata/custom-elements/reactions/HTMLOptionsCollection.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/HTMLOptionsCollection.html.ini @@ -1,17 +1,8 @@ [HTMLOptionsCollection.html] type: testharness - [length on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element] - expected: FAIL - [The indexed setter on HTMLOptionsCollection must enqueue connectedCallback when inserting a custom element] expected: FAIL - [The indexed setter on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element] - expected: FAIL - [add on HTMLOptionsCollection must enqueue connectedCallback when inserting a custom element] expected: FAIL - [remove on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element] - expected: FAIL - diff --git a/tests/wpt/metadata/custom-elements/reactions/HTMLSelectElement.html.ini b/tests/wpt/metadata/custom-elements/reactions/HTMLSelectElement.html.ini index b2efcf5e449..a7965cea05f 100644 --- a/tests/wpt/metadata/custom-elements/reactions/HTMLSelectElement.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/HTMLSelectElement.html.ini @@ -1,8 +1,5 @@ [HTMLSelectElement.html] type: testharness - [length on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element] - expected: FAIL - [The indexed setter on HTMLSelectElement must enqueue connectedCallback when inserting a custom element] expected: FAIL @@ -12,6 +9,3 @@ [add on HTMLSelectElement must enqueue connectedCallback when inserting a custom element] expected: FAIL - [remove on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element] - expected: FAIL - diff --git a/tests/wpt/metadata/custom-elements/reactions/HTMLTitleElement.html.ini b/tests/wpt/metadata/custom-elements/reactions/HTMLTitleElement.html.ini deleted file mode 100644 index 07e9cb95fc1..00000000000 --- a/tests/wpt/metadata/custom-elements/reactions/HTMLTitleElement.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[HTMLTitleElement.html] - type: testharness - [text on HTMLTitleElement must enqueue disconnectedCallback when removing a custom element] - expected: FAIL - diff --git a/tests/wpt/metadata/custom-elements/reactions/Node.html.ini b/tests/wpt/metadata/custom-elements/reactions/Node.html.ini index a5be84ba635..19256a1f7b7 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Node.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Node.html.ini @@ -15,24 +15,3 @@ [cloneNode on Node must enqueue an attributeChanged reaction when cloning an element only for observed attributes] expected: FAIL - [insertBefore on ChildNode must enqueue a connected reaction] - expected: FAIL - - [insertBefore on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - - [appendChild on ChildNode must enqueue a connected reaction] - expected: FAIL - - [appendChild on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - - [replaceChild on ChildNode must enqueue a connected reaction] - expected: FAIL - - [replaceChild on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - - [removeChild on ChildNode must enqueue a disconnected reaction] - expected: FAIL - diff --git a/tests/wpt/metadata/custom-elements/reactions/ParentNode.html.ini b/tests/wpt/metadata/custom-elements/reactions/ParentNode.html.ini deleted file mode 100644 index ccdf5de7cf0..00000000000 --- a/tests/wpt/metadata/custom-elements/reactions/ParentNode.html.ini +++ /dev/null @@ -1,14 +0,0 @@ -[ParentNode.html] - type: testharness - [prepend on ParentNode must enqueue a connected reaction] - expected: FAIL - - [prepend on ParentNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - - [append on ParentNode must enqueue a connected reaction] - expected: FAIL - - [append on ParentNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - diff --git a/tests/wpt/metadata/custom-elements/reactions/Range.html.ini b/tests/wpt/metadata/custom-elements/reactions/Range.html.ini index 5a3c020f1bc..662e10a7c43 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Range.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Range.html.ini @@ -1,8 +1,5 @@ [Range.html] type: testharness - [deleteContents on Range must enqueue a disconnected reaction] - expected: FAIL - [extractContents on Range must enqueue a disconnected reaction] expected: FAIL @@ -15,18 +12,6 @@ [cloneContents on Range must enqueue an attributeChanged reaction when cloning an element only for observed attributes] expected: FAIL - [insertNode on Range must enqueue a connected reaction] - expected: FAIL - - [insertNode on Range must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - - [surroundContents on Range must enqueue a connected reaction] - expected: FAIL - - [surroundContents on Range must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] - expected: FAIL - [createContextualFragment on Range must construct a custom element] expected: FAIL From 9b587a4f2d1d8abc70fa6d6220ac31e6dac32c72 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 7 Jul 2017 15:18:23 -0600 Subject: [PATCH 4/4] Invoke backup element queue via a microtask --- .../script/dom/customelementregistry.rs | 11 ++--- components/script/microtask.rs | 5 ++ components/script/script_thread.rs | 9 ++++ .../custom-elements/adopted-callback.html.ini | 45 +++++++++++++++++ .../connected-callbacks.html.ini | 24 ++++++++++ .../disconnected-callbacks.html.ini | 48 +++++++++++++++++++ .../reactions/ChildNode.html.ini | 23 +++++++++ .../reactions/Document.html.ini | 12 +++++ .../reactions/Element.html.ini | 12 +++++ .../reactions/HTMLOptionsCollection.html.ini | 9 ++++ .../reactions/HTMLSelectElement.html.ini | 6 +++ .../reactions/HTMLTitleElement.html.ini | 5 ++ .../custom-elements/reactions/Node.html.ini | 21 ++++++++ .../reactions/ParentNode.html.ini | 14 ++++++ .../custom-elements/reactions/Range.html.ini | 15 ++++++ 15 files changed, 252 insertions(+), 7 deletions(-) create mode 100644 tests/wpt/metadata/custom-elements/reactions/ChildNode.html.ini create mode 100644 tests/wpt/metadata/custom-elements/reactions/HTMLTitleElement.html.ini create mode 100644 tests/wpt/metadata/custom-elements/reactions/ParentNode.html.ini diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index 6077130c6c4..0d151abb127 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -29,6 +29,8 @@ use js::conversions::ToJSValConvertible; use js::jsapi::{Construct1, IsCallable, IsConstructor, HandleValueArray, HandleObject, MutableHandleValue}; use js::jsapi::{Heap, JS_GetProperty, JSAutoCompartment, JSContext}; use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue}; +use microtask::Microtask; +use script_thread::ScriptThread; use std::cell::Cell; use std::collections::{HashMap, VecDeque}; use std::ops::Deref; @@ -532,13 +534,7 @@ impl CustomElementReactionStack { self.processing_backup_element_queue.set(BackupElementQueueFlag::Processing); // Step 4 - // TODO: Invoke Microtask - - // Step 4.1 - self.backup_queue.invoke_reactions(); - - // Step 4.2 - self.processing_backup_element_queue.set(BackupElementQueueFlag::NotProcessing); + ScriptThread::enqueue_microtask(Microtask::CustomElementReaction); } /// https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction @@ -630,6 +626,7 @@ impl ElementQueue { while let Some(element) = self.next_element() { element.invoke_reactions() } + self.queue.borrow_mut().clear(); } fn next_element(&self) -> Option> { diff --git a/components/script/microtask.rs b/components/script/microtask.rs index 5028f2849da..a25b7ff3719 100644 --- a/components/script/microtask.rs +++ b/components/script/microtask.rs @@ -15,6 +15,7 @@ use dom::htmlimageelement::ImageElementMicrotask; use dom::htmlmediaelement::MediaElementMicrotask; use dom::mutationobserver::MutationObserver; use msg::constellation_msg::PipelineId; +use script_thread::ScriptThread; use std::cell::Cell; use std::mem; use std::rc::Rc; @@ -33,6 +34,7 @@ pub enum Microtask { Promise(EnqueuedPromiseCallback), MediaElement(MediaElementMicrotask), ImageElement(ImageElementMicrotask), + CustomElementReaction, NotifyMutationObservers, } @@ -87,6 +89,9 @@ impl MicrotaskQueue { Microtask::ImageElement(ref task) => { task.handler(); }, + Microtask::CustomElementReaction => { + ScriptThread::invoke_backup_element_queue(); + }, Microtask::NotifyMutationObservers => { MutationObserver::notify_mutation_observers(); } diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 1953f5691bd..7e171a1f048 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -755,6 +755,15 @@ impl ScriptThread { }) } + pub fn invoke_backup_element_queue() { + SCRIPT_THREAD_ROOT.with(|root| { + if let Some(script_thread) = root.get() { + let script_thread = unsafe { &*script_thread }; + script_thread.custom_element_reaction_stack.invoke_backup_element_queue(); + } + }) + } + /// Creates a new script thread. pub fn new(state: InitialScriptState, port: Receiver, diff --git a/tests/wpt/metadata/custom-elements/adopted-callback.html.ini b/tests/wpt/metadata/custom-elements/adopted-callback.html.ini index c823a05e4ec..7d4f4439a5b 100644 --- a/tests/wpt/metadata/custom-elements/adopted-callback.html.ini +++ b/tests/wpt/metadata/custom-elements/adopted-callback.html.ini @@ -129,3 +129,48 @@ [Custom Elements: adoptedCallback] expected: FAIL + [Inserting a custom element into the owner document must not enqueue and invoke adoptedCallback] + expected: FAIL + + [Inserting a custom element into the document of the template elements must enqueue and invoke adoptedCallback] + expected: FAIL + + [Moving a custom element from the owner document into the document of the template elements must enqueue and invoke adoptedCallback] + expected: FAIL + + [Inserting a custom element into a new document must enqueue and invoke adoptedCallback] + expected: FAIL + + [Moving a custom element from the owner document into a new document must enqueue and invoke adoptedCallback] + expected: FAIL + + [Inserting a custom element into a cloned document must enqueue and invoke adoptedCallback] + expected: FAIL + + [Moving a custom element from the owner document into a cloned document must enqueue and invoke adoptedCallback] + expected: FAIL + + [Inserting a custom element into a document created by createHTMLDocument must enqueue and invoke adoptedCallback] + expected: FAIL + + [Moving a custom element from the owner document into a document created by createHTMLDocument must enqueue and invoke adoptedCallback] + expected: FAIL + + [Inserting a custom element into an HTML document created by createDocument must enqueue and invoke adoptedCallback] + expected: FAIL + + [Moving a custom element from the owner document into an HTML document created by createDocument must enqueue and invoke adoptedCallback] + expected: FAIL + + [Inserting a custom element into the document of an iframe must enqueue and invoke adoptedCallback] + expected: FAIL + + [Moving a custom element from the owner document into the document of an iframe must enqueue and invoke adoptedCallback] + expected: FAIL + + [Inserting a custom element into an HTML document fetched by XHR must enqueue and invoke adoptedCallback] + expected: FAIL + + [Moving a custom element from the owner document into an HTML document fetched by XHR must enqueue and invoke adoptedCallback] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/connected-callbacks.html.ini b/tests/wpt/metadata/custom-elements/connected-callbacks.html.ini index 656964b574c..457ec15b357 100644 --- a/tests/wpt/metadata/custom-elements/connected-callbacks.html.ini +++ b/tests/wpt/metadata/custom-elements/connected-callbacks.html.ini @@ -99,3 +99,27 @@ [Custom Elements: connectedCallback] expected: FAIL + [Inserting a custom element into the document must enqueue and invoke connectedCallback] + expected: FAIL + + [Inserting a custom element into the document of the template elements must enqueue and invoke connectedCallback] + expected: FAIL + + [Inserting a custom element into a new document must enqueue and invoke connectedCallback] + expected: FAIL + + [Inserting a custom element into a cloned document must enqueue and invoke connectedCallback] + expected: FAIL + + [Inserting a custom element into a document created by createHTMLDocument must enqueue and invoke connectedCallback] + expected: FAIL + + [Inserting a custom element into an HTML document created by createDocument must enqueue and invoke connectedCallback] + expected: FAIL + + [Inserting a custom element into the document of an iframe must enqueue and invoke connectedCallback] + expected: FAIL + + [Inserting a custom element into an HTML document fetched by XHR must enqueue and invoke connectedCallback] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/disconnected-callbacks.html.ini b/tests/wpt/metadata/custom-elements/disconnected-callbacks.html.ini index 55ac810a899..caa481be682 100644 --- a/tests/wpt/metadata/custom-elements/disconnected-callbacks.html.ini +++ b/tests/wpt/metadata/custom-elements/disconnected-callbacks.html.ini @@ -75,3 +75,51 @@ [Custom Elements: disconnectedCallback] expected: FAIL + [Removing a custom element from the document must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing an ancestor of custom element from the document must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing a custom element from the document of the template elements must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing an ancestor of custom element from the document of the template elements must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing a custom element from a new document must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing an ancestor of custom element from a new document must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing a custom element from a cloned document must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing an ancestor of custom element from a cloned document must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing a custom element from a document created by createHTMLDocument must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing an ancestor of custom element from a document created by createHTMLDocument must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing a custom element from an HTML document created by createDocument must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing an ancestor of custom element from an HTML document created by createDocument must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing a custom element from the document of an iframe must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing an ancestor of custom element from the document of an iframe must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing a custom element from an HTML document fetched by XHR must enqueue and invoke disconnectedCallback] + expected: FAIL + + [Removing an ancestor of custom element from an HTML document fetched by XHR must enqueue and invoke disconnectedCallback] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/reactions/ChildNode.html.ini b/tests/wpt/metadata/custom-elements/reactions/ChildNode.html.ini new file mode 100644 index 00000000000..4265435e3b6 --- /dev/null +++ b/tests/wpt/metadata/custom-elements/reactions/ChildNode.html.ini @@ -0,0 +1,23 @@ +[ChildNode.html] + type: testharness + [before on ChildNode must enqueue a connected reaction] + expected: FAIL + + [before on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + + [after on ChildNode must enqueue a connected reaction] + expected: FAIL + + [after on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + + [replaceWith on ChildNode must enqueue a connected reaction] + expected: FAIL + + [replaceWith on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + + [replaceWith on ChildNode must enqueue a disconnected reaction] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/reactions/Document.html.ini b/tests/wpt/metadata/custom-elements/reactions/Document.html.ini index 10b24674200..bf986fdbca0 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Document.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Document.html.ini @@ -21,3 +21,15 @@ [importNode on Document must construct a new custom element when importing a custom element from a template] expected: FAIL + [adoptNode on Document must enqueue an adopted reaction when importing a custom element] + expected: FAIL + + [title on Document must enqueue disconnectedCallback when removing a custom element] + expected: FAIL + + [write on Document must enqueue connectedCallback after constructing a custom element] + expected: FAIL + + [writeln on Document must enqueue connectedCallback after constructing a custom element] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/reactions/Element.html.ini b/tests/wpt/metadata/custom-elements/reactions/Element.html.ini index bf8e6529090..d6e6402eece 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Element.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Element.html.ini @@ -69,3 +69,15 @@ [insertAdjacentHTML on Element must enqueue a attributeChanged reaction for a newly constructed custom element] expected: FAIL + [insertAdjacentElement on Element must enqueue a connected reaction] + expected: FAIL + + [insertAdjacentElement on Element must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + + [innerHTML on Element must enqueue a disconnected reaction] + expected: FAIL + + [outerHTML on Element must enqueue a disconnected reaction] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/reactions/HTMLOptionsCollection.html.ini b/tests/wpt/metadata/custom-elements/reactions/HTMLOptionsCollection.html.ini index 88525dabcb3..1a1f74719e6 100644 --- a/tests/wpt/metadata/custom-elements/reactions/HTMLOptionsCollection.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/HTMLOptionsCollection.html.ini @@ -6,3 +6,12 @@ [add on HTMLOptionsCollection must enqueue connectedCallback when inserting a custom element] expected: FAIL + [length on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element] + expected: FAIL + + [The indexed setter on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element] + expected: FAIL + + [remove on HTMLOptionsCollection must enqueue disconnectedCallback when removing a custom element] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/reactions/HTMLSelectElement.html.ini b/tests/wpt/metadata/custom-elements/reactions/HTMLSelectElement.html.ini index a7965cea05f..517deb05807 100644 --- a/tests/wpt/metadata/custom-elements/reactions/HTMLSelectElement.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/HTMLSelectElement.html.ini @@ -9,3 +9,9 @@ [add on HTMLSelectElement must enqueue connectedCallback when inserting a custom element] expected: FAIL + [length on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element] + expected: FAIL + + [remove on HTMLSelectElement must enqueue disconnectedCallback when removing a custom element] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/reactions/HTMLTitleElement.html.ini b/tests/wpt/metadata/custom-elements/reactions/HTMLTitleElement.html.ini new file mode 100644 index 00000000000..07e9cb95fc1 --- /dev/null +++ b/tests/wpt/metadata/custom-elements/reactions/HTMLTitleElement.html.ini @@ -0,0 +1,5 @@ +[HTMLTitleElement.html] + type: testharness + [text on HTMLTitleElement must enqueue disconnectedCallback when removing a custom element] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/reactions/Node.html.ini b/tests/wpt/metadata/custom-elements/reactions/Node.html.ini index 19256a1f7b7..a5be84ba635 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Node.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Node.html.ini @@ -15,3 +15,24 @@ [cloneNode on Node must enqueue an attributeChanged reaction when cloning an element only for observed attributes] expected: FAIL + [insertBefore on ChildNode must enqueue a connected reaction] + expected: FAIL + + [insertBefore on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + + [appendChild on ChildNode must enqueue a connected reaction] + expected: FAIL + + [appendChild on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + + [replaceChild on ChildNode must enqueue a connected reaction] + expected: FAIL + + [replaceChild on ChildNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + + [removeChild on ChildNode must enqueue a disconnected reaction] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/reactions/ParentNode.html.ini b/tests/wpt/metadata/custom-elements/reactions/ParentNode.html.ini new file mode 100644 index 00000000000..ccdf5de7cf0 --- /dev/null +++ b/tests/wpt/metadata/custom-elements/reactions/ParentNode.html.ini @@ -0,0 +1,14 @@ +[ParentNode.html] + type: testharness + [prepend on ParentNode must enqueue a connected reaction] + expected: FAIL + + [prepend on ParentNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + + [append on ParentNode must enqueue a connected reaction] + expected: FAIL + + [append on ParentNode must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + diff --git a/tests/wpt/metadata/custom-elements/reactions/Range.html.ini b/tests/wpt/metadata/custom-elements/reactions/Range.html.ini index 662e10a7c43..64c174992a5 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Range.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Range.html.ini @@ -15,3 +15,18 @@ [createContextualFragment on Range must construct a custom element] expected: FAIL + [deleteContents on Range must enqueue a disconnected reaction] + expected: FAIL + + [insertNode on Range must enqueue a connected reaction] + expected: FAIL + + [insertNode on Range must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL + + [surroundContents on Range must enqueue a connected reaction] + expected: FAIL + + [surroundContents on Range must enqueue a disconnected reaction, an adopted reaction, and a connected reaction when the custom element was in another document] + expected: FAIL +