Closed
Bug 1264947
Opened 9 years ago
Closed 9 years ago
HTMLTableElement.rows doesn't seem to return element in the order defined in HTML Spec.
Categories
(Core :: DOM: Core & HTML, defect)
Tracking
()
RESOLVED
FIXED
mozilla49
| Tracking | Status | |
|---|---|---|
| firefox49 | --- | fixed |
People
(Reporter: smaug, Assigned: jdai)
Details
(Whiteboard: [tw-dom] btpp-active)
Attachments
(4 files, 8 obsolete files)
|
775 bytes,
text/html
|
Details | |
|
1.53 KB,
text/html
|
Details | |
|
6.58 KB,
patch
|
jdai
:
review+
|
Details | Diff | Splinter Review |
|
14.93 KB,
patch
|
jdai
:
review+
|
Details | Diff | Splinter Review |
If I read the code right, the implementation returns first elements in tbodies, and then children of table element itself. Per spec "followed by those elements whose parent is either a table or tbody element, again in tree order,"
| Reporter | ||
Comment 1•9 years ago
|
||
Need to test what other browsers do.
| Reporter | ||
Comment 2•9 years ago
|
||
| Reporter | ||
Comment 3•9 years ago
|
||
And we're behavior differently to Edge and Chrome.
I assume fixing this should be quite easy. Some changes to
#define DO_FOR_EACH_ROWGROUP(_code) in HTMLTableElement.cpp
We probably need separate macro/method to find certain element based on an index and then the existing macro works for a fast way to get the length of the collection.
Or something, could be fixed also in different way.
Whiteboard: [tw-dom]
| Reporter | ||
Comment 4•9 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #3)
> And we're behavior differently to Edge and Chrome.
huh, how did I write that bad English :)
Anyhow, link to the spec
https://html.spec.whatwg.org/multipage/tables.html#dom-table-rows
| Assignee | ||
Updated•9 years ago
|
Assignee: nobody → jdai
| Assignee | ||
Comment 5•9 years ago
|
||
| Assignee | ||
Comment 6•9 years ago
|
||
| Assignee | ||
Comment 7•9 years ago
|
||
| Assignee | ||
Updated•9 years ago
|
Whiteboard: [tw-dom] → [tw-dom] btpp-active
| Assignee | ||
Updated•9 years ago
|
Attachment #8750192 -
Attachment description: Part 2: Bug 1264947 - HTMLTableElement.rows return element in the order. → wip, v1
| Assignee | ||
Comment 8•9 years ago
|
||
Attachment #8750192 -
Attachment is obsolete: true
| Assignee | ||
Comment 9•9 years ago
|
||
Comment on attachment 8750638 [details] [diff] [review]
Part 2: Bug 1264947 - HTMLTableElement.rows return element in the order.
Base on comment #3, I separate a macro named DO_FOR_EACH_BY_ORDER()
which is to find certain element based on an index.
Hi Olli, may I have your review? Thank you.
Attachment #8750638 -
Attachment description: wip, v2 → Part 2: Bug 1264947 - HTMLTableElement.rows return element in the order.
Attachment #8750638 -
Flags: review?(bugs)
| Assignee | ||
Updated•9 years ago
|
Attachment #8750191 -
Flags: review?(bugs)
| Reporter | ||
Updated•9 years ago
|
Attachment #8750191 -
Flags: review?(bugs) → review+
| Reporter | ||
Comment 10•9 years ago
|
||
I presume we'll need to change http://mxr.mozilla.org/mozilla-central/source/testing/web-platform/meta/html/semantics/tabular-data/the-table-element/table-rows.html.ini with the patch. Can we even remove that whole .ini, assuming all the tests in http://mxr.mozilla.org/mozilla-central/source/testing/web-platform/tests/html/semantics/tabular-data/the-table-element/table-rows.html?force=1 are passed.
| Reporter | ||
Comment 11•9 years ago
|
||
Looks like no, since that test fails because of some issue in head/foot handling. I wonder if that is issue in the test or in the spec or in our impl.
| Reporter | ||
Comment 12•9 years ago
|
||
Comment on attachment 8750638 [details] [diff] [review]
Part 2: Bug 1264947 - HTMLTableElement.rows return element in the order.
yeah, looks like we just handle the first thead and first tfoot, but per spec .rows should handle them all.
So the macro here cann't use mParent->GetTHead()/GetTFoot() but needs to actually iterate through all the child node for those.
And once that is done, the wpt test should pass and the .ini file which annotates known failures could be removed.
Attachment #8750638 -
Flags: review?(bugs) → review-
| Assignee | ||
Comment 13•9 years ago
|
||
Address comment 10, which are
- Make all the tests in table-rows.html are passed.
- Modify TableRowsCollection::GetLength() apply DO_FOR_EACH_BY_ORDER().
- Remove test_bug1264947.html because wpt table-rows.html cover all of them.
Try result:https://treeherder.mozilla.org/#/jobs?repo=try&revision=d914eb7fb451ee44831f032bec1e630dd921ac4a
Hi Olli, may I have your review? Thank you.
Attachment #8750638 -
Attachment is obsolete: true
Attachment #8751150 -
Flags: review?(bugs)
| Reporter | ||
Comment 14•9 years ago
|
||
Now that I look at the code some more, do we ever need to use DO_FOR_EACH_ROWGROUP, or should we always use the new macro?
In other words, could or should TableRowsCollection::GetSupportedNames and TableRowsCollection::NamedItem use the new macro? I think so.
| Reporter | ||
Updated•9 years ago
|
Flags: needinfo?(jdai)
| Assignee | ||
Comment 15•9 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #14)
> Now that I look at the code some more, do we ever need to use
> DO_FOR_EACH_ROWGROUP, or should we always use the new macro?
> In other words, could or should TableRowsCollection::GetSupportedNames and
> TableRowsCollection::NamedItem use the new macro? I think so.
Yes, you are right. We should use new macro. Thank you for pointing them out.
Looks like TableRowsCollection::NamedItem no method use it, perhaps I should add comment for it?
Flags: needinfo?(jdai)
| Reporter | ||
Comment 16•9 years ago
|
||
I'm pretty sure the generated code for HTMLCollection webidl interface uses NamedItem.
| Assignee | ||
Comment 17•9 years ago
|
||
Address comment 14, which is
- Apply TableRowsCollection::GetSupportedNames and TableRowsCollection::NamedItem to new macro.
Attachment #8751150 -
Attachment is obsolete: true
Attachment #8751150 -
Flags: review?(bugs)
| Assignee | ||
Comment 18•9 years ago
|
||
Following comment 17, I removed mOrphanRows in this patch.
Hi Olli, may I have your review? Thank you.
Attachment #8751603 -
Attachment is obsolete: true
Attachment #8752045 -
Flags: review?(bugs)
| Reporter | ||
Comment 19•9 years ago
|
||
Comment on attachment 8752045 [details] [diff] [review]
Part 2: Bug 1264947 - HTMLTableElement.rows return element in the order. v4
> // Macro that can be used to avoid copy/pasting code to iterate over the
> // rowgroups. _code should be the code to execute for each rowgroup. The
>-// rowgroup's rows will be in the nsIDOMHTMLCollection* named "rows". Note
>-// that this may be null at any time. This macro assumes an nsresult named
>+// rowgroup's rows will be in the nsIDOMHTMLCollection* named "rows".
>+// _trCode should be the code to excute for each tr row. Note that
execute
>+// this may be null at any time. This macro assumes an nsresult named
> // |rv| is in scope.
>-#define DO_FOR_EACH_ROWGROUP(_code) \
>- do { \
>- if (mParent) { \
>- /* THead */ \
>- HTMLTableSectionElement* rowGroup = mParent->GetTHead(); \
>- nsIHTMLCollection* rows; \
>- if (rowGroup) { \
>- rows = rowGroup->Rows(); \
>- do { /* gives scoping */ \
>- _code \
>- } while (0); \
>- } \
>- /* TBodies */ \
>- for (nsIContent* _node = mParent->nsINode::GetFirstChild(); \
>- _node; _node = _node->GetNextSibling()) { \
>- if (_node->IsHTMLElement(nsGkAtoms::tbody)) { \
>- rowGroup = static_cast<HTMLTableSectionElement*>(_node); \
>- rows = rowGroup->Rows(); \
>- do { /* gives scoping */ \
>- _code \
>- } while (0); \
>+ #define DO_FOR_EACH_BY_ORDER(_code, _trCode) \
>+ do { \
>+ if (mParent) { \
>+ HTMLTableSectionElement* rowGroup; \
>+ nsIHTMLCollection* rows; \
>+ /* THead */ \
>+ for (nsIContent* _node = mParent->nsINode::GetFirstChild(); \
>+ _node; _node = _node->GetNextSibling()) { \
>+ if (_node->IsHTMLElement(nsGkAtoms::thead)) { \
>+ rowGroup = static_cast<HTMLTableSectionElement*>(_node);\
>+ rows = rowGroup->Rows(); \
>+ do { /* gives scoping */ \
>+ _code \
>+ } while (0); \
>+ } \
>+ } \
>+ /* TBodies */ \
>+ for (nsIContent* _node = mParent->nsINode::GetFirstChild(); \
>+ _node; _node = _node->GetNextSibling()) { \
>+ if (_node->IsHTMLElement(nsGkAtoms::tr)) { \
>+ do { \
>+ _trCode \
>+ } while (0); \
>+ } \
>+ if (_node->IsHTMLElement(nsGkAtoms::tbody)) { \
This 'if' could be 'else if', right?
> TableRowsCollection::GetFirstNamedElement(const nsAString& aName, bool& aFound)
> {
> aFound = false;
>- DO_FOR_EACH_ROWGROUP(
>+ DO_FOR_EACH_BY_ORDER({
> Element* item = rows->NamedGetter(aName, aFound);
> if (aFound) {
> return item;
> }
>- );
>+ }, {
>+ nsCOMPtr<nsIAtom> name = NS_Atomize(aName);
>+ NS_ENSURE_TRUE(name, nullptr);
Perhaps move this atomize to be before the macro usage so that we don't repeat it for each <tr> elements.
>+ if (_node &&
>+ ((_node->IsHTMLElement() &&
Is there a need for _node->IsHTMLElement() check here. Don't we do that inside the macro since we have if (_node->IsHTMLElement(nsGkAtoms::tr)) { there.
>+ _node->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
>+ name, eCaseMatters)) ||
2 spaces too much before 'name'
>+ _node->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id,
>+ name, eCaseMatters))) {
ditto
> TableRowsCollection::GetSupportedNames(nsTArray<nsString>& aNames)
> {
>- DO_FOR_EACH_ROWGROUP(
>+ AutoTArray<nsIAtom*, 8> atoms;
>+ DO_FOR_EACH_BY_ORDER({
> nsTArray<nsString> names;
> nsCOMPtr<nsIHTMLCollection> coll = do_QueryInterface(rows);
> if (coll) {
> coll->GetSupportedNames(names);
> for (uint32_t i = 0; i < names.Length(); ++i) {
> if (!aNames.Contains(names[i])) {
> aNames.AppendElement(names[i]);
> }
> }
> }
>- );
>+ }, {
>+ if (_node->HasID()) {
>+ nsIAtom* id = _node->GetID();
>+ MOZ_ASSERT(id != nsGkAtoms::_empty,
>+ "Empty ids don't get atomized");
>+ if (!atoms.Contains(id)) {
>+ atoms.AppendElement(id);
>+ }
>+ }
>+
>+ nsGenericHTMLElement* el = nsGenericHTMLElement::FromContent(_node);
>+ if (el) {
>+ const nsAttrValue* val = el->GetParsedAttr(nsGkAtoms::name);
>+ if (val && val->Type() == nsAttrValue::eAtom) {
>+ nsIAtom* name = val->GetAtomValue();
>+ MOZ_ASSERT(name != nsGkAtoms::_empty,
>+ "Empty names don't get atomized");
>+ if (!atoms.Contains(name)) {
>+ atoms.AppendElement(name);
>+ }
>+ }
>+ }
>+
>+ uint32_t atomsLen = atoms.Length();
>+
>+ nsString* names = aNames.AppendElements(atomsLen);
>+ for (uint32_t i = 0; i < atomsLen; ++i) {
>+ atoms[i]->ToString(names[i]);
>+ }
What if aNames already contains the name, I mean what if it has been added there already in the block which deals with rows.
I think it would be simpler if you just played with strings here and not have separate array for atoms.
Note, if you need to convert atom to string for comparisons etc, nsDependentAtomString can be handy.
I'd like to see a new patch fixing TableRowsCollection::GetSupportedNames.
Attachment #8752045 -
Flags: review?(bugs) → review-
| Assignee | ||
Comment 20•9 years ago
|
||
Thanks for your useful information. I address it all and add a testcase in my patch.
Hi Olli, may I have your review? Thank you.
Attachment #8752045 -
Attachment is obsolete: true
Attachment #8752761 -
Flags: review?(bugs)
| Reporter | ||
Comment 21•9 years ago
|
||
Comment on attachment 8752761 [details] [diff] [review]
Part 2: Bug 1264947 - HTMLTableElement.rows return element in the order. v5
> TableRowsCollection::GetFirstNamedElement(const nsAString& aName, bool& aFound)
> {
> aFound = false;
>- DO_FOR_EACH_ROWGROUP(
>+ nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(aName);
>+ DO_FOR_EACH_BY_ORDER({
> Element* item = rows->NamedGetter(aName, aFound);
> if (aFound) {
> return item;
> }
>- );
>+ }, {
>+ NS_ENSURE_TRUE(nameAtom, nullptr);
move also this NS_ENSURE_TRUE to be next to NS_Atomize(aName);
>+++ b/dom/html/test/test_bug1264947.html
You could have added all the new tests to the existing web-platform-test, but up to you.
Attachment #8752761 -
Flags: review?(bugs) → review+
| Assignee | ||
Comment 22•9 years ago
|
||
(In reply to Olli Pettay [:smaug] from comment #21)
> Comment on attachment 8752761 [details] [diff] [review]
> Part 2: Bug 1264947 - HTMLTableElement.rows return element in the order. v5
>
> > TableRowsCollection::GetFirstNamedElement(const nsAString& aName, bool& aFound)
> > {
> > aFound = false;
> >- DO_FOR_EACH_ROWGROUP(
> >+ nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(aName);
> >+ DO_FOR_EACH_BY_ORDER({
> > Element* item = rows->NamedGetter(aName, aFound);
> > if (aFound) {
> > return item;
> > }
> >- );
> >+ }, {
> >+ NS_ENSURE_TRUE(nameAtom, nullptr);
> move also this NS_ENSURE_TRUE to be next to NS_Atomize(aName);
Will do.
>
> >+++ b/dom/html/test/test_bug1264947.html
> You could have added all the new tests to the existing web-platform-test,
> but up to you.
I will put my tests into existing web-platform-test. Thank you.
| Assignee | ||
Comment 23•9 years ago
|
||
Attachment #8750191 -
Attachment is obsolete: true
Attachment #8753293 -
Flags: review+
| Assignee | ||
Comment 24•9 years ago
|
||
Try result:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=f4fea5191a556bf31cfe9a22ed75d09fd8d44cfc
Attachment #8752761 -
Attachment is obsolete: true
Attachment #8753294 -
Flags: review+
| Assignee | ||
Comment 25•9 years ago
|
||
I upload a new patch because the previous patch missed part of code.
Try result:
https://treeherder.mozilla.org/#/jobs?repo=try&revision=f4fea5191a556bf31cfe9a22ed75d09fd8d44cfc
Attachment #8753294 -
Attachment is obsolete: true
Attachment #8753301 -
Flags: review+
| Assignee | ||
Updated•9 years ago
|
Keywords: checkin-needed
Comment 26•9 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/533d90705f59
https://hg.mozilla.org/integration/mozilla-inbound/rev/ec1046025657
Keywords: checkin-needed
Comment 27•9 years ago
|
||
| bugherder | ||
https://hg.mozilla.org/mozilla-central/rev/533d90705f59
https://hg.mozilla.org/mozilla-central/rev/ec1046025657
Status: NEW → RESOLVED
Closed: 9 years ago
status-firefox49:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla49
You need to log in
before you can comment on or make changes to this bug.
Description
•