RESOLVED FIXED 106616
[Microdata] itemtype attribute must update correctly on adding or removing tokens
https://bugs.webkit.org/show_bug.cgi?id=106616
Summary [Microdata] itemtype attribute must update correctly on adding or removing to...
Arko Saha
Reported 2013-01-10 16:33:21 PST
itemType.add() and itemType.remove() must update the itemtype attribute properly. Test: var element = document.createElement('div'); element.itemType.add('foo'); element.itemType.add('FOO'); alert(element.getAttribute('itemtype')); Expected result: element.getAttribute('itemtype') should return 'foo FOO' Actual result: returns null Same behavior can be observed with itemref and itemprop attribute.
Attachments
Patch (25.63 KB, patch)
2013-01-10 16:55 PST, Arko Saha
no flags
Patch2 (23.98 KB, patch)
2013-01-23 16:35 PST, Arko Saha
no flags
Patch3 (24.03 KB, patch)
2013-01-23 18:32 PST, Arko Saha
rniwa: review+
Patch for landing (28.26 KB, patch)
2013-01-24 11:47 PST, Arko Saha
no flags
Arko Saha
Comment 1 2013-01-10 16:55:54 PST
Ryosuke Niwa
Comment 2 2013-01-15 12:14:04 PST
Comment on attachment 182226 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=182226&action=review > Source/WebCore/html/MicroDataAttributeTokenList.cpp:56 > +void MicroDataAttributeTokenList::setValue(const AtomicString& value) > +{ > + m_element->setAttribute(m_attributeName, value); > +} > + > +void MicroDataAttributeTokenList::resetValue(const AtomicString& value) > +{ > + DOMSettableTokenList::setValue(value); > +} I don't like bi-directionally updated data structures... Why don't we do this inside Node::setItemRef and friends instead?
Arko Saha
Comment 3 2013-01-23 16:35:44 PST
Arko Saha
Comment 4 2013-01-23 16:37:23 PST
Let me try to explain the issue, The actual problem is with adding tokens to itemref attribute. element.itemRef.add('foo'); In this case setAttribute() method is not getting called for given element. As a result element.getAttribute('itemtype') returns null Code flow is as below: 0 WebCore::DOMSettableTokenList::setValue DOMSettableTokenList.cpp 88 1 WebCore::DOMTokenList::add DOMTokenList.cpp 89 2 WebCore::DOMSettableTokenList::add DOMSettableTokenList.cpp 54 3 WebCore::jsDOMTokenListPrototypeFunctionAdd JSDOMTokenList.cpp 271 It does not call Node::setItemRef(). DOMSettableTokenList::add() is getting called in this case, which internally calls DOMSettableTokenList::setValue to update the tokens and value of DOMSettableTokenList. In the patch I have override setValue() method in MicroDataAttributeTokenList. So that we can call setAttribute() to update the attribute. With my change the code flow will be like : 0 WebCore::MicroDataAttributeTokenList::setValue MicroDataAttributeTokenList.cpp 50 1 WebCore::DOMTokenList::add DOMTokenList.cpp 89 2 WebCore::DOMSettableTokenList::add DOMSettableTokenList.cpp 54 3 WebCore::jsDOMTokenListPrototypeFunctionAdd JSDOMTokenList.cpp 271
Ryosuke Niwa
Comment 5 2013-01-23 16:44:39 PST
Comment on attachment 184341 [details] Patch2 View in context: https://bugs.webkit.org/attachment.cgi?id=184341&action=review > Source/WebCore/dom/NodeRareData.h:52 > +using namespace HTMLNames; > + We don't need this, right? > Source/WebCore/html/MicroDataAttributeTokenList.cpp:55 > + if (oldValue != newValue) > + m_element->setAttribute(m_attributeName, newValue); What happens to this token list when someone manually sets the attribute? e.g. element.setAttribute('itemprop', ~); > Source/WebCore/html/MicroDataAttributeTokenList.h:43 > +typedef int ExceptionCode; Why do we need this?
Arko Saha
Comment 6 2013-01-23 17:09:50 PST
(In reply to comment #5) > > Source/WebCore/dom/NodeRareData.h:52 > > +using namespace HTMLNames; > > + > > We don't need this, right? This is required else we need to pass HTMLNames::itempropAttr while creating MicroDataAttributeTokenList as below: + DOMSettableTokenList* itemProp(Node* node) const { if (!m_itemProp) - m_itemProp = DOMSettableTokenList::create(); + m_itemProp = MicroDataAttributeTokenList::create(toElement(node), HTMLNames::itempropAttr); return m_itemProp.get(); } > > Source/WebCore/html/MicroDataAttributeTokenList.cpp:55 > > + if (oldValue != newValue) > > + m_element->setAttribute(m_attributeName, newValue); > > What happens to this token list when someone manually sets the attribute? e.g. element.setAttribute('itemprop', ~); Code flow in that case will be like: 0 WebCore::MicroDataAttributeTokenList::setValue MicroDataAttributeTokenList.cpp 50 0x7fb94d1ebc89 1 WebCore::Node::setItemProp Node.cpp 2536 0x7fb94cfb7bbf 2 WebCore::HTMLElement::parseAttribute HTMLElement.cpp 233 0x7fb94d16510c 3 WebCore::Element::attributeChanged Element.cpp 816 0x7fb94cf6830c 4 WebCore::StyledElement::attributeChanged StyledElement.cpp 168 0x7fb94d003235 5 WebCore::Element::didAddAttribute Element.cpp 2561 0x7fb94cf6e66a 6 WebCore::Element::addAttributeInternal Element.cpp 1785 0x7fb94cf6bc14 7 WebCore::Element::setAttributeInternal Element.cpp 771 0x7fb94cf72ab7 8 WebCore::Element::setAttribute Element.cpp 749 0x7fb94cf680a5 9 WebCore::jsElementPrototypeFunctionSetAttribute JSElement.cpp 1773 0x7fb94da0e83d setValue() is called from Element::setAttribute() -> Element::attributeChanged(). So no need to call setAttribute() from MicroDataAttributeTokenList::setValue as attribute value is already updated. > > Source/WebCore/html/MicroDataAttributeTokenList.h:43 > > +typedef int ExceptionCode; > > Why do we need this? My bad, this is not required.
Ryosuke Niwa
Comment 7 2013-01-23 17:22:33 PST
(In reply to comment #6) > (In reply to comment #5) > > > Source/WebCore/dom/NodeRareData.h:52 > > > +using namespace HTMLNames; > > > + > > > > We don't need this, right? > > This is required else we need to pass HTMLNames::itempropAttr while creating MicroDataAttributeTokenList as below: > > + DOMSettableTokenList* itemProp(Node* node) const > { > if (!m_itemProp) > - m_itemProp = DOMSettableTokenList::create(); > + m_itemProp = MicroDataAttributeTokenList::create(toElement(node), HTMLNames::itempropAttr); > return m_itemProp.get(); > } > > > > Source/WebCore/html/MicroDataAttributeTokenList.cpp:55 > > > + if (oldValue != newValue) > > > + m_element->setAttribute(m_attributeName, newValue); > > > > What happens to this token list when someone manually sets the attribute? e.g. element.setAttribute('itemprop', ~); > > Code flow in that case will be like: > 0 WebCore::MicroDataAttributeTokenList::setValue MicroDataAttributeTokenList.cpp 50 0x7fb94d1ebc89 > 1 WebCore::Node::setItemProp Node.cpp 2536 0x7fb94cfb7bbf We might want to add something like setValueFromAttribute or setValueInternal to clarify the semantics here. Otherwise, it look as if we're gonna fall into an infinite loop. Also, it's inefficient to get the string, compare the string, and set it.
Arko Saha
Comment 8 2013-01-23 18:32:28 PST
Created attachment 184373 [details] Patch3 Incorporated review comments.
Arko Saha
Comment 9 2013-01-24 11:47:22 PST
Created attachment 184544 [details] Patch for landing Added new files MicroDataAttributeTokenList.{cpp,h} to xcode project.
WebKit Review Bot
Comment 10 2013-01-24 16:02:18 PST
Comment on attachment 184544 [details] Patch for landing Clearing flags on attachment: 184544 Committed r140745: <http://trac.webkit.org/changeset/140745>
WebKit Review Bot
Comment 11 2013-01-24 16:02:26 PST
All reviewed patches have been landed. Closing bug.
Note You need to log in before you can comment on or make changes to this bug.