Track custom element state

This commit is contained in:
Connor Brewster 2017-08-01 12:20:31 -06:00
parent e700006fb2
commit 9f51c7df21
6 changed files with 59 additions and 21 deletions

View file

@ -81,7 +81,7 @@ use dom::bindings::js::Root;
use dom::bindings::utils::{DOM_PROTOTYPE_SLOT, ProtoOrIfaceArray, get_proto_or_iface_array};
use dom::create::create_native_html_element;
use dom::customelementregistry::ConstructionStackEntry;
use dom::element::{Element, ElementCreator};
use dom::element::{CustomElementState, Element, ElementCreator};
use dom::htmlelement::HTMLElement;
use dom::window::Window;
use html5ever::LocalName;
@ -296,8 +296,10 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
// Step 8.2 is performed in the generated caller code.
// TODO: Step 8.3 - 8.4
// Set the element's custom element state and definition.
// Step 8.3
element.set_custom_element_state(CustomElementState::Custom);
// Step 8.4
element.set_custom_element_definition(definition.clone());
// Step 8.5

View file

@ -7,7 +7,7 @@ use dom::bindings::js::Root;
use dom::bindings::reflector::DomObject;
use dom::customelementregistry::{is_valid_custom_element_name, upgrade_element};
use dom::document::Document;
use dom::element::{CustomElementCreationMode, Element, ElementCreator};
use dom::element::{CustomElementCreationMode, CustomElementState, Element, ElementCreator};
use dom::globalscope::GlobalScope;
use dom::htmlanchorelement::HTMLAnchorElement;
use dom::htmlappletelement::HTMLAppletElement;
@ -129,7 +129,9 @@ fn create_html_element(name: QualName,
if definition.is_autonomous() {
match mode {
CustomElementCreationMode::Asynchronous => {
let result = Root::upcast(HTMLElement::new(name.local.clone(), prefix.clone(), document));
let result = Root::upcast::<Element>(
HTMLElement::new(name.local.clone(), prefix.clone(), document));
result.set_custom_element_state(CustomElementState::Undefined);
ScriptThread::enqueue_upgrade_reaction(&*result, definition);
return result;
},
@ -153,7 +155,10 @@ fn create_html_element(name: QualName,
}
// Step 6.1.2
Root::upcast(HTMLUnknownElement::new(local_name, prefix, document))
let element = Root::upcast::<Element>(
HTMLUnknownElement::new(local_name, prefix, document));
element.set_custom_element_state(CustomElementState::Failed);
element
},
};
},
@ -162,6 +167,7 @@ fn create_html_element(name: QualName,
// Steps 5.1-5.2
let element = create_native_html_element(name, prefix, document, creator);
element.set_is(definition.name.clone());
element.set_custom_element_state(CustomElementState::Undefined);
match mode {
// Step 5.3
CustomElementCreationMode::Synchronous =>
@ -174,7 +180,15 @@ fn create_html_element(name: QualName,
}
}
create_native_html_element(name, prefix, document, creator)
// Steps 7.1-7.2
let result = create_native_html_element(name.clone(), prefix, document, creator);
// Step 7.3
if is_valid_custom_element_name(&*name.local) || is.is_some() {
result.set_custom_element_state(CustomElementState::Undefined);
}
result
}
pub fn create_native_html_element(name: QualName,

View file

@ -18,7 +18,7 @@ use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::document::Document;
use dom::domexception::{DOMErrorName, DOMException};
use dom::element::Element;
use dom::element::{CustomElementState, Element};
use dom::globalscope::GlobalScope;
use dom::htmlelement::HTMLElement;
use dom::node::{document_from_node, Node, window_from_node};
@ -477,8 +477,11 @@ impl CustomElementDefinition {
/// https://html.spec.whatwg.org/multipage/#concept-upgrade-an-element
#[allow(unsafe_code)]
pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Element) {
// TODO: Steps 1-2
// Track custom element state
// Steps 1-2
let state = element.get_custom_element_state();
if state == CustomElementState::Custom || state == CustomElementState::Failed {
return;
}
// Step 3
for attr in element.attrs().iter() {
@ -504,8 +507,8 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
// Step 7 exception handling
if let Err(error) = result {
// TODO: Step 7.1
// Track custom element state
// Step 7.1
element.set_custom_element_state(CustomElementState::Failed);
// Step 7.2
element.clear_reaction_queue();
@ -520,6 +523,10 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
return;
}
// Step 8
element.set_custom_element_state(CustomElementState::Custom);
// Step 9
element.set_custom_element_definition(definition);
}

View file

@ -150,6 +150,8 @@ pub struct Element {
/// https://dom.spec.whatwg.org/#concept-element-custom-element-definition
#[ignore_heap_size_of = "Rc"]
custom_element_definition: DOMRefCell<Option<Rc<CustomElementDefinition>>>,
/// https://dom.spec.whatwg.org/#concept-element-custom-element-state
custom_element_state: Cell<CustomElementState>,
}
impl fmt::Debug for Element {
@ -179,6 +181,15 @@ pub enum CustomElementCreationMode {
Asynchronous,
}
/// https://dom.spec.whatwg.org/#concept-element-custom-element-state
#[derive(Clone, Copy, PartialEq, Eq, HeapSizeOf, JSTraceable)]
pub enum CustomElementState {
Undefined,
Failed,
Uncustomized,
Custom,
}
impl ElementCreator {
pub fn is_parser_created(&self) -> bool {
match *self {
@ -255,6 +266,7 @@ impl Element {
selector_flags: Cell::new(ElementSelectorFlags::empty()),
custom_element_reaction_queue: Default::default(),
custom_element_definition: Default::default(),
custom_element_state: Cell::new(CustomElementState::Uncustomized),
}
}
@ -289,6 +301,14 @@ impl Element {
self.is.borrow().clone()
}
pub fn set_custom_element_state(&self, state: CustomElementState) {
self.custom_element_state.set(state);
}
pub fn get_custom_element_state(&self) -> CustomElementState {
self.custom_element_state.get()
}
pub fn set_custom_element_definition(&self, definition: Rc<CustomElementDefinition>) {
*self.custom_element_definition.borrow_mut() = Some(definition);
}

View file

@ -31,9 +31,9 @@ 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, 424);
sizeof_checker!(size_htmlelement, HTMLElement, 440);
sizeof_checker!(size_div, HTMLDivElement, 440);
sizeof_checker!(size_span, HTMLSpanElement, 440);
sizeof_checker!(size_element, Element, 432);
sizeof_checker!(size_htmlelement, HTMLElement, 448);
sizeof_checker!(size_div, HTMLDivElement, 448);
sizeof_checker!(size_span, HTMLSpanElement, 448);
sizeof_checker!(size_text, Text, 216);
sizeof_checker!(size_characterdata, CharacterData, 216);

View file

@ -1,5 +0,0 @@
[Node-cloneNode.html]
type: testharness
[Inserting an element must not try to upgrade a custom element when it had already failed to upgrade once]
expected: FAIL