From 6d9d4add617e4e5ad08a65d563e9842b3cde0c7b Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Wed, 19 Jul 2017 13:34:33 -0600 Subject: [PATCH] Enqueue upgrades --- components/script/dom/create.rs | 20 ++++++-- .../script/dom/customelementregistry.rs | 32 ++++++++---- components/script/dom/node.rs | 9 ++-- ...r-uses-registry-of-owner-document.html.ini | 3 -- .../custom-elements/reaction-timing.html.ini | 5 -- .../reactions/Document.html.ini | 3 -- .../custom-elements/reactions/Node.html.ini | 3 -- .../custom-elements/reactions/Range.html.ini | 3 -- .../custom-elements/upgrading.html.ini | 50 ------------------- .../upgrading/Node-cloneNode.html.ini | 12 ----- .../upgrading-enqueue-reactions.html.ini | 3 -- .../upgrading-parser-created-element.html.ini | 3 -- 12 files changed, 43 insertions(+), 103 deletions(-) delete mode 100644 tests/wpt/metadata/custom-elements/reaction-timing.html.ini delete mode 100644 tests/wpt/metadata/custom-elements/upgrading.html.ini diff --git a/components/script/dom/create.rs b/components/script/dom/create.rs index f1895e8844e6..e70c547e3d34 100644 --- a/components/script/dom/create.rs +++ b/components/script/dom/create.rs @@ -5,7 +5,7 @@ use dom::bindings::error::{report_pending_exception, throw_dom_exception}; use dom::bindings::js::Root; use dom::bindings::reflector::DomObject; -use dom::customelementregistry::is_valid_custom_element_name; +use dom::customelementregistry::{is_valid_custom_element_name, upgrade_element}; use dom::document::Document; use dom::element::{CustomElementCreationMode, Element, ElementCreator}; use dom::globalscope::GlobalScope; @@ -81,6 +81,7 @@ use dom::htmlvideoelement::HTMLVideoElement; use dom::svgsvgelement::SVGSVGElement; use html5ever::{LocalName, Prefix, QualName}; use js::jsapi::JSAutoCompartment; +use script_thread::ScriptThread; use servo_config::prefs::PREFS; fn create_svg_element(name: QualName, @@ -127,8 +128,11 @@ fn create_html_element(name: QualName, if let Some(definition) = definition { if definition.is_autonomous() { match mode { - // TODO: Handle asynchronous CE creation. Relies on CE upgrades. - CustomElementCreationMode::Asynchronous => {}, + CustomElementCreationMode::Asynchronous => { + let result = Root::upcast(HTMLElement::new(name.local.clone(), prefix.clone(), document)); + ScriptThread::enqueue_upgrade_reaction(&*result, definition); + return result; + }, CustomElementCreationMode::Synchronous => { let local_name = name.local.clone(); return match definition.create_element(document, prefix.clone()) { @@ -155,9 +159,17 @@ fn create_html_element(name: QualName, }, } } else { + // Steps 5.1-5.2 let element = create_native_html_element(name, prefix, document, creator); element.set_is(definition.name.clone()); - // TODO: Enqueue custom element upgrade + match mode { + // Step 5.3 + CustomElementCreationMode::Synchronous => + upgrade_element(definition, &*element), + // Step 5.4 + CustomElementCreationMode::Asynchronous => + ScriptThread::enqueue_upgrade_reaction(&*element, definition), + } return element; } } diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index 45482d29c829..3f41f5da1cc2 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -9,6 +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::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods; use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior}; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; @@ -281,17 +282,28 @@ impl CustomElementRegistryMethods for CustomElementRegistry { self.element_definition_is_running.set(false); // Step 11 - let definition = CustomElementDefinition::new(name.clone(), - local_name, - constructor_, - observed_attributes, - callbacks); + let definition = Rc::new(CustomElementDefinition::new(name.clone(), + local_name.clone(), + constructor_, + observed_attributes, + callbacks)); // Step 12 - self.definitions.borrow_mut().insert(name.clone(), Rc::new(definition)); - - // TODO: Step 13, 14, 15 - // Handle custom element upgrades + self.definitions.borrow_mut().insert(name.clone(), definition.clone()); + + // Step 13 + let document = self.window.Document(); + + // Steps 14-15 + for candidate in document.upcast::().traverse_preorder().filter_map(Root::downcast::) { + let is = candidate.get_is(); + if *candidate.local_name() == local_name && + *candidate.namespace() == ns!(html) && + (extends.is_none() || is.as_ref() == Some(&name)) + { + ScriptThread::enqueue_upgrade_reaction(&*candidate, definition.clone()); + } + } // Step 16, 16.3 if let Some(promise) = self.when_defined.borrow_mut().remove(&name) { @@ -464,7 +476,7 @@ impl CustomElementDefinition { /// https://html.spec.whatwg.org/multipage/#concept-upgrade-an-element #[allow(unsafe_code)] -fn upgrade_element(definition: Rc, element: &Element) { +pub fn upgrade_element(definition: Rc, element: &Element) { // TODO: Steps 1-2 // Track custom element state diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index d6420b0a6f1e..3a978008e99b 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -30,7 +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::customelementregistry::{CallbackReaction, try_upgrade_element}; use dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument}; use dom::documentfragment::DocumentFragment; use dom::documenttype::DocumentType; @@ -1639,12 +1639,13 @@ impl Node { for descendant in kid.traverse_preorder().filter_map(Root::downcast::) { // Step 7.7.2. if descendant.is_connected() { - // Step 7.7.2.1. if descendant.get_custom_element_definition().is_some() { + // Step 7.7.2.1. ScriptThread::enqueue_callback_reaction(&*descendant, CallbackReaction::Connected); + } else { + // Step 7.7.2.2. + try_upgrade_element(&*descendant); } - // TODO: Step 7.7.2.2. - // Try to upgrade descendant. } } } diff --git a/tests/wpt/metadata/custom-elements/parser/parser-uses-registry-of-owner-document.html.ini b/tests/wpt/metadata/custom-elements/parser/parser-uses-registry-of-owner-document.html.ini index 4106ee6ebb98..aea72a43f87f 100644 --- a/tests/wpt/metadata/custom-elements/parser/parser-uses-registry-of-owner-document.html.ini +++ b/tests/wpt/metadata/custom-elements/parser/parser-uses-registry-of-owner-document.html.ini @@ -3,9 +3,6 @@ [HTML parser must not instantiate custom elements inside template elements] expected: FAIL - [HTML parser must use the registry of the content document inside an iframe] - expected: FAIL - [HTML parser must use the registry of window.document in a document created by document.implementation.createHTMLDocument()] expected: FAIL diff --git a/tests/wpt/metadata/custom-elements/reaction-timing.html.ini b/tests/wpt/metadata/custom-elements/reaction-timing.html.ini deleted file mode 100644 index 0697f701403d..000000000000 --- a/tests/wpt/metadata/custom-elements/reaction-timing.html.ini +++ /dev/null @@ -1,5 +0,0 @@ -[reaction-timing.html] - type: testharness - [Calling Node.prototype.cloneNode(false) must push a new element queue to the processing stack] - 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 c9319bdc3305..0076f82da665 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Document.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Document.html.ini @@ -1,8 +1,5 @@ [Document.html] type: testharness - [importNode on Document must construct a new custom element when importing a custom element from a template] - expected: FAIL - [execCommand on Document must enqueue a disconnected reaction when deleting a custom element from a contenteditable 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 fc8e80a9dcb7..e3396bed69fd 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Node.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Node.html.ini @@ -3,9 +3,6 @@ [cloneNode on Node must enqueue an attributeChanged reaction when cloning an element with an observed attribute] expected: FAIL - [cloneNode on Node must not enqueue an attributeChanged reaction when cloning an element with an unobserved attribute] - expected: FAIL - [cloneNode on Node must enqueue an attributeChanged reaction when cloning an element only for observed attributes] 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 678971e6eaff..37eaa10d28b1 100644 --- a/tests/wpt/metadata/custom-elements/reactions/Range.html.ini +++ b/tests/wpt/metadata/custom-elements/reactions/Range.html.ini @@ -3,9 +3,6 @@ [cloneContents on Range must enqueue an attributeChanged reaction when cloning an element with an observed attribute] expected: FAIL - [cloneContents on Range must not enqueue an attributeChanged reaction when cloning an element with an unobserved attribute] - expected: FAIL - [cloneContents on Range must enqueue an attributeChanged reaction when cloning an element only for observed attributes] expected: FAIL diff --git a/tests/wpt/metadata/custom-elements/upgrading.html.ini b/tests/wpt/metadata/custom-elements/upgrading.html.ini deleted file mode 100644 index a9bcfe9fca6d..000000000000 --- a/tests/wpt/metadata/custom-elements/upgrading.html.ini +++ /dev/null @@ -1,50 +0,0 @@ -[upgrading.html] - type: testharness - [Creating an element in the document of the template elements and inserting into the document must not enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in the document of the template elements and adopting back to a document with browsing context must enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in a new document and inserting into the document must not enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in a new document and adopting back to a document with browsing context must enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in a cloned document and inserting into the document must not enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in a cloned document and adopting back to a document with browsing context must enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in a document created by createHTMLDocument and inserting into the document must not enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in a document created by createHTMLDocument and adopting back to a document with browsing context must enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in an HTML document created by createDocument and inserting into the document must not enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in an HTML document created by createDocument and adopting back to a document with browsing context must enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in an HTML document fetched by XHR and inserting into the document must not enqueue a custom element upgrade reaction] - expected: FAIL - - [Creating an element in an HTML document fetched by XHR and adopting back to a document with browsing context must enqueue a custom element upgrade reaction] - expected: FAIL - - ["define" in the document of an iframe must not enqueue a custom element upgrade reaction on a disconnected unresolved custom element] - expected: FAIL - - [Inserting an unresolved custom element into the document of an iframe must enqueue a custom element upgrade reaction] - expected: FAIL - - ["define" in the document of an iframe must enqueue a custom element upgrade reaction on a connected unresolved custom element] - expected: FAIL - - [Adopting and inserting an unresolved custom element into the document of an iframe must enqueue a custom element upgrade reaction] - expected: FAIL - diff --git a/tests/wpt/metadata/custom-elements/upgrading/Node-cloneNode.html.ini b/tests/wpt/metadata/custom-elements/upgrading/Node-cloneNode.html.ini index 3214c6fd3b0b..2e78908601d2 100644 --- a/tests/wpt/metadata/custom-elements/upgrading/Node-cloneNode.html.ini +++ b/tests/wpt/metadata/custom-elements/upgrading/Node-cloneNode.html.ini @@ -1,17 +1,5 @@ [Node-cloneNode.html] type: testharness - [Node.prototype.cloneNode(false) must be able to clone a custom element] - expected: FAIL - - [Node.prototype.cloneNode(false) must be able to clone a custom element inside an iframe] - expected: FAIL - - [Node.prototype.cloneNode(true) must be able to clone a descendent custom element] - expected: FAIL - - [Node.prototype.cloneNode(true) must set parentNode, previousSibling, and nextSibling before upgrading custom elements] - expected: FAIL - [HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call] expected: FAIL diff --git a/tests/wpt/metadata/custom-elements/upgrading/upgrading-enqueue-reactions.html.ini b/tests/wpt/metadata/custom-elements/upgrading/upgrading-enqueue-reactions.html.ini index 6b6638f0b866..c45292cb290a 100644 --- a/tests/wpt/metadata/custom-elements/upgrading/upgrading-enqueue-reactions.html.ini +++ b/tests/wpt/metadata/custom-elements/upgrading/upgrading-enqueue-reactions.html.ini @@ -12,6 +12,3 @@ [Upgrading a custom element must enqueue attributeChangedCallback before connectedCallback] expected: FAIL - [Upgrading a custom element must not invoke attributeChangedCallback and connectedCallback when the element failed to upgrade] - expected: FAIL - diff --git a/tests/wpt/metadata/custom-elements/upgrading/upgrading-parser-created-element.html.ini b/tests/wpt/metadata/custom-elements/upgrading/upgrading-parser-created-element.html.ini index d252ad96aa17..bf6273a3516e 100644 --- a/tests/wpt/metadata/custom-elements/upgrading/upgrading-parser-created-element.html.ini +++ b/tests/wpt/metadata/custom-elements/upgrading/upgrading-parser-created-element.html.ini @@ -1,8 +1,5 @@ [upgrading-parser-created-element.html] type: testharness - [Element.prototype.createElement must add an unresolved custom element to the upgrade candidates map] - expected: FAIL - [HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself after super() call] expected: FAIL