New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Html options collection#13129 #13380
Conversation
Heads up! This PR modifies the following files:
|
7340655
to
26659af
Compare
#[dom_struct] | ||
pub struct HTMLOptionsCollection { | ||
collection: HTMLCollection, | ||
root: MutHeap<JS<Node>> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary? The parent class already has this field.
@@ -28,7 +32,8 @@ use style::element_state::*; | |||
|
|||
#[dom_struct] | |||
pub struct HTMLSelectElement { | |||
htmlelement: HTMLElement | |||
htmlelement: HTMLElement, | |||
options: MutNullableHeap<JS<HTMLOptionsCollection>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't be nullable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not? It's done so in HTMLFormElement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's expensive to create an HTMLFormControlsCollection for HTMLFormElement, but for HTMLSelectElement, creating an HTMLOptionsCollection is just a straightforward filter, hence it isn't necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this isn't possible to create an HTMLOptionsCollection
during the creation of HTMLSelectElement
. Ignore my comment and leave it as-is.
let options = HTMLOptionsCollection::new(window.r(), self.upcast(), filter); | ||
self.options.set(Some(&options)); | ||
options | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Indentation.
|
||
// https://html.spec.whatwg.org/multipage/#dom-select-item | ||
fn Item(&self, index: u32) -> Option<Root<Element>> { | ||
self.Options().IndexedGetter(index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this not Item(index)
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no such method for HTMLOptionsCollection.
|
||
// https://html.spec.whatwg.org/multipage/#dom-htmloptionscollection-add | ||
fn Add(&self, element: HTMLOptionElementOrHTMLOptGroupElement, before: Option<HTMLElementOrLong >) -> ErrorResult { | ||
// TODO |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this TODO doing here?
let name = QualName::new(ns!(html), name_atom.clone()); | ||
let element = Element::create(name, None, document.r(), ElementCreator::ScriptCreated); | ||
let node = element.r().upcast::<Node>(); | ||
try!(Node::pre_insert(node, root.r(), None)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty messy, you can achieve the same simply by using the AppendChild WebIDL function on Node and HTMLOptionElement::new
.
// // https://html.spec.whatwg.org/multipage/#dom-select-setter | ||
// fn IndexedSetter(&self, index: u32, value: Option<&HTMLOptionElement>) -> ErrorResult { | ||
// self.Options().IndexedSetter(index, value) | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this commented out?
// // https://html.spec.whatwg.org/multipage/#dom-select-remove | ||
// fn Remove(&self, index: i32) -> ErrorResult { | ||
// self.Options().Remove(index) | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this commented out?
element.r().Remove(); | ||
Ok(()) | ||
} else { | ||
Err(Error::NotFound) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec doesn't say that you should throw a NotFoundError in this case, instead it says to abort the algorithm.
if delta < 0 { | ||
// new length is lower - deleting last option elements | ||
for index in (length..current_length).rev() { | ||
self.Remove(index as i32).unwrap() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unwrapping is not fine here, since it can fail. If you don't care about the result of removing, you can do let _ = self.Remove(index as i32);
.filter_map(Root::downcast::<HTMLOptionElement>) | ||
.nth(index as usize) | ||
.map(|item| Root::from_ref(item.upcast())) | ||
self.Options().IndexedGetter(index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this not self.Options().Item(index)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you ignored my review comment here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as the previous similar - there is no such method (Item) for HTMLOptionsCollection.
26659af
to
47aaf09
Compare
fn add_new_elements(&self, count: u32) -> ErrorResult { | ||
let root = self.collection.get_root(); | ||
let document = document_from_node(root.r()); | ||
let name_atom = Atom::from(DOMString::from("option".to_owned())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let name_atom = atom!("option");
3dfce35
to
c8574ec
Compare
@KiChjang fixed latest one, fixed indentation in idl file. |
@KiChjang as for Item method - how are they used from JS? The collection should inherit these methods from HTMLCollection, but binding generator does not require them for HTMLOptionsCollection. Should I implement it anyway? |
What you need to do is to |
fn add_new_elements(&self, count: u32) -> ErrorResult { | ||
let root = self.collection.get_root(); | ||
let document = document_from_node(root.r()); | ||
let name_atom = atom!("option"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed this in my previous review, but name_atom
is completely unnecessary. You can just call atom!("option")
directly in HTMLOptionElement::new
.
for _ in 0..count { | ||
let element = HTMLOptionElement::new(name_atom.clone(), None, document.r()); | ||
let node = element.upcast::<Node>(); | ||
try!(root.AppendChild(node).map(|_| ())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the map necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AppentChild returns Fallable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably this function returns ErrorResult, which is Fallible<(), Error>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, AppendChild returns Fallible<Root<Node>, Error>
and the function returns Fallible<(), Error>
so I had to map Root<Node>
to ()
.
@@ -229,6 +229,9 @@ impl HTMLCollection { | |||
} | |||
} | |||
|
|||
pub fn get_root(&self) -> Root<Node> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's call this root_node
instead.
|
||
let node = match element { | ||
HTMLOptionElementOrHTMLOptGroupElement::HTMLOptionElement(ref element) => element.upcast::<Node>(), | ||
HTMLOptionElementOrHTMLOptGroupElement::HTMLOptGroupElement(ref element) => element.upcast::<Node>(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
HTMLOptionElementOrHTMLOptGroupElement::HTMLOptionElement(ref el) |
HTMLOptionElementOrHTMLOptGroupElement::HTMLOptGroupElement(ref el) => el.upcast::<Node>()
I'm not sure the above works, but if not, use the following:
let node: &Node = match element {
// same as above, but use element.upcast() instead of element.upcast::<Node>()
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe either of those will work - match arms that are combined must contain the exact same types.
edit: oh, I think I'm misreading your second suggestion. If "as above" means the original code, then that's fine.
|
||
fn add_new_elements(&self, count: u32) -> ErrorResult { | ||
let root = self.collection.get_root(); | ||
let document = document_from_node(root.r()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why it has to be root.r()
, but self
works here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self is not derived from Node. Base 'class' is HTMLCollection.
c8574ec
to
0245c9c
Compare
🔒 Merge conflict |
☔ The latest upstream changes (presumably #13426) made this pull request unmergeable. Please resolve the merge conflicts. |
de23c13
to
6d5791f
Compare
@bors-servo: r=KiChjang |
📌 Commit 6d5791f has been approved by |
6d5791f
to
80c70e3
Compare
@bors-servo: r=KiChjang |
📌 Commit 80c70e3 has been approved by |
Html options collection#13129 <!-- Please describe your changes on the following line: --> Implement HTMLOptionsCollection and related HTMLSelectElement items --- <!-- 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 #13129 (github issue number if applicable). <!-- Either: --> - [X] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- 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/13380) <!-- Reviewable:end -->
☀️ Test successful - arm32, arm64, linux-dev, linux-rel, mac-dev-unit, mac-rel-css, mac-rel-wpt, windows-dev |
Implement HTMLOptionsCollection and related HTMLSelectElement items
./mach build -d
does not report any errors./mach test-tidy
does not report any errorsThis change is