Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upImplement custom element registry #17112
Conversation
highfive
commented
May 31, 2017
|
Heads up! This PR modifies the following files:
|
highfive
commented
May 31, 2017
| } | ||
|
|
||
| // TODO: 7.2 | ||
| // Check that the element interface for extends is not HTMLUnknownElement |
This comment has been minimized.
This comment has been minimized.
cbrewster
May 31, 2017
Author
Member
I'm not entirely sure the best way to go about this. AFAICT we only determine the element interface here: https://dxr.mozilla.org/servo/rev/779edd7c4aaf900f12fab378a378b0fc52d4c628/components/script/dom/create.rs#129-272.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 2, 2017
Author
Member
Indeed. I am trying to think of a way that we could reuse the match here so we don't need to maintain two matches, but I haven't thought of anything yet. How often is that match changed?
d022726
to
96d3193
|
First review pass. |
| rooted!(in(global_scope.get_cx()) let mut prototype = UndefinedValue()); | ||
| unsafe { | ||
| // Step 10.1 | ||
| let c_name = CString::new("prototype").unwrap(); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 2, 2017
Author
Member
I think we have to use CString here. JS_GetProperty expects a *const i8 and b"prototype\0".as_ptr() gets a *const u8
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| // https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define | ||
| // Steps 10.1, 10.2 | ||
| #[allow(unsafe_code)] | ||
| fn check_prototype(&self, constructor: HandleObject) -> ErrorResult { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 2, 2017
Author
Member
Step 10.1 (The second 10.1, which unsets the element definition is running) By making it a function I can return early without worrying about not unsetting the flag.
|
|
||
| // Step 10.2 | ||
| if !prototype.is_object() { | ||
| return Err(Error::Type("constructor.protoype is not an object".to_owned())); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| } | ||
|
|
||
| impl CustomElementRegistryMethods for CustomElementRegistry { | ||
| #[allow(unsafe_code, unrooted_must_root)] |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
||
| // Step 1 | ||
| if unsafe { !IsConstructor(constructor.get()) } { | ||
| return Err(Error::Type("Second argument of CustomElementRegistry.defin is not a constructor".to_owned())); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
||
| // https://html.spec.whatwg.org/multipage/#dom-customelementregistry-whendefined | ||
| #[allow(unrooted_must_root)] | ||
| fn WhenDefined(&self, name: DOMString) -> Fallible<Rc<Promise>> { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| let mut map = self.when_defined.borrow_mut(); | ||
|
|
||
| // Steps 4, 5 | ||
| let promise = match map.get(&name).cloned() { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| } | ||
| } else { | ||
| return false; | ||
| } |
This comment has been minimized.
This comment has been minimized.
nox
Jun 2, 2017
Member
if !name.chars().next().map_or(false, |c| c >= 'a' && c >= 'z') {
return false;
}
This comment has been minimized.
This comment has been minimized.
|
|
||
| // Check if this character is not a PCENChar | ||
| // https://html.spec.whatwg.org/multipage/#prod-pcenchar | ||
| if c != '-' && c != '.' && c != '_' && c != '\u{B7}' && |
This comment has been minimized.
This comment has been minimized.
nox
Jun 2, 2017
Member
Please make a is_potential_custom_element_char function and use that here, all the reversed conditions don't help readability.
This comment has been minimized.
This comment has been minimized.
|
|
||
| for c in name.chars() { | ||
| if c == '-' { | ||
| has_dash = true; |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| // https://html.spec.whatwg.org/multipage/#dom-customelementregistry-define | ||
| // Steps 10.1, 10.2 | ||
| #[allow(unsafe_code)] | ||
| fn check_prototype(&self, constructor: HandleObject) -> ErrorResult { |
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 2, 2017
Author
Member
Step 10.1 (The second 10.1, which unsets the element definition is running) By making it a function I can return early without worrying about not unsetting the flag.
| rooted!(in(global_scope.get_cx()) let mut prototype = UndefinedValue()); | ||
| unsafe { | ||
| // Step 10.1 | ||
| let c_name = CString::new("prototype").unwrap(); |
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 2, 2017
Author
Member
I think we have to use CString here. JS_GetProperty expects a *const i8 and b"prototype\0".as_ptr() gets a *const u8
|
|
||
| // Step 10.2 | ||
| if !prototype.is_object() { | ||
| return Err(Error::Type("constructor.protoype is not an object".to_owned())); |
This comment has been minimized.
This comment has been minimized.
| } | ||
|
|
||
| impl CustomElementRegistryMethods for CustomElementRegistry { | ||
| #[allow(unsafe_code, unrooted_must_root)] |
This comment has been minimized.
This comment has been minimized.
|
|
||
| // Step 1 | ||
| if unsafe { !IsConstructor(constructor.get()) } { | ||
| return Err(Error::Type("Second argument of CustomElementRegistry.defin is not a constructor".to_owned())); |
This comment has been minimized.
This comment has been minimized.
|
|
||
| // Step 1 | ||
| if !is_valid_custom_element_name(&name) { | ||
| return Err(Error::Syntax); |
This comment has been minimized.
This comment has been minimized.
| let mut map = self.when_defined.borrow_mut(); | ||
|
|
||
| // Steps 4, 5 | ||
| let promise = match map.get(&name).cloned() { |
This comment has been minimized.
This comment has been minimized.
| } | ||
| } else { | ||
| return false; | ||
| } |
This comment has been minimized.
This comment has been minimized.
|
|
||
| for c in name.chars() { | ||
| if c == '-' { | ||
| has_dash = true; |
This comment has been minimized.
This comment has been minimized.
|
|
||
| // Check if this character is not a PCENChar | ||
| // https://html.spec.whatwg.org/multipage/#prod-pcenchar | ||
| if c != '-' && c != '.' && c != '_' && c != '\u{B7}' && |
This comment has been minimized.
This comment has been minimized.
|
|
||
| [customElements.whenDefined must return an unresolved promise when the registry does not contain the entry with the given name] | ||
| expected: FAIL | ||
|
|
||
| [customElements.whenDefined must return a rejected promise when the given name is not a valid custom element name] |
This comment has been minimized.
This comment has been minimized.
666f935
to
e233823
|
This is a really readable implementation! |
| } | ||
|
|
||
| if !is_potential_custom_element_char(c) | ||
| { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
||
| for c in chars { | ||
| if c == '-' { | ||
| has_dash = true; |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 3, 2017
Author
Member
The name can have more than one dash, it just needs at a minimum one.
| // https://html.spec.whatwg.org/multipage/#dom-customelementregistry-get | ||
| #[allow(unsafe_code)] | ||
| unsafe fn Get(&self, cx: *mut JSContext, name: DOMString) -> JSVal { | ||
| match self.definitions.borrow_mut().get(&name) { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| } | ||
|
|
||
| // TODO: 7.2 | ||
| // Check that the element interface for extends is not HTMLUnknownElement |
This comment has been minimized.
This comment has been minimized.
jdm
Jun 2, 2017
Member
I don't see any way around it but duplicating the relevant data from create.rs, unfortunately.
|
|
||
| [customElements.define unset the element definition is running flag before upgrading custom elements] | ||
| expected: FAIL | ||
|
|
||
| [customElements.define must not throw when defining another custom element in a different global object during Get(constructor, "prototype")] |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 3, 2017
Author
Member
The test relies on createElement creating a custom element which isn't implemented yet:
assert_true(iframe.contentDocument.createElement('another-custom-element') instanceof InnerCustomElement);
e233823
to
5bcf748
| // https://html.spec.whatwg.org/multipage/#dom-customelementregistry-get | ||
| #[allow(unsafe_code)] | ||
| unsafe fn Get(&self, cx: *mut JSContext, name: DOMString) -> JSVal { | ||
| match self.definitions.borrow_mut().get(&name) { |
This comment has been minimized.
This comment has been minimized.
|
|
||
| for c in chars { | ||
| if c == '-' { | ||
| has_dash = true; |
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 3, 2017
Author
Member
The name can have more than one dash, it just needs at a minimum one.
| } | ||
|
|
||
| if !is_potential_custom_element_char(c) | ||
| { |
This comment has been minimized.
This comment has been minimized.
|
|
||
| [customElements.define unset the element definition is running flag before upgrading custom elements] | ||
| expected: FAIL | ||
|
|
||
| [customElements.define must not throw when defining another custom element in a different global object during Get(constructor, "prototype")] |
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 3, 2017
Author
Member
The test relies on createElement creating a custom element which isn't implemented yet:
assert_true(iframe.contentDocument.createElement('another-custom-element') instanceof InnerCustomElement);
| @@ -1,5 +1,53 @@ | |||
| [define.html] | |||
| type: testharness | |||
| [Custom Elements: Element definition] | |||
| [If constructor is arrow function, should throw a TypeError] | |||
This comment has been minimized.
This comment has been minimized.
cbrewster
Jun 3, 2017
Author
Member
I am not sure how I should check for this, is there anything other than IsConstructor that I need to do?
This comment has been minimized.
This comment has been minimized.
jdm
Jun 3, 2017
Member
I suspect it's a limitation of our old version of Spider monkey. It would be worth seeing if Gecko passes that test.
This comment has been minimized.
This comment has been minimized.
|
@bors-servo: r+ |
|
|
Implement custom element registry <!-- Please describe your changes on the following line: --> Implements https://html.spec.whatwg.org/multipage/#customelementregistry --- <!-- 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 - [X] These changes fix #16753 (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/17112) <!-- Reviewable:end -->
|
|
|
You should add a Preference annotation to the CustomElementRegistry interface as well. |
5bcf748
to
87bf4ca
|
@bors-servo r=jdm |
|
|
Implement custom element registry <!-- Please describe your changes on the following line: --> Implements https://html.spec.whatwg.org/multipage/#customelementregistry --- <!-- 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 - [X] These changes fix #16753 (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/17112) <!-- Reviewable:end -->
|
|
The test relies on DOM elements with ids beind added as properties of the window. Servo does not do this, and this is not a best practice. Upstreamed from servo/servo#17112 [ci skip]
cbrewster commentedMay 31, 2017
•
edited
Implements https://html.spec.whatwg.org/multipage/#customelementregistry
./mach build -ddoes not report any errors./mach test-tidydoes not report any errorsThis change is