mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Add flag for sync/async CE creation
This commit is contained in:
parent
2f36d3544f
commit
062b128688
9 changed files with 78 additions and 35 deletions
|
@ -6,8 +6,7 @@ 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::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::Element;
|
use dom::element::{CustomElementCreationMode, Element, ElementCreator};
|
||||||
use dom::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;
|
||||||
|
@ -116,7 +115,8 @@ fn create_html_element(name: QualName,
|
||||||
prefix: Option<Prefix>,
|
prefix: Option<Prefix>,
|
||||||
is: Option<LocalName>,
|
is: Option<LocalName>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
creator: ElementCreator)
|
creator: ElementCreator,
|
||||||
|
mode: CustomElementCreationMode)
|
||||||
-> Root<Element> {
|
-> Root<Element> {
|
||||||
assert!(name.ns == ns!(html));
|
assert!(name.ns == ns!(html));
|
||||||
|
|
||||||
|
@ -125,24 +125,31 @@ fn create_html_element(name: QualName,
|
||||||
|
|
||||||
if let Some(definition) = definition {
|
if let Some(definition) = definition {
|
||||||
if definition.is_autonomous() {
|
if definition.is_autonomous() {
|
||||||
let local_name = name.local.clone();
|
match mode {
|
||||||
return match definition.create_element(document) {
|
// TODO: Handle asynchronous CE creation. Relies on CE upgrades.
|
||||||
Ok(element) => element,
|
CustomElementCreationMode::Asynchronous => {},
|
||||||
Err(error) => {
|
CustomElementCreationMode::Synchronous => {
|
||||||
// Step 6. Recovering from exception.
|
let local_name = name.local.clone();
|
||||||
let global = GlobalScope::current().unwrap_or_else(|| document.global());
|
return match definition.create_element(document) {
|
||||||
|
Ok(element) => element,
|
||||||
|
Err(error) => {
|
||||||
|
// Step 6. Recovering from exception.
|
||||||
|
let global = GlobalScope::current().unwrap_or_else(|| document.global());
|
||||||
|
let cx = global.get_cx();
|
||||||
|
|
||||||
// Step 6.1.1
|
// Step 6.1.1
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ac = JSAutoCompartment::new(global.get_cx(), global.reflector().get_jsobject().get());
|
let _ac = JSAutoCompartment::new(cx, global.reflector().get_jsobject().get());
|
||||||
throw_dom_exception(global.get_cx(), &global, error);
|
throw_dom_exception(cx, &global, error);
|
||||||
report_pending_exception(global.get_cx(), true);
|
report_pending_exception(cx, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 6.1.2
|
// Step 6.1.2
|
||||||
Root::upcast(HTMLUnknownElement::new(local_name, prefix, document))
|
Root::upcast(HTMLUnknownElement::new(local_name, prefix, document))
|
||||||
|
},
|
||||||
|
};
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
} else {
|
} else {
|
||||||
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());
|
||||||
|
@ -323,11 +330,12 @@ pub fn create_native_html_element(name: QualName,
|
||||||
pub fn create_element(name: QualName,
|
pub fn create_element(name: QualName,
|
||||||
is: Option<LocalName>,
|
is: Option<LocalName>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
creator: ElementCreator)
|
creator: ElementCreator,
|
||||||
|
mode: CustomElementCreationMode)
|
||||||
-> Root<Element> {
|
-> Root<Element> {
|
||||||
let prefix = name.prefix.clone();
|
let prefix = name.prefix.clone();
|
||||||
match name.ns {
|
match name.ns {
|
||||||
ns!(html) => create_html_element(name, prefix, is, document, creator),
|
ns!(html) => create_html_element(name, prefix, is, document, creator, mode),
|
||||||
ns!(svg) => create_svg_element(name, prefix, document),
|
ns!(svg) => create_svg_element(name, prefix, document),
|
||||||
_ => Element::new(name.local, name.ns, prefix, document)
|
_ => Element::new(name.local, name.ns, prefix, document)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ use dom::documentfragment::DocumentFragment;
|
||||||
use dom::documenttype::DocumentType;
|
use dom::documenttype::DocumentType;
|
||||||
use dom::domimplementation::DOMImplementation;
|
use dom::domimplementation::DOMImplementation;
|
||||||
use dom::element::{Element, ElementCreator, ElementPerformFullscreenEnter, ElementPerformFullscreenExit};
|
use dom::element::{Element, ElementCreator, ElementPerformFullscreenEnter, ElementPerformFullscreenExit};
|
||||||
|
use dom::element::CustomElementCreationMode;
|
||||||
use dom::errorevent::ErrorEvent;
|
use dom::errorevent::ErrorEvent;
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable, EventDefault, EventStatus};
|
use dom::event::{Event, EventBubbles, EventCancelable, EventDefault, EventStatus};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
|
@ -2854,7 +2855,7 @@ impl DocumentMethods for Document {
|
||||||
|
|
||||||
let name = QualName::new(None, ns, LocalName::from(local_name));
|
let name = QualName::new(None, ns, LocalName::from(local_name));
|
||||||
let is = options.is.as_ref().map(|is| LocalName::from(&**is));
|
let is = options.is.as_ref().map(|is| LocalName::from(&**is));
|
||||||
Ok(Element::create(name, is, self, ElementCreator::ScriptCreated))
|
Ok(Element::create(name, is, self, ElementCreator::ScriptCreated, CustomElementCreationMode::Synchronous))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-document-createelementns
|
// https://dom.spec.whatwg.org/#dom-document-createelementns
|
||||||
|
@ -2867,7 +2868,7 @@ impl DocumentMethods for Document {
|
||||||
&qualified_name)?;
|
&qualified_name)?;
|
||||||
let name = QualName::new(prefix, namespace, local_name);
|
let name = QualName::new(prefix, namespace, local_name);
|
||||||
let is = options.is.as_ref().map(|is| LocalName::from(&**is));
|
let is = options.is.as_ref().map(|is| LocalName::from(&**is));
|
||||||
Ok(Element::create(name, is, self, ElementCreator::ScriptCreated))
|
Ok(Element::create(name, is, self, ElementCreator::ScriptCreated, CustomElementCreationMode::Synchronous))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#dom-document-createattribute
|
// https://dom.spec.whatwg.org/#dom-document-createattribute
|
||||||
|
@ -3121,7 +3122,11 @@ impl DocumentMethods for Document {
|
||||||
Some(elem) => Root::upcast::<Node>(elem),
|
Some(elem) => Root::upcast::<Node>(elem),
|
||||||
None => {
|
None => {
|
||||||
let name = QualName::new(None, ns!(svg), local_name!("title"));
|
let name = QualName::new(None, ns!(svg), local_name!("title"));
|
||||||
let elem = Element::create(name, None, self, ElementCreator::ScriptCreated);
|
let elem = Element::create(name,
|
||||||
|
None,
|
||||||
|
self,
|
||||||
|
ElementCreator::ScriptCreated,
|
||||||
|
CustomElementCreationMode::Synchronous);
|
||||||
let parent = root.upcast::<Node>();
|
let parent = root.upcast::<Node>();
|
||||||
let child = elem.upcast::<Node>();
|
let child = elem.upcast::<Node>();
|
||||||
parent.InsertBefore(child, parent.GetFirstChild().r())
|
parent.InsertBefore(child, parent.GetFirstChild().r())
|
||||||
|
@ -3141,7 +3146,8 @@ impl DocumentMethods for Document {
|
||||||
let elem = Element::create(name,
|
let elem = Element::create(name,
|
||||||
None,
|
None,
|
||||||
self,
|
self,
|
||||||
ElementCreator::ScriptCreated);
|
ElementCreator::ScriptCreated,
|
||||||
|
CustomElementCreationMode::Synchronous);
|
||||||
head.upcast::<Node>()
|
head.upcast::<Node>()
|
||||||
.AppendChild(elem.upcast())
|
.AppendChild(elem.upcast())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
@ -165,6 +165,11 @@ pub enum ElementCreator {
|
||||||
ScriptCreated,
|
ScriptCreated,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum CustomElementCreationMode {
|
||||||
|
Synchronous,
|
||||||
|
Asynchronous,
|
||||||
|
}
|
||||||
|
|
||||||
impl ElementCreator {
|
impl ElementCreator {
|
||||||
pub fn is_parser_created(&self) -> bool {
|
pub fn is_parser_created(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -208,9 +213,10 @@ impl Element {
|
||||||
pub fn create(name: QualName,
|
pub fn create(name: QualName,
|
||||||
is: Option<LocalName>,
|
is: Option<LocalName>,
|
||||||
document: &Document,
|
document: &Document,
|
||||||
creator: ElementCreator)
|
creator: ElementCreator,
|
||||||
|
mode: CustomElementCreationMode)
|
||||||
-> Root<Element> {
|
-> Root<Element> {
|
||||||
create_element(name, is, document, creator)
|
create_element(name, is, document, creator, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_inherited(local_name: LocalName,
|
pub fn new_inherited(local_name: LocalName,
|
||||||
|
@ -1984,7 +1990,8 @@ impl ElementMethods for Element {
|
||||||
let body_elem = Element::create(QualName::new(None, ns!(html), local_name!("body")),
|
let body_elem = Element::create(QualName::new(None, ns!(html), local_name!("body")),
|
||||||
None,
|
None,
|
||||||
&context_document,
|
&context_document,
|
||||||
ElementCreator::ScriptCreated);
|
ElementCreator::ScriptCreated,
|
||||||
|
CustomElementCreationMode::Synchronous);
|
||||||
Root::upcast(body_elem)
|
Root::upcast(body_elem)
|
||||||
},
|
},
|
||||||
_ => context_node.GetParentElement().unwrap()
|
_ => context_node.GetParentElement().unwrap()
|
||||||
|
|
|
@ -33,7 +33,7 @@ use dom::cssstylesheet::CSSStyleSheet;
|
||||||
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;
|
||||||
use dom::element::{Element, ElementCreator};
|
use dom::element::{CustomElementCreationMode, Element, ElementCreator};
|
||||||
use dom::eventtarget::EventTarget;
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::htmlbodyelement::HTMLBodyElement;
|
use dom::htmlbodyelement::HTMLBodyElement;
|
||||||
|
@ -1827,8 +1827,11 @@ impl Node {
|
||||||
ns: element.namespace().clone(),
|
ns: element.namespace().clone(),
|
||||||
local: element.local_name().clone()
|
local: element.local_name().clone()
|
||||||
};
|
};
|
||||||
let element = Element::create(name, element.get_is(),
|
let element = Element::create(name,
|
||||||
&document, ElementCreator::ScriptCreated);
|
element.get_is(),
|
||||||
|
&document,
|
||||||
|
ElementCreator::ScriptCreated,
|
||||||
|
CustomElementCreationMode::Asynchronous);
|
||||||
Root::upcast::<Node>(element)
|
Root::upcast::<Node>(element)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@ use dom::bindings::trace::JSTraceable;
|
||||||
use dom::comment::Comment;
|
use dom::comment::Comment;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::documenttype::DocumentType;
|
use dom::documenttype::DocumentType;
|
||||||
use dom::element::{Element, ElementCreator};
|
use dom::element::{CustomElementCreationMode, Element, ElementCreator};
|
||||||
use dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement};
|
use dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement};
|
||||||
use dom::htmlscriptelement::HTMLScriptElement;
|
use dom::htmlscriptelement::HTMLScriptElement;
|
||||||
use dom::htmltemplateelement::HTMLTemplateElement;
|
use dom::htmltemplateelement::HTMLTemplateElement;
|
||||||
|
@ -252,7 +252,8 @@ impl Sink {
|
||||||
let elem = Element::create(name,
|
let elem = Element::create(name,
|
||||||
is,
|
is,
|
||||||
&*self.document,
|
&*self.document,
|
||||||
ElementCreator::ParserCreated(self.current_line));
|
ElementCreator::ParserCreated(self.current_line),
|
||||||
|
CustomElementCreationMode::Synchronous);
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
elem.set_attribute_from_parser(attr.name, DOMString::from(String::from(attr.value)), None);
|
elem.set_attribute_from_parser(attr.name, DOMString::from(String::from(attr.value)), None);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use dom::characterdata::CharacterData;
|
||||||
use dom::comment::Comment;
|
use dom::comment::Comment;
|
||||||
use dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
|
use dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument};
|
||||||
use dom::documenttype::DocumentType;
|
use dom::documenttype::DocumentType;
|
||||||
use dom::element::{Element, ElementCreator};
|
use dom::element::{Element, ElementCreator, CustomElementCreationMode};
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement};
|
use dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement};
|
||||||
use dom::htmlimageelement::HTMLImageElement;
|
use dom::htmlimageelement::HTMLImageElement;
|
||||||
|
@ -786,8 +786,11 @@ impl TreeSink for Sink {
|
||||||
.find(|attr| attr.name.local.eq_str_ignore_ascii_case("is"))
|
.find(|attr| attr.name.local.eq_str_ignore_ascii_case("is"))
|
||||||
.map(|attr| LocalName::from(&*attr.value));
|
.map(|attr| LocalName::from(&*attr.value));
|
||||||
|
|
||||||
let elem = Element::create(name, is, &*self.document,
|
let elem = Element::create(name,
|
||||||
ElementCreator::ParserCreated(self.current_line));
|
is,
|
||||||
|
&*self.document,
|
||||||
|
ElementCreator::ParserCreated(self.current_line),
|
||||||
|
CustomElementCreationMode::Synchronous);
|
||||||
|
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
elem.set_attribute_from_parser(attr.name, DOMString::from(String::from(attr.value)), None);
|
elem.set_attribute_from_parser(attr.name, DOMString::from(String::from(attr.value)), None);
|
||||||
|
|
|
@ -6,3 +6,6 @@
|
||||||
[Custom Elements: Custom element reactions must be invoked before returning to author scripts]
|
[Custom Elements: Custom element reactions must be invoked before returning to author scripts]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[Calling Node.prototype.cloneNode(false) must push a new element queue to the processing stack]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -30,3 +30,6 @@
|
||||||
[writeln on Document must enqueue connectedCallback after constructing a custom element]
|
[writeln on Document must enqueue connectedCallback after constructing a custom element]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[importNode on Document must construct a new custom element when importing a custom element from a template]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -15,3 +15,12 @@
|
||||||
[Inserting an element must not try to upgrade a custom element when it had already failed to upgrade once]
|
[Inserting an element must not try to upgrade a custom element when it had already failed to upgrade once]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue