Skip to content

[cssom-1] Ensure inline style and corresponding declaration block updates each other properly #2269

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

Merged
merged 2 commits into from
Feb 11, 2018
Merged

Conversation

upsuper
Copy link
Member

@upsuper upsuper commented Feb 3, 2018

This mostly follows how DOMTokenList works in the DOM spec, which has a similar situation that having a live object reflecting an attribute.

This should fix #1559.

@upsuper
Copy link
Member Author

upsuper commented Feb 3, 2018

cc @bzbarsky

@upsuper
Copy link
Member Author

upsuper commented Feb 3, 2018

Note that this cannot bikeshed correctly at this moment, because "attribute change steps" wasn't actually exported from the DOM spec until whatwg/dom#567 which was merged several hours ago.

@upsuper
Copy link
Member Author

upsuper commented Feb 4, 2018

WebKit and Blink don't agree with the part of setProperty. They don't update the attribute when the setting doesn't change value. It seems tricky to me in the sense that I don't think we have a formal definition anywhere about how to compare two values of a property, do we?

Also, if we follow the resolution in #1898 to make setProperty append new value rather than mutate the value in-place, the behavior of WebKit and Blink may become more trickier to be right. Given these, I tend to keep the that part as-is.

@upsuper
Copy link
Member Author

upsuper commented Feb 4, 2018

Also wpt test for this change: web-platform-tests/wpt#9376.


When a <a>CSS declaration block</a> object is created, then:
<ol>
<li>Let <var>owner node</var> be the <a for="CSSStyleDeclaration">owner node</a>.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to also check if the readonly flag is set. Now this will try to get an attribute when doing getComputedStyle(elm) I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you're right. The algorithm for attribute change steps also need updates.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to make this algorithm and attribute change steps check readonly flag.

@zcorpan
Copy link
Member

zcorpan commented Feb 5, 2018

They don't update the attribute when the setting doesn't change value. It seems tricky to me in the sense that I don't think we have a formal definition anywhere about how to compare two values of a property, do we?

We don't I think. But maybe figuring this out can be part of #1898 ?

@upsuper
Copy link
Member Author

upsuper commented Feb 5, 2018

We don't I think. But maybe figuring this out can be part of #1898 ?

Yeah, sure, I guess setProperty part definitely needs further tweaking for that issue.

@@ -2034,6 +2034,25 @@ Note: The serialization of an empty CSS declaration block is the empty string.
Note: The serialization of a non-empty CSS declaration block does not include any surrounding whitespace, i.e., no whitespace appears
before the first property name and no whitespace appears after the final semicolon delimiter that follows the last property value.

A <a>CSS declaration block</a> has these <a>attribute change steps</a> for its <a for="CSSStyleDeclaration">owner node</a>:
<ol>
<li>If the <a for="CSSStyleDeclaration">readonly flag</a> is set, terminate these steps.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can this even happen? The cases when there is an owner node are currently not readonly and there are no plans I am aware of to make them readonly...

There should probably be a note here explaining what this test is about, because it's pretty confusing.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getComputedStyle sets owner node per the spec. But maybe that is a spec bug?

https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I missed that somehow. OK, then this is probably fine. That said, this is the first actual use of owner node that I can see. So if it simplifies things, we could probably avoid setting owner node in getComputedStyle instead of dealing with it here....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think we can set it to null there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can discuss this in a separate PR. I don't think that needs to block this change.

Actually, I have a feeling that having the declaration block from getComputedStyle have the owner node set makes sense. Not sure how useful it is, though.

<li>If <var>owner node</var> is null, or the <a for="CSSStyleDeclaration">readonly flag</a> is set, terminate these steps.
<li>Let <var>value</var> be the result of <a lt="get an attribute by namespace and local name">getting an attribute</a>
given null, "<code>style</code>", and <var>owner node</var>.
<li>If <var>value</var> is not null, let the <a for="CSSStyleDeclaration">declarations</a> be the result of
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/let the/let/ ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to me that there is a convention that we use "the" before associated properties, and no "the" before variables, so I add "the" here. Not sure if my understanding is correct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like that, yeah, though probably not entirely consistent. But we should probably adopt Infra Standard conventions when we update things or write new material for CSSOM (like saying "then return" instead of "terminate these steps").

@@ -2079,6 +2098,8 @@ Setting the {{CSSStyleDeclaration/cssText}} attribute must run these steps:
<li>Empty the <a for="CSSStyleDeclaration">declarations</a>.
<li><a lt="Parse a CSS declaration block">Parse</a> the given value and, if the return value is not the empty list, insert the items in the list
into the <a for="CSSStyleDeclaration">declarations</a>, in <a>specified order</a>.
<li>If the <a for="CSSStyleDeclaration">owner node</a> is not null, <a>set an attribute value</a> for <a for="CSSStyleDeclaration">owner node</a>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really think we should prevent this attribute set from leading to a re-parse. It's a much simpler model than having it re-parse, because in the presence of CSP parsing from the string does NOT give the same results as the thing that was serialized to the string, in general. And since UAs are going to optimize out the reparsing for basic sanity reasons, this is likely to lead to divergence between what the spec theoretically says (but no one would ever do) and what UAs do.

There are also issues around base URIs: set vs serialize-and-reparse treat them differently. I did explicitly mention this in #1559 as a problem with the serialize-and-reparse approach.

Not reviewing the rest of the changes for now given that, because they will need to be modified anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any suggestion for how can we avoid serialize-and-reparse? It seems to me if we want to avoid that, we would need to duplicate many definitions from the DOM spec just for getting rid of the "run attribute change steps" part.

Is there any existing algorithm in the DOM spec helps doing that? If not, I suggest we merge this change to get the spec closer to what browsers do currently, and file a new issue to address the serialize-and-reparse issue, which may need some help from the DOM spec side.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could set a flag while you are setting the attribute, and not do any attribute change steps while that flag is set, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, okay, fair. Thanks for the suggestion.

…ates each other properly.

This mostly follows how `DOMTokenList` works in the DOM spec, which has
a similar situation that having a live object reflecting an attribute.

This should fix #1559.
@upsuper
Copy link
Member Author

upsuper commented Feb 11, 2018

@zcorpan @bzbarsky ping. Are you two fine with the updated version? (The second commit is the change on top of what you have reviewed.)

Copy link
Member

@zcorpan zcorpan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I glossed over the serialize-and-reparse issue in my first review, sorry about that. I think the fix looks good. I added a test for it in web-platform-tests/wpt@dc41ada

@upsuper
Copy link
Member Author

upsuper commented Feb 11, 2018

Thanks for the review and the new test :)

@upsuper upsuper merged commit 79619b8 into w3c:master Feb 11, 2018
@upsuper upsuper deleted the cssom-style-attr branch February 11, 2018 22:38
@zcorpan
Copy link
Member

zcorpan commented Feb 12, 2018

@upsuper
Copy link
Member Author

upsuper commented Feb 12, 2018

Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1197705

I removed the test of setting identical value triggering mutation record. That test would fail Chrome as well, but anyway... We can add that later after we address #1898.

@bzbarsky bzbarsky changed the title [cssom-1] Ensure inline style and corresponding declaration block ates each other properly [cssom-1] Ensure inline style and corresponding declaration block updates each other properly Feb 12, 2018
from a string <var>value</var>.
</ol>

When a <a>CSS declaration block</a> object is created, then:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@upsuper Why is this timing correct? Especially since nothing specifies when these objects are actually created, last I checked...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as it is returned from Element.style, does it matter when the objects are actually created? Browser needs to create it at some point, but before script gets it somehow, whether it exists doesn't really matter, does it?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It matters because the base URI is different at different points in time, depending on what the node document of the element is. So depending on exactly when the creation/parsing happen you will get different behavior for relative URIs in property values....

Maybe that doesn't affect what CSSOM sees, just the actual styling behavior.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... okay. Sounds like something worth raising for css-style-attr I guess... The interaction between the two specs would be fun...

<li>Let <var>owner node</var> be <var>declaration block</var>'s <a for="CSSStyleDeclaration">owner node</a>.
<li>If <var>owner node</var> is null, terminate these steps.
<li>Set <var>declaration block</var>'s <a for="CSSStyleDeclaration">updating flag</a>.
<li><a>Set an attribute value</a> for <var>owner node</var> using "<code>style</code>" and the result of

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't handle mutation events right, but I guess neither does anything else....

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[cssom]Inline style manipulation is somewhere between underspecified and incorrectly specified
3 participants