Bug 96752 - CSS Style is not recalculated when media attribute of style element is changed
Summary: CSS Style is not recalculated when media attribute of style element is changed
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: DOM (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Alexander Shalamov
URL: http://www.w3.org/Style/CSS/Test/Medi...
Keywords:
Depends on:
Blocks: 45017 97006
  Show dependency treegraph
 
Reported: 2012-09-14 04:19 PDT by Alexander Shalamov
Modified: 2012-10-09 14:53 PDT (History)
13 users (show)

See Also:


Attachments
Patch 1 (2.39 KB, patch)
2012-09-14 04:27 PDT, Alexander Shalamov
webkit.review.bot: commit-queue-
Details | Formatted Diff | Diff
Patch 2 (2.55 KB, patch)
2012-09-14 04:44 PDT, Alexander Shalamov
no flags Details | Formatted Diff | Diff
Patch 3 (2.59 KB, patch)
2012-09-14 05:42 PDT, Alexander Shalamov
rniwa: review-
Details | Formatted Diff | Diff
Patch 4 (4.35 KB, patch)
2012-09-18 05:32 PDT, Alexander Shalamov
webkit.review.bot: commit-queue-
Details | Formatted Diff | Diff
Patch 5 (5.89 KB, patch)
2012-09-19 00:59 PDT, Alexander Shalamov
no flags Details | Formatted Diff | Diff
Patch 6 (5.95 KB, patch)
2012-10-05 03:15 PDT, Alexander Shalamov
no flags Details | Formatted Diff | Diff
Patch 7 (5.94 KB, patch)
2012-10-05 03:29 PDT, Alexander Shalamov
kenneth: review-
Details | Formatted Diff | Diff
Patch 8 (6.11 KB, patch)
2012-10-08 04:44 PDT, Alexander Shalamov
no flags Details | Formatted Diff | Diff
Patch 9 (6.51 KB, patch)
2012-10-09 05:03 PDT, Alexander Shalamov
kenneth: review+
Details | Formatted Diff | Diff
Patch 10 (6.45 KB, patch)
2012-10-09 12:07 PDT, Alexander Shalamov
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Shalamov 2012-09-14 04:19:34 PDT
When "media" attribute of style element is changed, style should be recalculated.
Comment 1 Alexander Shalamov 2012-09-14 04:27:52 PDT
Created attachment 164099 [details]
Patch 1

For initial review.
I would like to get opinion about new layout test.
Should I write new layout test or we could import w3c media query tests?
Comment 2 WebKit Review Bot 2012-09-14 04:37:02 PDT
Comment on attachment 164099 [details]
Patch 1

Attachment 164099 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/13851476
Comment 3 Alexander Shalamov 2012-09-14 04:44:10 PDT
Created attachment 164105 [details]
Patch 2

+#include "MediaList.h"
Comment 4 WebKit Review Bot 2012-09-14 04:49:08 PDT
Attachment 164105 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/WebCore/ChangeLog', u'Source/WebCor..." exit_code: 1
Source/WebCore/html/HTMLStyleElement.cpp:37:  Alphabetical sorting problem.  [build/include_order] [4]
Total errors found: 1 in 3 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 5 Alexander Shalamov 2012-09-14 05:42:38 PDT
Created attachment 164120 [details]
Patch 3

fixed include order
Comment 6 Ryosuke Niwa 2012-09-17 14:22:59 PDT
Comment on attachment 164120 [details]
Patch 3

View in context: https://bugs.webkit.org/attachment.cgi?id=164120&action=review

> Source/WebCore/ChangeLog:10
> +        No new tests (OOPS!).

We clearly need tests.
Comment 7 Andreas Kling 2012-09-17 14:39:08 PDT
Comment on attachment 164120 [details]
Patch 3

View in context: https://bugs.webkit.org/attachment.cgi?id=164120&action=review

> Source/WebCore/html/HTMLStyleElement.cpp:83
> +    HTMLElement::attributeChanged(attribute);
> +    if (attribute.name() == mediaAttr && inDocument()
> +        && !document()->parsing() && document()->renderer() && m_sheet) {
> +        RefPtr<MediaQuerySet> mediaQueries = MediaQuerySet::createAllowingDescriptionSyntax(attribute.value());
> +        m_sheet->setMediaQueries(mediaQueries.release());
> +        document()->styleResolverChanged(DeferRecalcStyle);
> +    }

This logic should be in parseAttribute().
Comment 8 Alexander Shalamov 2012-09-18 05:32:50 PDT
Created attachment 164538 [details]
Patch 4

- Added new layout test
- Moved code from HTMLStyleElement::attributeChanged to HTMLStyleElement::parseAttribute
Comment 9 Kenneth Rohde Christiansen 2012-09-18 08:00:00 PDT
Comment on attachment 164538 [details]
Patch 4

View in context: https://bugs.webkit.org/attachment.cgi?id=164538&action=review

> LayoutTests/fast/media/mq-js-update-media-expected.txt:6
> +layer at (0,0) size 800x600
> +  RenderView at (0,0) size 800x600
> +layer at (0,0) size 800x216
> +  RenderBlock {HTML} at (0,0) size 800x216
> +    RenderBody {BODY} at (8,8) size 784x200
> +      RenderBlock {DIV} at (0,0) size 200x200

Wasnt it better making this a text output? like query and print the color of the div?

> Source/WebCore/ChangeLog:13
> +        Reviewed by NOBODY (OOPS!).
> +
> +        When "media" attribute of style element is changed, style is recalculated.
> +
> +        Test: fast/media/mq-js-update-media.html
> +
> +        * css/CSSStyleSheet.cpp:
> +        (WebCore::CSSStyleSheet::setMediaQueries):

Please write HOW you are fixing this

> Source/WebCore/css/CSSStyleSheet.cpp:210
> +    if (m_mediaCSSOMWrapper && m_mediaQueries)
> +        m_mediaCSSOMWrapper->reattach(m_mediaQueries.get());

Is this efficient?
Comment 10 WebKit Review Bot 2012-09-18 08:19:22 PDT
Comment on attachment 164538 [details]
Patch 4

Attachment 164538 [details] did not pass chromium-ews (chromium-xvfb):
Output: http://queues.webkit.org/results/13900214

New failing tests:
fast/media/mq-js-update-media.html
Comment 11 Alexander Shalamov 2012-09-18 23:17:59 PDT
(In reply to comment #9)
> (From update of attachment 164538 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=164538&action=review
> 
> > LayoutTests/fast/media/mq-js-update-media-expected.txt:6
> > +layer at (0,0) size 800x600
> > +  RenderView at (0,0) size 800x600
> > +layer at (0,0) size 800x216
> > +  RenderBlock {HTML} at (0,0) size 800x216
> > +    RenderBody {BODY} at (8,8) size 784x200
> > +      RenderBlock {DIV} at (0,0) size 200x200
> 
> Wasnt it better making this a text output? like query and print the color of the div?

I was thinking that getting render tree is faster than dumping text from test runner. I will rewrite test to get text output.

> 
> > Source/WebCore/ChangeLog:13
> > +        Reviewed by NOBODY (OOPS!).
> > +
> > +        When "media" attribute of style element is changed, style is recalculated.
> > +
> > +        Test: fast/media/mq-js-update-media.html
> > +
> > +        * css/CSSStyleSheet.cpp:
> > +        (WebCore::CSSStyleSheet::setMediaQueries):
> 
> Please write HOW you are fixing this

I will. Thanks.

> > Source/WebCore/css/CSSStyleSheet.cpp:210
> > +    if (m_mediaCSSOMWrapper && m_mediaQueries)
> > +        m_mediaCSSOMWrapper->reattach(m_mediaQueries.get());
> 
> Is this efficient?

CSSOM wrapper is lazily initialised and never updated. When media query is updated CSSOM wrapper should be updated as well. Those lines are required to update media query CSSOM wrapper.
Comment 12 Alexander Shalamov 2012-09-19 00:59:27 PDT
Created attachment 164682 [details]
Patch 5

- Added detailed explanation to changelog.
- Modified layout test that outputs text rather than render tree.
Comment 13 Alexander Shalamov 2012-10-05 03:15:31 PDT
Created attachment 167295 [details]
Patch 6

Rebased to master
Comment 14 WebKit Review Bot 2012-10-05 03:17:47 PDT
Attachment 167295 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'LayoutTests/ChangeLog', u'LayoutTests/fast..." exit_code: 1
Source/WebCore/html/HTMLStyleElement.cpp:88:  Weird number of spaces at line-start.  Are you using a 4-space indent?  [whitespace/indent] [3]
Total errors found: 1 in 6 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 15 Alexander Shalamov 2012-10-05 03:29:59 PDT
Created attachment 167298 [details]
Patch 7

Looks like check-webkit-style become stricter. Fix should make bot happy.
Comment 16 Kenneth Rohde Christiansen 2012-10-05 09:22:40 PDT
Comment on attachment 167298 [details]
Patch 7

View in context: https://bugs.webkit.org/attachment.cgi?id=167298&action=review

> LayoutTests/fast/media/mq-js-update-media.html:13
> +          if (window.testRunner) {
> +              testRunner.dumpAsText();
> +              testRunner.waitUntilDone();
> +          }

Why not do this outside the function?

> LayoutTests/fast/media/mq-js-update-media.html:19
> +          test(divComputedStyle.backgroundColor, "255", "Div should have rgb(255, 0, 0) background color.");

Maybe there is a shouldBe method for comparing this

> LayoutTests/fast/media/mq-js-update-media.html:33
> +      function test(actual, expected, message) {
> +          var re = /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/;
> +          var color = re.exec(actual)[1];
> +          if(color === expected)

This test should include the js test frame work used by other tests, and ie. not define log() itself.
Comment 17 Alexander Shalamov 2012-10-08 04:44:47 PDT
Created attachment 167524 [details]
Patch 8

- Use testharness.js and testharnessreport.js
- Use getRGBColorValue instead of regexp to compare color component values
Comment 18 Kenneth Rohde Christiansen 2012-10-08 04:52:57 PDT
Comment on attachment 167524 [details]
Patch 8

View in context: https://bugs.webkit.org/attachment.cgi?id=167524&action=review

> Source/WebCore/html/HTMLStyleElement.cpp:87
> +    else if (attribute.name() == mediaAttr && inDocument() && !document()->parsing() && document()->renderer() && m_sheet) {

So what happens if it is parsing? Then this will happen when it is finished? Can it be tested? Why do you need the renderer() check?
Comment 19 Alexander Shalamov 2012-10-08 05:39:34 PDT
(In reply to comment #18)
> (From update of attachment 167524 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=167524&action=review
> 
> > Source/WebCore/html/HTMLStyleElement.cpp:87
> > +    else if (attribute.name() == mediaAttr && inDocument() && !document()->parsing() && document()->renderer() && m_sheet) {
> 
> So what happens if it is parsing? Then this will happen when it is finished? Can it be tested?

I have to add javascript code to body and check that case. Thanks.

> Why do you need the renderer() check?

If document is being destroyed and there is no renderer, there is no point to recalc style.
Comment 20 Kenneth Rohde Christiansen 2012-10-08 06:10:06 PDT
> If document is being destroyed and there is no renderer, there is no point to recalc style.

If that is the only case that can happen it sounds fine, but maybe a comment makes sense, like // The render will only be null doing destruction of the document, in which case we don't need to recalculate.

But then again, can't people use the media query listeners from javascript and actually need to get notified? ie. media queries doesn't always depend on style
Comment 21 Alexander Shalamov 2012-10-09 05:03:56 PDT
Created attachment 167736 [details]
Patch 9

- Modified test to verify that media query is updated when document is parsed
Comment 22 Alexander Shalamov 2012-10-09 05:07:34 PDT
(In reply to comment #20)
> > If document is being destroyed and there is no renderer, there is no point to recalc style.
> 
> If that is the only case that can happen it sounds fine, but maybe a comment makes sense, like // The render will only be null doing destruction of the document, in which case we don't need to recalculate.
> 
> But then again, can't people use the media query listeners from javascript and actually need to get notified? ie. media queries doesn't always depend on style

Are you talking about the case when style node is detached from document?

> > Source/WebCore/html/HTMLStyleElement.cpp:87
> > +    else if (attribute.name() == mediaAttr && inDocument() && !document()->parsing() && document()->renderer() && m_sheet) {
> 
> So what happens if it is parsing? Then this will happen when it is finished? Can it be tested?

I removed that condition, I was too strict. Checked all implementations of *::parseAttribute and parsing state is never checked.
Comment 23 Kenneth Rohde Christiansen 2012-10-09 05:17:01 PDT
> > But then again, can't people use the media query listeners from javascript and actually need to get notified? ie. media queries doesn't always depend on style

Or say when it is not create yet.

I mean orientation can change at any point and you can write scripts 

mql = window.msMatchMedia("(orientation: landscape)");

function orientationChange(mql) 
{
  if (mql.matches) 
  {
     ... // landscape
  } 
  else 
  {
     ... // portrait
  }
}

mql.addListener(orientationChange);
Comment 24 Kenneth Rohde Christiansen 2012-10-09 05:17:42 PDT
> mql = window.msMatchMedia("(orientation: landscape)");

matchMedia :-) I had to look up the documentation and used the MS one :-)
Comment 25 Alexander Shalamov 2012-10-09 05:31:39 PDT
(In reply to comment #24)
> > mql = window.msMatchMedia("(orientation: landscape)");
> 
> matchMedia :-) I had to look up the documentation and used the MS one :-)

If there are media listeners, they would be notified and their media query re-evaluated.

Document::styleResolverChanged calls evaluateMediaQueryList() that would notify listeners if there are any.
Comment 26 Kenneth Rohde Christiansen 2012-10-09 05:32:24 PDT
ok good, could you test that? just to make sure
Comment 27 Alexander Shalamov 2012-10-09 05:41:03 PDT
(In reply to comment #26)
> ok good, could you test that? just to make sure

Sure
Comment 28 Kenneth Rohde Christiansen 2012-10-09 06:47:40 PDT
Comment on attachment 167736 [details]
Patch 9

OK LGTM, but the added test would be nice!
Comment 29 Darin Adler 2012-10-09 10:02:58 PDT
Comment on attachment 167736 [details]
Patch 9

View in context: https://bugs.webkit.org/attachment.cgi?id=167736&action=review

> Source/WebCore/html/HTMLStyleElement.cpp:89
> +        RefPtr<MediaQuerySet> mediaQueries = MediaQuerySet::createAllowingDescriptionSyntax(attribute.value());
> +        m_sheet->setMediaQueries(mediaQueries.release());

Not sure the local variable here makes the code easier to read. Iā€™d just do it on one line.
Comment 30 Alexander Shalamov 2012-10-09 11:53:13 PDT
(In reply to comment #28)
> (From update of attachment 167736 [details])
> OK LGTM, but the added test would be nice!

Only test case I managed to implement didn't test what I wanted. I had an iframe and then I was changing style for iframe that triggered notification for media listeners in sub-document.

Unfortunately I don't have valid test for the use-case you've mentioned. Whenever there is a style change based on media query, document style is recalculated, but properties like width (frame), height, device-width, color, etc are not affected, therefore, notification for media query listeners is not fired.

I also tried to change font-size and were thinking that if media query uses rem units I could trigger notification, but for some reason that didn't work either, maybe there is a bug in media query evaluator for length calculation.
Comment 31 Alexander Shalamov 2012-10-09 12:07:26 PDT
Created attachment 167811 [details]
Patch 10

- Fixed code according to Darin's comments
Comment 32 Kenneth Rohde Christiansen 2012-10-09 14:36:47 PDT
Comment on attachment 167811 [details]
Patch 10

You can add the test in another patch. I am sure more fixes are needed as few features (orientation being one) actually trigger a reevaluated media query
Comment 33 WebKit Review Bot 2012-10-09 14:53:18 PDT
Comment on attachment 167811 [details]
Patch 10

Clearing flags on attachment: 167811

Committed r130816: <http://trac.webkit.org/changeset/130816>
Comment 34 WebKit Review Bot 2012-10-09 14:53:25 PDT
All reviewed patches have been landed.  Closing bug.