mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Get observed attributes when a CE is defined
Implements steps 10.5 - 10.6 of CustomElementRegistry.define
This commit is contained in:
parent
901a2028f1
commit
596ed557d2
2 changed files with 57 additions and 25 deletions
|
@ -9,7 +9,7 @@ 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::conversions::{ConversionResult, FromJSValConvertible};
|
use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior};
|
||||||
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
use dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::{JS, Root};
|
use dom::bindings::js::{JS, Root};
|
||||||
|
@ -126,6 +126,33 @@ impl CustomElementRegistry {
|
||||||
attribute_changed_callback: get_callback(cx, prototype, b"attributeChangedCallback\0")?,
|
attribute_changed_callback: get_callback(cx, prototype, b"attributeChangedCallback\0")?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define
|
||||||
|
/// Step 10.6
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
fn get_observed_attributes(&self, constructor: HandleObject) -> Fallible<Vec<DOMString>> {
|
||||||
|
let cx = self.window.get_cx();
|
||||||
|
rooted!(in(cx) let mut observed_attributes = UndefinedValue());
|
||||||
|
if unsafe { !JS_GetProperty(cx,
|
||||||
|
constructor,
|
||||||
|
b"observedAttributes\0".as_ptr() as *const _,
|
||||||
|
observed_attributes.handle_mut()) } {
|
||||||
|
return Err(Error::JSFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if observed_attributes.is_undefined() {
|
||||||
|
return Ok(Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
let conversion = unsafe {
|
||||||
|
FromJSValConvertible::from_jsval(cx, observed_attributes.handle(), StringificationBehavior::Default)
|
||||||
|
};
|
||||||
|
match conversion {
|
||||||
|
Ok(ConversionResult::Success(attributes)) => Ok(attributes),
|
||||||
|
Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into())),
|
||||||
|
_ => Err(Error::JSFailed),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define
|
/// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define
|
||||||
|
@ -157,8 +184,8 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
|
||||||
#[allow(unsafe_code, unrooted_must_root)]
|
#[allow(unsafe_code, unrooted_must_root)]
|
||||||
/// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define
|
/// https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define
|
||||||
fn Define(&self, name: DOMString, constructor_: Rc<Function>, options: &ElementDefinitionOptions) -> ErrorResult {
|
fn Define(&self, name: DOMString, constructor_: Rc<Function>, options: &ElementDefinitionOptions) -> ErrorResult {
|
||||||
let global_scope = self.window.upcast::<GlobalScope>();
|
let cx = self.window.get_cx();
|
||||||
rooted!(in(global_scope.get_cx()) let constructor = constructor_.callback());
|
rooted!(in(cx) let constructor = constructor_.callback());
|
||||||
let name = LocalName::from(&*name);
|
let name = LocalName::from(&*name);
|
||||||
|
|
||||||
// Step 1
|
// Step 1
|
||||||
|
@ -211,9 +238,9 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
|
||||||
self.element_definition_is_running.set(true);
|
self.element_definition_is_running.set(true);
|
||||||
|
|
||||||
// Steps 10.1 - 10.2
|
// Steps 10.1 - 10.2
|
||||||
rooted!(in(global_scope.get_cx()) let mut prototype = UndefinedValue());
|
rooted!(in(cx) let mut prototype = UndefinedValue());
|
||||||
{
|
{
|
||||||
let _ac = JSAutoCompartment::new(global_scope.get_cx(), constructor.get());
|
let _ac = JSAutoCompartment::new(cx, constructor.get());
|
||||||
if let Err(error) = self.check_prototype(constructor.handle(), prototype.handle_mut()) {
|
if let Err(error) = self.check_prototype(constructor.handle(), prototype.handle_mut()) {
|
||||||
self.element_definition_is_running.set(false);
|
self.element_definition_is_running.set(false);
|
||||||
return Err(error);
|
return Err(error);
|
||||||
|
@ -221,9 +248,9 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Steps 10.3 - 10.4
|
// Steps 10.3 - 10.4
|
||||||
rooted!(in(global_scope.get_cx()) let proto_object = prototype.to_object());
|
rooted!(in(cx) let proto_object = prototype.to_object());
|
||||||
let callbacks = {
|
let callbacks = {
|
||||||
let _ac = JSAutoCompartment::new(global_scope.get_cx(), proto_object.get());
|
let _ac = JSAutoCompartment::new(cx, proto_object.get());
|
||||||
match self.get_callbacks(proto_object.handle()) {
|
match self.get_callbacks(proto_object.handle()) {
|
||||||
Ok(callbacks) => callbacks,
|
Ok(callbacks) => callbacks,
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
@ -233,8 +260,19 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Steps 10.5 - 10.6
|
// Step 10.5 - 10.6
|
||||||
// Get observed attributes from the constructor
|
let observed_attributes = if callbacks.attribute_changed_callback.is_some() {
|
||||||
|
let _ac = JSAutoCompartment::new(cx, constructor.get());
|
||||||
|
match self.get_observed_attributes(constructor.handle()) {
|
||||||
|
Ok(attributes) => attributes,
|
||||||
|
Err(error) => {
|
||||||
|
self.element_definition_is_running.set(false);
|
||||||
|
return Err(error);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
self.element_definition_is_running.set(false);
|
self.element_definition_is_running.set(false);
|
||||||
|
|
||||||
|
@ -242,6 +280,7 @@ impl CustomElementRegistryMethods for CustomElementRegistry {
|
||||||
let definition = CustomElementDefinition::new(name.clone(),
|
let definition = CustomElementDefinition::new(name.clone(),
|
||||||
local_name,
|
local_name,
|
||||||
constructor_,
|
constructor_,
|
||||||
|
observed_attributes,
|
||||||
callbacks);
|
callbacks);
|
||||||
|
|
||||||
// Step 12
|
// Step 12
|
||||||
|
@ -333,15 +372,23 @@ pub struct CustomElementDefinition {
|
||||||
#[ignore_heap_size_of = "Rc"]
|
#[ignore_heap_size_of = "Rc"]
|
||||||
pub constructor: Rc<Function>,
|
pub constructor: Rc<Function>,
|
||||||
|
|
||||||
|
pub observed_attributes: Vec<DOMString>,
|
||||||
|
|
||||||
pub callbacks: LifecycleCallbacks,
|
pub callbacks: LifecycleCallbacks,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomElementDefinition {
|
impl CustomElementDefinition {
|
||||||
fn new(name: LocalName, local_name: LocalName, constructor: Rc<Function>, callbacks: LifecycleCallbacks) -> CustomElementDefinition {
|
fn new(name: LocalName,
|
||||||
|
local_name: LocalName,
|
||||||
|
constructor: Rc<Function>,
|
||||||
|
observed_attributes: Vec<DOMString>,
|
||||||
|
callbacks: LifecycleCallbacks)
|
||||||
|
-> CustomElementDefinition {
|
||||||
CustomElementDefinition {
|
CustomElementDefinition {
|
||||||
name: name,
|
name: name,
|
||||||
local_name: local_name,
|
local_name: local_name,
|
||||||
constructor: constructor,
|
constructor: constructor,
|
||||||
|
observed_attributes: observed_attributes,
|
||||||
callbacks: callbacks,
|
callbacks: callbacks,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,5 @@
|
||||||
[CustomElementRegistry.html]
|
[CustomElementRegistry.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[customElements.define must get "observedAttributes" property on the constructor prototype when "attributeChangedCallback" is present]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[customElements.define must rethrow an exception thrown while getting observedAttributes on the constructor prototype]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[customElements.define must rethrow an exception thrown while converting the value of observedAttributes to sequence<DOMString>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[customElements.define must rethrow an exception thrown while iterating over observedAttributes to sequence<DOMString>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[customElements.define must rethrow an exception thrown while retrieving Symbol.iterator on observedAttributes]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[customElements.define must upgrade elements in the shadow-including tree order]
|
[customElements.define must upgrade elements in the shadow-including tree order]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue