mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Auto merge of #17935 - cbrewster:ce_upgrades, r=jdm
Custom element upgrades <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [X] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17935) <!-- Reviewable:end -->
This commit is contained in:
commit
a087fee4b4
30 changed files with 318 additions and 295 deletions
|
@ -188,7 +188,7 @@ impl Attr {
|
||||||
|
|
||||||
if owner.get_custom_element_definition().is_some() {
|
if owner.get_custom_element_definition().is_some() {
|
||||||
let reaction = CallbackReaction::AttributeChanged(name, Some(old_value), Some(new_value), namespace);
|
let reaction = CallbackReaction::AttributeChanged(name, Some(old_value), Some(new_value), namespace);
|
||||||
ScriptThread::enqueue_callback_reaction(owner, reaction);
|
ScriptThread::enqueue_callback_reaction(owner, reaction, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(Some(owner) == self.owner().r());
|
assert!(Some(owner) == self.owner().r());
|
||||||
|
|
|
@ -5377,7 +5377,12 @@ let result = match result {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
JS_SetPrototype(cx, result.reflector().get_jsobject(), prototype.handle());
|
rooted!(in(cx) let mut element = result.reflector().get_jsobject().get());
|
||||||
|
if !JS_WrapObject(cx, element.handle_mut()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_SetPrototype(cx, element.handle(), prototype.handle());
|
||||||
|
|
||||||
(result).to_jsval(cx, args.rval());
|
(result).to_jsval(cx, args.rval());
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -80,7 +80,8 @@ use dom::bindings::guard::Guard;
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::bindings::utils::{DOM_PROTOTYPE_SLOT, ProtoOrIfaceArray, get_proto_or_iface_array};
|
use dom::bindings::utils::{DOM_PROTOTYPE_SLOT, ProtoOrIfaceArray, get_proto_or_iface_array};
|
||||||
use dom::create::create_native_html_element;
|
use dom::create::create_native_html_element;
|
||||||
use dom::element::{Element, ElementCreator};
|
use dom::customelementregistry::ConstructionStackEntry;
|
||||||
|
use dom::element::{CustomElementState, Element, ElementCreator};
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use html5ever::LocalName;
|
use html5ever::LocalName;
|
||||||
|
@ -281,24 +282,44 @@ pub unsafe fn html_constructor<T>(window: &Window, call_args: &CallArgs) -> Fall
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 8.1
|
let entry = definition.construction_stack.borrow().last().cloned();
|
||||||
let name = QualName::new(None, ns!(html), definition.local_name.clone());
|
match entry {
|
||||||
let element = if definition.is_autonomous() {
|
// Step 8
|
||||||
Root::upcast(HTMLElement::new(name.local, None, &*document))
|
None => {
|
||||||
} else {
|
// Step 8.1
|
||||||
create_native_html_element(name, None, &*document, ElementCreator::ScriptCreated)
|
let name = QualName::new(None, ns!(html), definition.local_name.clone());
|
||||||
};
|
let element = if definition.is_autonomous() {
|
||||||
|
Root::upcast(HTMLElement::new(name.local, None, &*document))
|
||||||
|
} else {
|
||||||
|
create_native_html_element(name, None, &*document, ElementCreator::ScriptCreated)
|
||||||
|
};
|
||||||
|
|
||||||
// Step 8.2 is performed in the generated caller code.
|
// Step 8.2 is performed in the generated caller code.
|
||||||
|
|
||||||
// TODO: Step 8.3 - 8.4
|
// Step 8.3
|
||||||
// Set the element's custom element state and definition.
|
element.set_custom_element_state(CustomElementState::Custom);
|
||||||
|
|
||||||
// Step 8.5
|
// Step 8.4
|
||||||
Root::downcast(element).ok_or(Error::InvalidState)
|
element.set_custom_element_definition(definition.clone());
|
||||||
|
|
||||||
// TODO: Steps 9-13
|
// Step 8.5
|
||||||
// Custom element upgrades are not implemented yet, so these steps are unnecessary.
|
Root::downcast(element).ok_or(Error::InvalidState)
|
||||||
|
},
|
||||||
|
// Step 9
|
||||||
|
Some(ConstructionStackEntry::Element(element)) => {
|
||||||
|
// Step 11 is performed in the generated caller code.
|
||||||
|
|
||||||
|
// Step 12
|
||||||
|
let mut construction_stack = definition.construction_stack.borrow_mut();
|
||||||
|
construction_stack.pop();
|
||||||
|
construction_stack.push(ConstructionStackEntry::AlreadyConstructedMarker);
|
||||||
|
|
||||||
|
// Step 13
|
||||||
|
Root::downcast(element).ok_or(Error::InvalidState)
|
||||||
|
},
|
||||||
|
// Step 10
|
||||||
|
Some(ConstructionStackEntry::AlreadyConstructedMarker) => Err(Error::InvalidState),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_new_element_queue() {
|
pub fn push_new_element_queue() {
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
use dom::bindings::error::{report_pending_exception, throw_dom_exception};
|
use dom::bindings::error::{report_pending_exception, throw_dom_exception};
|
||||||
use dom::bindings::js::Root;
|
use dom::bindings::js::Root;
|
||||||
use dom::bindings::reflector::DomObject;
|
use dom::bindings::reflector::DomObject;
|
||||||
|
use dom::customelementregistry::{is_valid_custom_element_name, upgrade_element};
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{CustomElementCreationMode, Element, ElementCreator};
|
use dom::element::{CustomElementCreationMode, CustomElementState, Element, ElementCreator};
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::htmlanchorelement::HTMLAnchorElement;
|
use dom::htmlanchorelement::HTMLAnchorElement;
|
||||||
use dom::htmlappletelement::HTMLAppletElement;
|
use dom::htmlappletelement::HTMLAppletElement;
|
||||||
|
@ -80,6 +81,7 @@ use dom::htmlvideoelement::HTMLVideoElement;
|
||||||
use dom::svgsvgelement::SVGSVGElement;
|
use dom::svgsvgelement::SVGSVGElement;
|
||||||
use html5ever::{LocalName, Prefix, QualName};
|
use html5ever::{LocalName, Prefix, QualName};
|
||||||
use js::jsapi::JSAutoCompartment;
|
use js::jsapi::JSAutoCompartment;
|
||||||
|
use script_thread::ScriptThread;
|
||||||
use servo_config::prefs::PREFS;
|
use servo_config::prefs::PREFS;
|
||||||
|
|
||||||
fn create_svg_element(name: QualName,
|
fn create_svg_element(name: QualName,
|
||||||
|
@ -121,13 +123,18 @@ fn create_html_element(name: QualName,
|
||||||
assert!(name.ns == ns!(html));
|
assert!(name.ns == ns!(html));
|
||||||
|
|
||||||
// Step 4
|
// Step 4
|
||||||
let definition = document.lookup_custom_element_definition(name.local.clone(), is);
|
let definition = document.lookup_custom_element_definition(&name.ns, &name.local, is.as_ref());
|
||||||
|
|
||||||
if let Some(definition) = definition {
|
if let Some(definition) = definition {
|
||||||
if definition.is_autonomous() {
|
if definition.is_autonomous() {
|
||||||
match mode {
|
match mode {
|
||||||
// TODO: Handle asynchronous CE creation. Relies on CE upgrades.
|
CustomElementCreationMode::Asynchronous => {
|
||||||
CustomElementCreationMode::Asynchronous => {},
|
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;
|
||||||
|
},
|
||||||
CustomElementCreationMode::Synchronous => {
|
CustomElementCreationMode::Synchronous => {
|
||||||
let local_name = name.local.clone();
|
let local_name = name.local.clone();
|
||||||
return match definition.create_element(document, prefix.clone()) {
|
return match definition.create_element(document, prefix.clone()) {
|
||||||
|
@ -148,20 +155,40 @@ fn create_html_element(name: QualName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6.1.2
|
// 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
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Steps 5.1-5.2
|
||||||
let element = create_native_html_element(name, prefix, document, creator);
|
let element = create_native_html_element(name, prefix, document, creator);
|
||||||
element.set_is(definition.name.clone());
|
element.set_is(definition.name.clone());
|
||||||
// TODO: Enqueue custom element upgrade
|
element.set_custom_element_state(CustomElementState::Undefined);
|
||||||
|
match mode {
|
||||||
|
// Step 5.3
|
||||||
|
CustomElementCreationMode::Synchronous =>
|
||||||
|
upgrade_element(definition, &*element),
|
||||||
|
// Step 5.4
|
||||||
|
CustomElementCreationMode::Asynchronous =>
|
||||||
|
ScriptThread::enqueue_upgrade_reaction(&*element, definition),
|
||||||
|
}
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
pub fn create_native_html_element(name: QualName,
|
||||||
|
@ -184,6 +211,7 @@ pub fn create_native_html_element(name: QualName,
|
||||||
|
|
||||||
// This is a big match, and the IDs for inline-interned atoms are not very structured.
|
// This is a big match, and the IDs for inline-interned atoms are not very structured.
|
||||||
// Perhaps we should build a perfect hash from those IDs instead.
|
// Perhaps we should build a perfect hash from those IDs instead.
|
||||||
|
// https://html.spec.whatwg.org/multipage/#elements-in-the-dom
|
||||||
match name.local {
|
match name.local {
|
||||||
local_name!("a") => make!(HTMLAnchorElement),
|
local_name!("a") => make!(HTMLAnchorElement),
|
||||||
local_name!("abbr") => make!(HTMLElement),
|
local_name!("abbr") => make!(HTMLElement),
|
||||||
|
@ -326,7 +354,8 @@ pub fn create_native_html_element(name: QualName,
|
||||||
local_name!("video") => make!(HTMLVideoElement),
|
local_name!("video") => make!(HTMLVideoElement),
|
||||||
local_name!("wbr") => make!(HTMLElement),
|
local_name!("wbr") => make!(HTMLElement),
|
||||||
local_name!("xmp") => make!(HTMLPreElement),
|
local_name!("xmp") => make!(HTMLPreElement),
|
||||||
_ => make!(HTMLUnknownElement),
|
_ if is_valid_custom_element_name(&*name.local) => make!(HTMLElement),
|
||||||
|
_ => make!(HTMLUnknownElement),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,25 +9,26 @@ use dom::bindings::codegen::Bindings::CustomElementRegistryBinding::CustomElemen
|
||||||
use dom::bindings::codegen::Bindings::CustomElementRegistryBinding::ElementDefinitionOptions;
|
use dom::bindings::codegen::Bindings::CustomElementRegistryBinding::ElementDefinitionOptions;
|
||||||
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
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::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior};
|
||||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception, throw_dom_exception};
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::{JS, Root};
|
use dom::bindings::js::{JS, Root};
|
||||||
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
|
||||||
use dom::bindings::str::DOMString;
|
use dom::bindings::str::DOMString;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::domexception::{DOMErrorName, DOMException};
|
use dom::domexception::{DOMErrorName, DOMException};
|
||||||
use dom::element::Element;
|
use dom::element::{CustomElementState, Element};
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::node::Node;
|
use dom::node::{document_from_node, Node, window_from_node};
|
||||||
use dom::promise::Promise;
|
use dom::promise::Promise;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use html5ever::{LocalName, Namespace, Prefix};
|
use html5ever::{LocalName, Namespace, Prefix};
|
||||||
use js::conversions::ToJSValConvertible;
|
use js::conversions::ToJSValConvertible;
|
||||||
use js::jsapi::{Construct1, IsCallable, IsConstructor, HandleValueArray, HandleObject, MutableHandleValue};
|
use js::jsapi::{Construct1, IsCallable, IsConstructor, HandleValueArray, HandleObject, MutableHandleValue};
|
||||||
use js::jsapi::{Heap, JS_GetProperty, JSAutoCompartment, JSContext};
|
use js::jsapi::{Heap, JS_GetProperty, JS_SameValue, JSAutoCompartment, JSContext};
|
||||||
use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue};
|
use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue};
|
||||||
use microtask::Microtask;
|
use microtask::Microtask;
|
||||||
use script_thread::ScriptThread;
|
use script_thread::ScriptThread;
|
||||||
|
@ -79,13 +80,13 @@ impl CustomElementRegistry {
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#look-up-a-custom-element-definition
|
/// https://html.spec.whatwg.org/multipage/#look-up-a-custom-element-definition
|
||||||
pub fn lookup_definition(&self,
|
pub fn lookup_definition(&self,
|
||||||
local_name: LocalName,
|
local_name: &LocalName,
|
||||||
is: Option<LocalName>)
|
is: Option<&LocalName>)
|
||||||
-> Option<Rc<CustomElementDefinition>> {
|
-> Option<Rc<CustomElementDefinition>> {
|
||||||
self.definitions.borrow().values().find(|definition| {
|
self.definitions.borrow().values().find(|definition| {
|
||||||
// Step 4-5
|
// Step 4-5
|
||||||
definition.local_name == local_name &&
|
definition.local_name == *local_name &&
|
||||||
(definition.name == local_name || Some(&definition.name) == is.as_ref())
|
(definition.name == *local_name || Some(&definition.name) == is)
|
||||||
}).cloned()
|
}).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -281,17 +282,28 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
|
||||||
self.element_definition_is_running.set(false);
|
self.element_definition_is_running.set(false);
|
||||||
|
|
||||||
// Step 11
|
// Step 11
|
||||||
let definition = CustomElementDefinition::new(name.clone(),
|
let definition = Rc::new(CustomElementDefinition::new(name.clone(),
|
||||||
local_name,
|
local_name.clone(),
|
||||||
constructor_,
|
constructor_,
|
||||||
observed_attributes,
|
observed_attributes,
|
||||||
callbacks);
|
callbacks));
|
||||||
|
|
||||||
// Step 12
|
// Step 12
|
||||||
self.definitions.borrow_mut().insert(name.clone(), Rc::new(definition));
|
self.definitions.borrow_mut().insert(name.clone(), definition.clone());
|
||||||
|
|
||||||
// TODO: Step 13, 14, 15
|
// Step 13
|
||||||
// Handle custom element upgrades
|
let document = self.window.Document();
|
||||||
|
|
||||||
|
// Steps 14-15
|
||||||
|
for candidate in document.upcast::<Node>().traverse_preorder().filter_map(Root::downcast::<Element>) {
|
||||||
|
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
|
// Step 16, 16.3
|
||||||
if let Some(promise) = self.when_defined.borrow_mut().remove(&name) {
|
if let Some(promise) = self.when_defined.borrow_mut().remove(&name) {
|
||||||
|
@ -366,6 +378,12 @@ pub struct LifecycleCallbacks {
|
||||||
attribute_changed_callback: Option<Rc<Function>>,
|
attribute_changed_callback: Option<Rc<Function>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(HeapSizeOf, JSTraceable, Clone)]
|
||||||
|
pub enum ConstructionStackEntry {
|
||||||
|
Element(Root<Element>),
|
||||||
|
AlreadyConstructedMarker,
|
||||||
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#custom-element-definition
|
/// https://html.spec.whatwg.org/multipage/#custom-element-definition
|
||||||
#[derive(HeapSizeOf, JSTraceable, Clone)]
|
#[derive(HeapSizeOf, JSTraceable, Clone)]
|
||||||
pub struct CustomElementDefinition {
|
pub struct CustomElementDefinition {
|
||||||
|
@ -379,6 +397,8 @@ pub struct CustomElementDefinition {
|
||||||
pub observed_attributes: Vec<DOMString>,
|
pub observed_attributes: Vec<DOMString>,
|
||||||
|
|
||||||
pub callbacks: LifecycleCallbacks,
|
pub callbacks: LifecycleCallbacks,
|
||||||
|
|
||||||
|
pub construction_stack: DOMRefCell<Vec<ConstructionStackEntry>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomElementDefinition {
|
impl CustomElementDefinition {
|
||||||
|
@ -394,6 +414,7 @@ impl CustomElementDefinition {
|
||||||
constructor: constructor,
|
constructor: constructor,
|
||||||
observed_attributes: observed_attributes,
|
observed_attributes: observed_attributes,
|
||||||
callbacks: callbacks,
|
callbacks: callbacks,
|
||||||
|
construction_stack: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,10 +474,113 @@ impl CustomElementDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#concept-upgrade-an-element
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Element) {
|
||||||
|
// 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() {
|
||||||
|
let local_name = attr.local_name().clone();
|
||||||
|
let value = DOMString::from(&**attr.value());
|
||||||
|
let namespace = attr.namespace().clone();
|
||||||
|
ScriptThread::enqueue_callback_reaction(element,
|
||||||
|
CallbackReaction::AttributeChanged(local_name, None, Some(value), namespace), Some(definition.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4
|
||||||
|
if element.is_connected() {
|
||||||
|
ScriptThread::enqueue_callback_reaction(element, CallbackReaction::Connected, Some(definition.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5
|
||||||
|
definition.construction_stack.borrow_mut().push(ConstructionStackEntry::Element(Root::from_ref(element)));
|
||||||
|
|
||||||
|
// Step 7
|
||||||
|
let result = run_upgrade_constructor(&definition.constructor, element);
|
||||||
|
|
||||||
|
definition.construction_stack.borrow_mut().pop();
|
||||||
|
|
||||||
|
// Step 7 exception handling
|
||||||
|
if let Err(error) = result {
|
||||||
|
// Step 7.1
|
||||||
|
element.set_custom_element_state(CustomElementState::Failed);
|
||||||
|
|
||||||
|
// Step 7.2
|
||||||
|
element.clear_reaction_queue();
|
||||||
|
|
||||||
|
// Step 7.3
|
||||||
|
let global = GlobalScope::current().expect("No current global");
|
||||||
|
let cx = global.get_cx();
|
||||||
|
unsafe {
|
||||||
|
throw_dom_exception(cx, &global, error);
|
||||||
|
report_pending_exception(cx, true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 8
|
||||||
|
element.set_custom_element_state(CustomElementState::Custom);
|
||||||
|
|
||||||
|
// Step 9
|
||||||
|
element.set_custom_element_definition(definition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#concept-upgrade-an-element
|
||||||
|
/// Steps 7.1-7.2
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn run_upgrade_constructor(constructor: &Rc<Function>, element: &Element) -> ErrorResult {
|
||||||
|
let window = window_from_node(element);
|
||||||
|
let cx = window.get_cx();
|
||||||
|
rooted!(in(cx) let constructor_val = ObjectValue(constructor.callback()));
|
||||||
|
rooted!(in(cx) let mut element_val = UndefinedValue());
|
||||||
|
unsafe { element.to_jsval(cx, element_val.handle_mut()); }
|
||||||
|
rooted!(in(cx) let mut construct_result = ptr::null_mut());
|
||||||
|
{
|
||||||
|
// Go into the constructor's compartment
|
||||||
|
let _ac = JSAutoCompartment::new(cx, constructor.callback());
|
||||||
|
let args = HandleValueArray::new();
|
||||||
|
// Step 7.1
|
||||||
|
if unsafe { !Construct1(cx, constructor_val.handle(), &args, construct_result.handle_mut()) } {
|
||||||
|
return Err(Error::JSFailed);
|
||||||
|
}
|
||||||
|
// Step 7.2
|
||||||
|
let mut same = false;
|
||||||
|
rooted!(in(cx) let construct_result_val = ObjectValue(construct_result.get()));
|
||||||
|
if unsafe { !JS_SameValue(cx, construct_result_val.handle(), element_val.handle(), &mut same) } {
|
||||||
|
return Err(Error::JSFailed);
|
||||||
|
}
|
||||||
|
if !same {
|
||||||
|
return Err(Error::InvalidState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#concept-try-upgrade
|
||||||
|
pub fn try_upgrade_element(element: &Element) {
|
||||||
|
// Step 1
|
||||||
|
let document = document_from_node(element);
|
||||||
|
let namespace = element.namespace();
|
||||||
|
let local_name = element.local_name();
|
||||||
|
let is = element.get_is();
|
||||||
|
if let Some(definition) = document.lookup_custom_element_definition(namespace, local_name, is.as_ref()) {
|
||||||
|
// Step 2
|
||||||
|
ScriptThread::enqueue_upgrade_reaction(element, definition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(HeapSizeOf, JSTraceable)]
|
#[derive(HeapSizeOf, JSTraceable)]
|
||||||
#[must_root]
|
#[must_root]
|
||||||
pub enum CustomElementReaction {
|
pub enum CustomElementReaction {
|
||||||
// TODO: Support upgrade reactions
|
Upgrade(
|
||||||
|
#[ignore_heap_size_of = "Rc"]
|
||||||
|
Rc<CustomElementDefinition>
|
||||||
|
),
|
||||||
Callback(
|
Callback(
|
||||||
#[ignore_heap_size_of = "Rc"]
|
#[ignore_heap_size_of = "Rc"]
|
||||||
Rc<Function>,
|
Rc<Function>,
|
||||||
|
@ -470,6 +594,7 @@ impl CustomElementReaction {
|
||||||
pub fn invoke(&self, element: &Element) {
|
pub fn invoke(&self, element: &Element) {
|
||||||
// Step 2.1
|
// Step 2.1
|
||||||
match *self {
|
match *self {
|
||||||
|
CustomElementReaction::Upgrade(ref definition) => upgrade_element(definition.clone(), element),
|
||||||
CustomElementReaction::Callback(ref callback, ref arguments) => {
|
CustomElementReaction::Callback(ref callback, ref arguments) => {
|
||||||
let arguments = arguments.iter().map(|arg| arg.handle()).collect();
|
let arguments = arguments.iter().map(|arg| arg.handle()).collect();
|
||||||
let _ = callback.Call_(&*element, arguments, ExceptionHandling::Report);
|
let _ = callback.Call_(&*element, arguments, ExceptionHandling::Report);
|
||||||
|
@ -561,9 +686,12 @@ impl CustomElementReactionStack {
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction
|
/// https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-callback-reaction
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn enqueue_callback_reaction(&self, element: &Element, reaction: CallbackReaction) {
|
pub fn enqueue_callback_reaction(&self,
|
||||||
|
element: &Element,
|
||||||
|
reaction: CallbackReaction,
|
||||||
|
definition: Option<Rc<CustomElementDefinition>>) {
|
||||||
// Step 1
|
// Step 1
|
||||||
let definition = match element.get_custom_element_definition() {
|
let definition = match definition.or_else(|| element.get_custom_element_definition()) {
|
||||||
Some(definition) => definition,
|
Some(definition) => definition,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
@ -628,6 +756,14 @@ impl CustomElementReactionStack {
|
||||||
// Step 6
|
// Step 6
|
||||||
self.enqueue_element(element);
|
self.enqueue_element(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#enqueue-a-custom-element-upgrade-reaction
|
||||||
|
pub fn enqueue_upgrade_reaction(&self, element: &Element, definition: Rc<CustomElementDefinition>) {
|
||||||
|
// Step 1
|
||||||
|
element.push_upgrade_reaction(definition);
|
||||||
|
// Step 2
|
||||||
|
self.enqueue_element(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#element-queue
|
/// https://html.spec.whatwg.org/multipage/#element-queue
|
||||||
|
@ -663,7 +799,7 @@ impl ElementQueue {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#valid-custom-element-name
|
/// https://html.spec.whatwg.org/multipage/#valid-custom-element-name
|
||||||
fn is_valid_custom_element_name(name: &str) -> bool {
|
pub fn is_valid_custom_element_name(name: &str) -> bool {
|
||||||
// Custom elment names must match:
|
// Custom elment names must match:
|
||||||
// PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
|
// PotentialCustomElementName ::= [a-z] (PCENChar)* '-' (PCENChar)*
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ use dom_struct::dom_struct;
|
||||||
use encoding::EncodingRef;
|
use encoding::EncodingRef;
|
||||||
use encoding::all::UTF_8;
|
use encoding::all::UTF_8;
|
||||||
use euclid::{Point2D, Vector2D};
|
use euclid::{Point2D, Vector2D};
|
||||||
use html5ever::{LocalName, QualName};
|
use html5ever::{LocalName, Namespace, QualName};
|
||||||
use hyper::header::{Header, SetCookie};
|
use hyper::header::{Header, SetCookie};
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
|
@ -2001,13 +2001,19 @@ impl Document {
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#look-up-a-custom-element-definition
|
/// https://html.spec.whatwg.org/multipage/#look-up-a-custom-element-definition
|
||||||
pub fn lookup_custom_element_definition(&self,
|
pub fn lookup_custom_element_definition(&self,
|
||||||
local_name: LocalName,
|
namespace: &Namespace,
|
||||||
is: Option<LocalName>)
|
local_name: &LocalName,
|
||||||
|
is: Option<&LocalName>)
|
||||||
-> Option<Rc<CustomElementDefinition>> {
|
-> Option<Rc<CustomElementDefinition>> {
|
||||||
if !PREFS.get("dom.customelements.enabled").as_boolean().unwrap_or(false) {
|
if !PREFS.get("dom.customelements.enabled").as_boolean().unwrap_or(false) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 1
|
||||||
|
if *namespace != ns!(html) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
if !self.has_browsing_context {
|
if !self.has_browsing_context {
|
||||||
return None;
|
return None;
|
||||||
|
|
|
@ -101,6 +101,7 @@ use std::cell::{Cell, Ref};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use style::CaseSensitivityExt;
|
use style::CaseSensitivityExt;
|
||||||
use style::applicable_declarations::ApplicableDeclarationBlock;
|
use style::applicable_declarations::ApplicableDeclarationBlock;
|
||||||
|
@ -149,6 +150,8 @@ pub struct Element {
|
||||||
/// https://dom.spec.whatwg.org/#concept-element-custom-element-definition
|
/// https://dom.spec.whatwg.org/#concept-element-custom-element-definition
|
||||||
#[ignore_heap_size_of = "Rc"]
|
#[ignore_heap_size_of = "Rc"]
|
||||||
custom_element_definition: DOMRefCell<Option<Rc<CustomElementDefinition>>>,
|
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 {
|
impl fmt::Debug for Element {
|
||||||
|
@ -178,6 +181,15 @@ pub enum CustomElementCreationMode {
|
||||||
Asynchronous,
|
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 {
|
impl ElementCreator {
|
||||||
pub fn is_parser_created(&self) -> bool {
|
pub fn is_parser_created(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -254,6 +266,7 @@ impl Element {
|
||||||
selector_flags: Cell::new(ElementSelectorFlags::empty()),
|
selector_flags: Cell::new(ElementSelectorFlags::empty()),
|
||||||
custom_element_reaction_queue: Default::default(),
|
custom_element_reaction_queue: Default::default(),
|
||||||
custom_element_definition: Default::default(),
|
custom_element_definition: Default::default(),
|
||||||
|
custom_element_state: Cell::new(CustomElementState::Uncustomized),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,6 +301,14 @@ impl Element {
|
||||||
self.is.borrow().clone()
|
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>) {
|
pub fn set_custom_element_definition(&self, definition: Rc<CustomElementDefinition>) {
|
||||||
*self.custom_element_definition.borrow_mut() = Some(definition);
|
*self.custom_element_definition.borrow_mut() = Some(definition);
|
||||||
}
|
}
|
||||||
|
@ -300,12 +321,25 @@ impl Element {
|
||||||
self.custom_element_reaction_queue.borrow_mut().push(CustomElementReaction::Callback(function, args));
|
self.custom_element_reaction_queue.borrow_mut().push(CustomElementReaction::Callback(function, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn push_upgrade_reaction(&self, definition: Rc<CustomElementDefinition>) {
|
||||||
|
self.custom_element_reaction_queue.borrow_mut().push(CustomElementReaction::Upgrade(definition));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_reaction_queue(&self) {
|
||||||
|
self.custom_element_reaction_queue.borrow_mut().clear();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn invoke_reactions(&self) {
|
pub fn invoke_reactions(&self) {
|
||||||
let mut reaction_queue = self.custom_element_reaction_queue.borrow_mut();
|
// TODO: This is not spec compliant, as this will allow some reactions to be processed
|
||||||
for reaction in reaction_queue.iter() {
|
// after clear_reaction_queue has been called.
|
||||||
reaction.invoke(self);
|
rooted_vec!(let mut reactions);
|
||||||
|
while !self.custom_element_reaction_queue.borrow().is_empty() {
|
||||||
|
mem::swap(&mut *reactions, &mut *self.custom_element_reaction_queue.borrow_mut());
|
||||||
|
for reaction in reactions.iter() {
|
||||||
|
reaction.invoke(self);
|
||||||
|
}
|
||||||
|
reactions.clear();
|
||||||
}
|
}
|
||||||
reaction_queue.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://drafts.csswg.org/cssom-view/#css-layout-box
|
// https://drafts.csswg.org/cssom-view/#css-layout-box
|
||||||
|
@ -1077,7 +1111,7 @@ impl Element {
|
||||||
|
|
||||||
if self.get_custom_element_definition().is_some() {
|
if self.get_custom_element_definition().is_some() {
|
||||||
let reaction = CallbackReaction::AttributeChanged(name, None, Some(value), namespace);
|
let reaction = CallbackReaction::AttributeChanged(name, None, Some(value), namespace);
|
||||||
ScriptThread::enqueue_callback_reaction(self, reaction);
|
ScriptThread::enqueue_callback_reaction(self, reaction, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(attr.GetOwnerElement().r() == Some(self));
|
assert!(attr.GetOwnerElement().r() == Some(self));
|
||||||
|
@ -1220,7 +1254,7 @@ impl Element {
|
||||||
MutationObserver::queue_a_mutation_record(&self.node, mutation);
|
MutationObserver::queue_a_mutation_record(&self.node, mutation);
|
||||||
|
|
||||||
let reaction = CallbackReaction::AttributeChanged(name, Some(old_value), None, namespace);
|
let reaction = CallbackReaction::AttributeChanged(name, Some(old_value), None, namespace);
|
||||||
ScriptThread::enqueue_callback_reaction(self, reaction);
|
ScriptThread::enqueue_callback_reaction(self, reaction, None);
|
||||||
|
|
||||||
self.attrs.borrow_mut().remove(idx);
|
self.attrs.borrow_mut().remove(idx);
|
||||||
attr.set_owner(None);
|
attr.set_owner(None);
|
||||||
|
|
|
@ -30,7 +30,7 @@ use dom::bindings::str::{DOMString, USVString};
|
||||||
use dom::bindings::xmlname::namespace_from_domstring;
|
use dom::bindings::xmlname::namespace_from_domstring;
|
||||||
use dom::characterdata::{CharacterData, LayoutCharacterDataHelpers};
|
use dom::characterdata::{CharacterData, LayoutCharacterDataHelpers};
|
||||||
use dom::cssstylesheet::CSSStyleSheet;
|
use dom::cssstylesheet::CSSStyleSheet;
|
||||||
use dom::customelementregistry::CallbackReaction;
|
use dom::customelementregistry::{CallbackReaction, try_upgrade_element};
|
||||||
use dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
|
use dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
|
||||||
use dom::documentfragment::DocumentFragment;
|
use dom::documentfragment::DocumentFragment;
|
||||||
use dom::documenttype::DocumentType;
|
use dom::documenttype::DocumentType;
|
||||||
|
@ -317,7 +317,7 @@ impl Node {
|
||||||
node.style_and_layout_data.get().map(|d| node.dispose(d));
|
node.style_and_layout_data.get().map(|d| node.dispose(d));
|
||||||
// https://dom.spec.whatwg.org/#concept-node-remove step 14
|
// https://dom.spec.whatwg.org/#concept-node-remove step 14
|
||||||
if let Some(element) = node.as_custom_element() {
|
if let Some(element) = node.as_custom_element() {
|
||||||
ScriptThread::enqueue_callback_reaction(&*element, CallbackReaction::Disconnected);
|
ScriptThread::enqueue_callback_reaction(&*element, CallbackReaction::Disconnected, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1425,7 +1425,7 @@ impl Node {
|
||||||
for descendant in node.traverse_preorder().filter_map(|d| d.as_custom_element()) {
|
for descendant in node.traverse_preorder().filter_map(|d| d.as_custom_element()) {
|
||||||
// Step 3.2.
|
// Step 3.2.
|
||||||
ScriptThread::enqueue_callback_reaction(&*descendant,
|
ScriptThread::enqueue_callback_reaction(&*descendant,
|
||||||
CallbackReaction::Adopted(old_doc.clone(), Root::from_ref(document)));
|
CallbackReaction::Adopted(old_doc.clone(), Root::from_ref(document)), None);
|
||||||
}
|
}
|
||||||
for descendant in node.traverse_preorder() {
|
for descendant in node.traverse_preorder() {
|
||||||
// Step 3.3.
|
// Step 3.3.
|
||||||
|
@ -1639,12 +1639,13 @@ impl Node {
|
||||||
for descendant in kid.traverse_preorder().filter_map(Root::downcast::<Element>) {
|
for descendant in kid.traverse_preorder().filter_map(Root::downcast::<Element>) {
|
||||||
// Step 7.7.2.
|
// Step 7.7.2.
|
||||||
if descendant.is_connected() {
|
if descendant.is_connected() {
|
||||||
// Step 7.7.2.1.
|
|
||||||
if descendant.get_custom_element_definition().is_some() {
|
if descendant.get_custom_element_definition().is_some() {
|
||||||
ScriptThread::enqueue_callback_reaction(&*descendant, CallbackReaction::Connected);
|
// Step 7.7.2.1.
|
||||||
|
ScriptThread::enqueue_callback_reaction(&*descendant, CallbackReaction::Connected, None);
|
||||||
|
} else {
|
||||||
|
// Step 7.7.2.2.
|
||||||
|
try_upgrade_element(&*descendant);
|
||||||
}
|
}
|
||||||
// TODO: Step 7.7.2.2.
|
|
||||||
// Try to upgrade descendant.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ use dom::bindings::str::DOMString;
|
||||||
use dom::bindings::structuredclone::StructuredCloneData;
|
use dom::bindings::structuredclone::StructuredCloneData;
|
||||||
use dom::bindings::trace::JSTraceable;
|
use dom::bindings::trace::JSTraceable;
|
||||||
use dom::bindings::utils::WRAP_CALLBACKS;
|
use dom::bindings::utils::WRAP_CALLBACKS;
|
||||||
use dom::customelementregistry::{CallbackReaction, CustomElementReactionStack};
|
use dom::customelementregistry::{CallbackReaction, CustomElementDefinition, CustomElementReactionStack};
|
||||||
use dom::document::{Document, DocumentSource, FocusType, HasBrowsingContext, IsHTMLDocument, TouchEventResult};
|
use dom::document::{Document, DocumentSource, FocusType, HasBrowsingContext, IsHTMLDocument, TouchEventResult};
|
||||||
use dom::element::Element;
|
use dom::element::Element;
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
|
@ -774,11 +774,22 @@ impl ScriptThread {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enqueue_callback_reaction(element:&Element, reaction: CallbackReaction) {
|
pub fn enqueue_callback_reaction(element: &Element,
|
||||||
|
reaction: CallbackReaction,
|
||||||
|
definition: Option<Rc<CustomElementDefinition>>) {
|
||||||
SCRIPT_THREAD_ROOT.with(|root| {
|
SCRIPT_THREAD_ROOT.with(|root| {
|
||||||
if let Some(script_thread) = root.get() {
|
if let Some(script_thread) = root.get() {
|
||||||
let script_thread = unsafe { &*script_thread };
|
let script_thread = unsafe { &*script_thread };
|
||||||
script_thread.custom_element_reaction_stack.enqueue_callback_reaction(element, reaction);
|
script_thread.custom_element_reaction_stack.enqueue_callback_reaction(element, reaction, definition);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enqueue_upgrade_reaction(element: &Element, definition: Rc<CustomElementDefinition>) {
|
||||||
|
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_upgrade_reaction(element, definition);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,9 @@ macro_rules! sizeof_checker (
|
||||||
// Update the sizes here
|
// Update the sizes here
|
||||||
sizeof_checker!(size_event_target, EventTarget, 40);
|
sizeof_checker!(size_event_target, EventTarget, 40);
|
||||||
sizeof_checker!(size_node, Node, 184);
|
sizeof_checker!(size_node, Node, 184);
|
||||||
sizeof_checker!(size_element, Element, 424);
|
sizeof_checker!(size_element, Element, 432);
|
||||||
sizeof_checker!(size_htmlelement, HTMLElement, 440);
|
sizeof_checker!(size_htmlelement, HTMLElement, 448);
|
||||||
sizeof_checker!(size_div, HTMLDivElement, 440);
|
sizeof_checker!(size_div, HTMLDivElement, 448);
|
||||||
sizeof_checker!(size_span, HTMLSpanElement, 440);
|
sizeof_checker!(size_span, HTMLSpanElement, 448);
|
||||||
sizeof_checker!(size_text, Text, 216);
|
sizeof_checker!(size_text, Text, 216);
|
||||||
sizeof_checker!(size_characterdata, CharacterData, 216);
|
sizeof_checker!(size_characterdata, CharacterData, 216);
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
[custom-element-reaction-queue.html]
|
|
||||||
type: testharness
|
|
||||||
[Upgrading a custom element must invoke attributeChangedCallback and connectedCallback before start upgrading another element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Mutating a undefined custom element while upgrading a custom element must not enqueue or invoke reactions on the mutated element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
[HTML parser must not instantiate custom elements inside template elements]
|
[HTML parser must not instantiate custom elements inside template elements]
|
||||||
expected: FAIL
|
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()]
|
[HTML parser must use the registry of window.document in a document created by document.implementation.createHTMLDocument()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -1,20 +1,5 @@
|
||||||
[Document.html]
|
[Document.html]
|
||||||
type: testharness
|
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]
|
[execCommand on Document must enqueue a disconnected reaction when deleting a custom element from a contenteditable element]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[body on Document must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[open on Document must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[write on Document must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[writeln on Document must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -12,18 +12,6 @@
|
||||||
[setAttributeNodeNS on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
|
[setAttributeNodeNS on Element must enqueue an attributeChanged reaction when replacing an existing attribute]
|
||||||
expected: FAIL
|
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
|
|
||||||
|
|
||||||
[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
|
|
||||||
|
|
||||||
[insertAdjacentHTML on Element must enqueue a connected reaction for a newly constructed custom element]
|
[insertAdjacentHTML on Element must enqueue a connected reaction for a newly constructed custom element]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[HTMLAnchorElement.html]
|
|
||||||
type: testharness
|
|
||||||
[text on HTMLAnchorElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[HTMLOptionElement.html]
|
|
||||||
type: testharness
|
|
||||||
[text on HTMLOptionElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -3,30 +3,9 @@
|
||||||
[caption on HTMLTableElement must enqueue connectedCallback when inserting a custom element]
|
[caption on HTMLTableElement must enqueue connectedCallback when inserting a custom element]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[caption on HTMLTableElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[deleteCaption() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[tHead on HTMLTableElement must enqueue connectedCallback when inserting a custom element]
|
[tHead on HTMLTableElement must enqueue connectedCallback when inserting a custom element]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[tHead on HTMLTableElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[deleteTHead() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[tFoot on HTMLTableElement must enqueue connectedCallback when inserting a custom element]
|
[tFoot on HTMLTableElement must enqueue connectedCallback when inserting a custom element]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[tFoot on HTMLTableElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[deleteTFoot() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[deleteRow() on HTMLTableElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[HTMLTableRowElement.html]
|
|
||||||
type: testharness
|
|
||||||
[deleteCell() on HTMLTableRowElement must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
[HTMLTableSectionElement.html]
|
|
||||||
type: testharness
|
|
||||||
[deleteRow() on HTMLTableSectionElement on thead must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[deleteRow() on HTMLTableSectionElement on tfoot must enqueue disconnectedCallback when removing a custom element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
[Node.html]
|
|
||||||
type: testharness
|
|
||||||
[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
|
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
[Range.html]
|
[Range.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[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
|
|
||||||
|
|
||||||
[createContextualFragment on Range must construct a custom element]
|
[createContextualFragment on Range must construct a custom element]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
[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
|
|
||||||
|
|
||||||
[HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Upgrading a custom element must throw InvalidStateError when the custom element's constructor returns another element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Inserting an element must not try to upgrade a custom element when it had already failed to upgrade once]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
[upgrading-enqueue-reactions.html]
|
|
||||||
type: testharness
|
|
||||||
[Upgrading a custom element must enqueue attributeChangedCallback on each attribute]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Upgrading a custom element not must enqueue attributeChangedCallback on unobserved attributes]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Upgrading a custom element must enqueue connectedCallback if the element in the document]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[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
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
[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
|
|
||||||
|
|
||||||
[HTMLElement constructor must throw an InvalidStateError when the top of the construction stack is marked AlreadyConstructed due to a custom element constructor constructing itself before super() call]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Upgrading a custom element must throw an InvalidStateError when the returned element is not SameValue as the upgraded element]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -42,12 +42,6 @@
|
||||||
[Interfaces for BASEFONT]
|
[Interfaces for BASEFONT]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Interfaces for foo-bar]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Interfaces for FOO-BAR]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[Interfaces for menuitem]
|
[Interfaces for menuitem]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -26534,7 +26534,7 @@
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/collections.html": [
|
"mozilla/collections.html": [
|
||||||
"f1029d519aa7017a1a3d18a891a0774b9a39f847",
|
"aa060d1e5d1364224f2c2151e5f8b9580ac4427e",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/createEvent-storageevent.html": [
|
"mozilla/createEvent-storageevent.html": [
|
||||||
|
@ -27534,7 +27534,7 @@
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/prototypes.html": [
|
"mozilla/prototypes.html": [
|
||||||
"bb4824ae242ed89485a272f6ef74631d6fea62be",
|
"e19d75682a83f4d2de1cbdf053aadfda181d6725",
|
||||||
"testharness"
|
"testharness"
|
||||||
],
|
],
|
||||||
"mozilla/proxy_setter.html": [
|
"mozilla/proxy_setter.html": [
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
<track></track>
|
<track></track>
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
<foo-á>hi</foo-á>
|
<fooá>hi</fooá>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
test(function() {
|
test(function() {
|
||||||
|
@ -142,7 +142,7 @@ test(function() {
|
||||||
|
|
||||||
// Test non-ASCII tag names. Uppercasing is ASCII-only per spec:
|
// Test non-ASCII tag names. Uppercasing is ASCII-only per spec:
|
||||||
// http://dom.spec.whatwg.org/#dom-element-tagname
|
// http://dom.spec.whatwg.org/#dom-element-tagname
|
||||||
check_tag("foo-á", 1, [HTMLUnknownElement], "FOO-á");
|
check_tag("fooá", 1, [HTMLUnknownElement], "FOOá");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<foo-á>foo</foo-á>
|
<fooá>foo</fooá>
|
||||||
<script>
|
<script>
|
||||||
test(function() {
|
test(function() {
|
||||||
assert_true(window.document instanceof Node, "Should be Node");
|
assert_true(window.document instanceof Node, "Should be Node");
|
||||||
|
@ -18,8 +18,8 @@ test(function() {
|
||||||
assert_true(window.document.documentElement instanceof HTMLHtmlElement, "Should be HTMLHtmlElement");
|
assert_true(window.document.documentElement instanceof HTMLHtmlElement, "Should be HTMLHtmlElement");
|
||||||
assert_true(window.document instanceof Document, "Should be Document");
|
assert_true(window.document instanceof Document, "Should be Document");
|
||||||
assert_equals(window.document.documentElement.tagName, "HTML");
|
assert_equals(window.document.documentElement.tagName, "HTML");
|
||||||
assert_true(window.document.getElementsByTagName('foo-á')[0] instanceof HTMLUnknownElement, "Should be HTMLUnknownElement");
|
assert_true(window.document.getElementsByTagName('fooá')[0] instanceof HTMLUnknownElement, "Should be HTMLUnknownElement");
|
||||||
assert_equals(window.document.getElementsByTagName('foo-á')[0].tagName, "FOO-á");
|
assert_equals(window.document.getElementsByTagName('fooá')[0].tagName, "FOOá");
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue