Bug 106616 - [Microdata] itemtype attribute must update correctly on adding or removing tokens
Summary: [Microdata] itemtype attribute must update correctly on adding or removing to...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: DOM (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Arko Saha
URL:
Keywords:
Depends on:
Blocks: 92986
  Show dependency treegraph
 
Reported: 2013-01-10 16:33 PST by Arko Saha
Modified: 2013-01-24 16:02 PST (History)
5 users (show)

See Also:


Attachments
Patch (25.63 KB, patch)
2013-01-10 16:55 PST, Arko Saha
no flags Details | Formatted Diff | Diff
Patch2 (23.98 KB, patch)
2013-01-23 16:35 PST, Arko Saha
no flags Details | Formatted Diff | Diff
Patch3 (24.03 KB, patch)
2013-01-23 18:32 PST, Arko Saha
rniwa: review+
Details | Formatted Diff | Diff
Patch for landing (28.26 KB, patch)
2013-01-24 11:47 PST, Arko Saha
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Arko Saha 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.
Comment 1 Arko Saha 2013-01-10 16:55:54 PST
Created attachment 182226 [details]
Patch
Comment 2 Ryosuke Niwa 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?
Comment 3 Arko Saha 2013-01-23 16:35:44 PST
Created attachment 184341 [details]
Patch2
Comment 4 Arko Saha 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
Comment 5 Ryosuke Niwa 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?
Comment 6 Arko Saha 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.
Comment 7 Ryosuke Niwa 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.
Comment 8 Arko Saha 2013-01-23 18:32:28 PST
Created attachment 184373 [details]
Patch3

Incorporated review comments.
Comment 9 Arko Saha 2013-01-24 11:47:22 PST
Created attachment 184544 [details]
Patch for landing

Added new files MicroDataAttributeTokenList.{cpp,h} to xcode project.
Comment 10 WebKit Review Bot 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>
Comment 11 WebKit Review Bot 2013-01-24 16:02:26 PST
All reviewed patches have been landed.  Closing bug.