Title: [172826] trunk
Revision
172826
Author
[email protected]
Date
2014-08-20 20:33:18 -0700 (Wed, 20 Aug 2014)

Log Message

CSS: Implement the :placeholder-shown pseudo-class from Selectors Level 4
https://bugs.webkit.org/show_bug.cgi?id=118162

Reviewed by Antti Koivisto.

Source/WebCore:

Previously, HTMLTextFormControlElement was using some mix of its own state
and style to change the visibility of the placeholder. That approach was a little
bit too fragile, and we do not want the style to depends on the renderer() since
that creates circular dependencies.

The biggest change here is refactoring HTMLTextFormControlElement to have
1) An explicit "visible placeholder" state.
2) Separate the textUpdate() from the visibilityUpdate().
3) Remove the dependencies between the Element's style and the placeholder's style.
   This is done by simply using display:none; on the placeholder so that its parent's visibility
   is irrelevant.

When matching the selector, the style is set as unique since style sharing does not deal with
the changes of HTMLTextFormControlElement.

Tests: fast/css/placeholder-shown-basics.html
       fast/selectors/placeholder-shown-long-adjacent-backtracking.html
       fast/selectors/placeholder-shown-sibling-style-update.html
       fast/selectors/placeholder-shown-style-update.html
       fast/selectors/placeholder-shown-with-input-basics.html
       fast/selectors/placeholder-shown-with-textarea-basics.html

* css/CSSSelector.cpp:
(WebCore::CSSSelector::selectorText):
Add the CSS Selector description for CSSOM.

* css/CSSSelector.h:
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkOne):
* css/SelectorCheckerTestFunctions.h:
(WebCore::isPlaceholderShown):
* css/SelectorPseudoClassAndCompatibilityElementMap.in:
* css/html.css:
(::-webkit-input-placeholder):
Previously, the display was forced through the UA stylesheet. Since the display is now part
of the placeholder visibility, it is explicitly handled by HTMLTextFormControlElement and
its subclasses.

* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::addPseudoClassType):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
(WebCore::SelectorCompiler::makeUniqueIfNecessaryAndTestIsPlaceholderShown):
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasPlaceholderShown):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::parseAttribute):
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::updateValue):
(WebCore::HTMLTextAreaElement::setValueCommon):
(WebCore::HTMLTextAreaElement::updatePlaceholderText):
* html/HTMLTextFormControlElement.cpp:
(WebCore::HTMLTextFormControlElement::HTMLTextFormControlElement):
(WebCore::HTMLTextFormControlElement::dispatchFocusEvent):
(WebCore::HTMLTextFormControlElement::dispatchBlurEvent):
(WebCore::HTMLTextFormControlElement::placeholderShouldBeVisible):
(WebCore::HTMLTextFormControlElement::updatePlaceholderVisibility):
(WebCore::HTMLTextFormControlElement::selectionDirection):
(WebCore::HTMLTextFormControlElement::restoreCachedSelection):
(WebCore::HTMLTextFormControlElement::parseAttribute):
(WebCore::HTMLTextFormControlElement::hidePlaceholder):
(WebCore::HTMLTextFormControlElement::showPlaceholderIfNecessary):
* html/HTMLTextFormControlElement.h:
(WebCore::HTMLTextFormControlElement::isPlaceholderVisible):
(WebCore::HTMLTextFormControlElement::cachedSelectionDirection):
* html/TextFieldInputType.cpp:
(WebCore::TextFieldInputType::updatePlaceholderText):
(WebCore::TextFieldInputType::subtreeHasChanged):
(WebCore::TextFieldInputType::updateInnerTextValue):
* rendering/RenderTextControl.cpp:
(WebCore::RenderTextControl::styleDidChange):
* testing/Internals.cpp:
(WebCore::Internals::visiblePlaceholder):

LayoutTests:

Add basic test coverage for common operations: styling, querySelector, CSSOM.

The layout test failure of placeholder-shown-sibling-style-update.html seems unrelated
to this patch, it fails in many more cases. This will be investigated separately, the failure
are used as expected values for now.

* fast/css/css-selector-text-expected.txt:
* fast/css/css-selector-text.html:
* fast/css/css-set-selector-text-expected.txt:
* fast/css/css-set-selector-text.html:
* fast/css/placeholder-shown-basics-expected.html: Added.
* fast/css/placeholder-shown-basics.html: Added.
* fast/selectors/placeholder-shown-long-adjacent-backtracking-expected.txt: Added.
* fast/selectors/placeholder-shown-long-adjacent-backtracking.html: Added.
* fast/selectors/placeholder-shown-sibling-style-update-expected.txt: Added.
* fast/selectors/placeholder-shown-sibling-style-update.html: Added.
* fast/selectors/placeholder-shown-style-update-expected.txt: Added.
* fast/selectors/placeholder-shown-style-update.html: Added.
* fast/selectors/placeholder-shown-with-input-basics-expected.txt: Added.
* fast/selectors/placeholder-shown-with-input-basics.html: Added.
* fast/selectors/placeholder-shown-with-textarea-basics-expected.txt: Added.
* fast/selectors/placeholder-shown-with-textarea-basics.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (172825 => 172826)


--- trunk/LayoutTests/ChangeLog	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/LayoutTests/ChangeLog	2014-08-21 03:33:18 UTC (rev 172826)
@@ -1,3 +1,33 @@
+2014-08-20  Benjamin Poulain  <[email protected]>
+
+        CSS: Implement the :placeholder-shown pseudo-class from Selectors Level 4
+        https://bugs.webkit.org/show_bug.cgi?id=118162
+
+        Reviewed by Antti Koivisto.
+
+        Add basic test coverage for common operations: styling, querySelector, CSSOM.
+
+        The layout test failure of placeholder-shown-sibling-style-update.html seems unrelated
+        to this patch, it fails in many more cases. This will be investigated separately, the failure
+        are used as expected values for now.
+
+        * fast/css/css-selector-text-expected.txt:
+        * fast/css/css-selector-text.html:
+        * fast/css/css-set-selector-text-expected.txt:
+        * fast/css/css-set-selector-text.html:
+        * fast/css/placeholder-shown-basics-expected.html: Added.
+        * fast/css/placeholder-shown-basics.html: Added.
+        * fast/selectors/placeholder-shown-long-adjacent-backtracking-expected.txt: Added.
+        * fast/selectors/placeholder-shown-long-adjacent-backtracking.html: Added.
+        * fast/selectors/placeholder-shown-sibling-style-update-expected.txt: Added.
+        * fast/selectors/placeholder-shown-sibling-style-update.html: Added.
+        * fast/selectors/placeholder-shown-style-update-expected.txt: Added.
+        * fast/selectors/placeholder-shown-style-update.html: Added.
+        * fast/selectors/placeholder-shown-with-input-basics-expected.txt: Added.
+        * fast/selectors/placeholder-shown-with-input-basics.html: Added.
+        * fast/selectors/placeholder-shown-with-textarea-basics-expected.txt: Added.
+        * fast/selectors/placeholder-shown-with-textarea-basics.html: Added.
+
 2014-08-20  Benjamin Poulain  <[email protected]>
 
         Remove HTMLInputElement's suggestedValue

Modified: trunk/LayoutTests/fast/css/css-selector-text-expected.txt (172825 => 172826)


--- trunk/LayoutTests/fast/css/css-selector-text-expected.txt	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/LayoutTests/fast/css/css-selector-text-expected.txt	2014-08-21 03:33:18 UTC (rev 172826)
@@ -40,6 +40,8 @@
 PASS parseThenSerializeRule(':hover { }') is ':hover { }'
 PASS parseThenSerializeRule(':indeterminate { }') is ':indeterminate { }'
 PASS parseThenSerializeRule(':link { }') is ':link { }'
+PASS parseThenSerializeRule(':not(:placeholder-shown) { }') is ':not(:placeholder-shown) { }'
+PASS parseThenSerializeRule(':placeholder-shown { }') is ':placeholder-shown { }'
 PASS parseThenSerializeRule(':root { }') is ':root { }'
 PASS parseThenSerializeRule(':target { }') is ':target { }'
 PASS parseThenSerializeRule(':visited { }') is ':visited { }'

Modified: trunk/LayoutTests/fast/css/css-selector-text.html (172825 => 172826)


--- trunk/LayoutTests/fast/css/css-selector-text.html	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/LayoutTests/fast/css/css-selector-text.html	2014-08-21 03:33:18 UTC (rev 172826)
@@ -71,6 +71,8 @@
 testSelectorRoundTrip(":hover");
 testSelectorRoundTrip(":indeterminate");
 testSelectorRoundTrip(":link");
+testSelectorRoundTrip(":not(:placeholder-shown)");
+testSelectorRoundTrip(":placeholder-shown");
 testSelectorRoundTrip(":root");
 testSelectorRoundTrip(":target");
 testSelectorRoundTrip(":visited");

Modified: trunk/LayoutTests/fast/css/css-set-selector-text-expected.txt (172825 => 172826)


--- trunk/LayoutTests/fast/css/css-set-selector-text-expected.txt	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/LayoutTests/fast/css/css-set-selector-text-expected.txt	2014-08-21 03:33:18 UTC (rev 172826)
@@ -50,6 +50,8 @@
 PASS setThenReadSelectorText(':hover') is ':hover'
 PASS setThenReadSelectorText(':indeterminate') is ':indeterminate'
 PASS setThenReadSelectorText(':link') is ':link'
+PASS setThenReadSelectorText(':not(:placeholder-shown)') is ':not(:placeholder-shown)'
+PASS setThenReadSelectorText(':placeholder-shown') is ':placeholder-shown'
 PASS setThenReadSelectorText(':root') is ':root'
 PASS setThenReadSelectorText(':target') is ':target'
 PASS setThenReadSelectorText(':visited') is ':visited'

Modified: trunk/LayoutTests/fast/css/css-set-selector-text.html (172825 => 172826)


--- trunk/LayoutTests/fast/css/css-set-selector-text.html	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/LayoutTests/fast/css/css-set-selector-text.html	2014-08-21 03:33:18 UTC (rev 172826)
@@ -88,6 +88,8 @@
 testSelectorRoundTrip(":hover");
 testSelectorRoundTrip(":indeterminate");
 testSelectorRoundTrip(":link");
+testSelectorRoundTrip(":not(:placeholder-shown)");
+testSelectorRoundTrip(":placeholder-shown");
 testSelectorRoundTrip(":root");
 testSelectorRoundTrip(":target");
 testSelectorRoundTrip(":visited");

Added: trunk/LayoutTests/fast/css/placeholder-shown-basics-expected.html (0 => 172826)


--- trunk/LayoutTests/fast/css/placeholder-shown-basics-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/placeholder-shown-basics-expected.html	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        input, textarea {
+            height: 8px;
+        }
+        .placeholder-shown {
+            background-color: green;
+        }
+    </style>
+</head>
+<body>
+    <p>This test checks how various input elements are styled when :placeholder-shown is applied.</p>
+    <div>
+        <textarea></textarea>
+        <textarea placeholder></textarea>
+        <textarea placeholder="WebKit" class="placeholder-shown"></textarea>
+        <textarea placeholder="WebKit">Foobar</textarea>
+    </div>
+    <div>
+        <input>
+        <input placeholder>
+        <input placeholder="WebKit" class="placeholder-shown">
+        <input placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="">
+        <input type="" placeholder>
+        <input type="" placeholder="WebKit" class="placeholder-shown">
+        <input type="" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="hidden">
+        <input type="hidden" placeholder>
+        <input type="hidden" placeholder="WebKit" class="placeholder-shown">
+        <input type="hidden" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="text">
+        <input type="text" placeholder>
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="tel">
+        <input type="tel" placeholder>
+        <input type="tel" placeholder="WebKit" class="placeholder-shown">
+        <input type="tel" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="url">
+        <input type="url" placeholder>
+        <input type="url" placeholder="WebKit" class="placeholder-shown">
+        <input type="url" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="email">
+        <input type="email" placeholder>
+        <input type="email" placeholder="WebKit" class="placeholder-shown">
+        <input type="email" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="password">
+        <input type="password" placeholder>
+        <input type="password" placeholder="WebKit" class="placeholder-shown">
+        <input type="password" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="datetime">
+        <input type="datetime" placeholder>
+        <input type="datetime" placeholder="WebKit" class="placeholder-shown">
+        <input type="datetime" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="number">
+        <input type="number" placeholder>
+        <input type="number" placeholder="WebKit" class="placeholder-shown">
+        <input type="number" placeholder="WebKit" value="0">
+    </div>
+    <div>
+        <input type="range">
+        <input type="range" placeholder>
+        <input type="range" placeholder="WebKit">
+        <input type="range" placeholder="WebKit" value="1">
+    </div>
+    <div>
+        <input type="checkbox">
+        <input type="checkbox" placeholder>
+        <input type="checkbox" placeholder="WebKit">
+        <input type="checkbox" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="radio">
+        <input type="radio" placeholder>
+        <input type="radio" placeholder="WebKit">
+        <input type="radio" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="submit">
+        <input type="submit" placeholder>
+        <input type="submit" placeholder="WebKit">
+        <input type="submit" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="color">
+        <input type="color" placeholder>
+        <input type="color" placeholder="WebKit">
+        <input type="color" placeholder="WebKit" value="Foobar">
+    </div>
+
+</body>
+</html>

Added: trunk/LayoutTests/fast/css/placeholder-shown-basics.html (0 => 172826)


--- trunk/LayoutTests/fast/css/placeholder-shown-basics.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/placeholder-shown-basics.html	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+        input, textarea {
+            height: 8px;
+        }
+        :placeholder-shown {
+            background-color: green;
+        }
+    </style>
+</head>
+<body>
+    <p>This test checks how various input elements are styled when :placeholder-shown is applied.</p>
+    <div>
+        <textarea></textarea>
+        <textarea placeholder></textarea>
+        <textarea placeholder="WebKit"></textarea>
+        <textarea placeholder="WebKit">Foobar</textarea>
+    </div>
+    <div>
+        <input>
+        <input placeholder>
+        <input placeholder="WebKit">
+        <input placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="">
+        <input type="" placeholder>
+        <input type="" placeholder="WebKit">
+        <input type="" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="hidden">
+        <input type="hidden" placeholder>
+        <input type="hidden" placeholder="WebKit">
+        <input type="hidden" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="text">
+        <input type="text" placeholder>
+        <input type="text" placeholder="WebKit">
+        <input type="text" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="tel">
+        <input type="tel" placeholder>
+        <input type="tel" placeholder="WebKit">
+        <input type="tel" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="url">
+        <input type="url" placeholder>
+        <input type="url" placeholder="WebKit">
+        <input type="url" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="email">
+        <input type="email" placeholder>
+        <input type="email" placeholder="WebKit">
+        <input type="email" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="password">
+        <input type="password" placeholder>
+        <input type="password" placeholder="WebKit">
+        <input type="password" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="datetime">
+        <input type="datetime" placeholder>
+        <input type="datetime" placeholder="WebKit">
+        <input type="datetime" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="number">
+        <input type="number" placeholder>
+        <input type="number" placeholder="WebKit">
+        <input type="number" placeholder="WebKit" value="0">
+    </div>
+    <div>
+        <input type="range">
+        <input type="range" placeholder>
+        <input type="range" placeholder="WebKit">
+        <input type="range" placeholder="WebKit" value="1">
+    </div>
+    <div>
+        <input type="checkbox">
+        <input type="checkbox" placeholder>
+        <input type="checkbox" placeholder="WebKit">
+        <input type="checkbox" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="radio">
+        <input type="radio" placeholder>
+        <input type="radio" placeholder="WebKit">
+        <input type="radio" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="submit">
+        <input type="submit" placeholder>
+        <input type="submit" placeholder="WebKit">
+        <input type="submit" placeholder="WebKit" value="Foobar">
+    </div>
+    <div>
+        <input type="color">
+        <input type="color" placeholder>
+        <input type="color" placeholder="WebKit">
+        <input type="color" placeholder="WebKit" value="Foobar">
+    </div>
+
+</body>
+</html>

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-long-adjacent-backtracking-expected.txt (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-long-adjacent-backtracking-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-long-adjacent-backtracking-expected.txt	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,75 @@
+Test backtracking of a long chain of :placeholder-shown siblings to catch any issue with register allocation.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll(":placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown~:not(:placeholder-shown)").length is 3
+PASS document.querySelectorAll(":placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown~:not(:placeholder-shown)")[0] is document.getElementById("target1")
+PASS document.querySelectorAll(":placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown~:not(:placeholder-shown)")[1] is document.getElementById("target2")
+PASS document.querySelectorAll(":placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown~:not(:placeholder-shown)")[2] is document.getElementById("target3")
+PASS document.querySelectorAll("input").length is 61
+PASS getComputedStyle(document.querySelectorAll("input")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[2]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[3]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[4]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[5]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[6]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[7]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[8]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[9]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[10]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[11]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[12]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[13]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[14]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[15]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[16]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[17]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[18]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[19]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[20]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("input")[21]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[22]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[23]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[24]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[25]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[26]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[27]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[28]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[29]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[30]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[31]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[32]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[33]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[34]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[35]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[36]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[37]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[38]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[39]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[40]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("input")[41]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[42]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[43]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[44]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[45]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[46]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[47]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[48]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[49]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[50]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[51]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[52]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[53]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[54]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[55]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[56]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[57]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[58]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[59]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("input")[60]).backgroundColor is "rgb(1, 2, 3)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-long-adjacent-backtracking.html (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-long-adjacent-backtracking.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-long-adjacent-backtracking.html	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,104 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+input {
+    background-color: white;
+}
+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown~:not(:placeholder-shown) {
+    background-color: rgb(1, 2, 3);
+}
+</style>
+</head>
+<body>
+    <div style="display:none">
+        <!-- 20 empty -->
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+
+        <input id="target1" type="text" placeholder="WebKit" class="placeholder-not-shown" value="Not Shown!">
+
+        <!-- 19 empty -->
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+
+        <input id="target2" type="text" placeholder="WebKit" class="placeholder-not-shown" value="Not Shown!">
+
+        <!-- 19 empty -->
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+        <input type="text" placeholder="WebKit" class="placeholder-shown">
+
+        <input id="target3" type="text" placeholder="WebKit" class="placeholder-not-shown" value="Not Shown!">
+    </div>
+</body>
+<script>
+description('Test backtracking of a long chain of :placeholder-shown siblings to catch any issue with register allocation.');
+
+shouldBe('document.querySelectorAll(":placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown~:not(:placeholder-shown)").length', '3');
+shouldBe('document.querySelectorAll(":placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown~:not(:placeholder-shown)")[0]', 'document.getElementById("target1")');
+shouldBe('document.querySelectorAll(":placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown~:not(:placeholder-shown)")[1]', 'document.getElementById("target2")');
+shouldBe('document.querySelectorAll(":placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown+:placeholder-shown~:not(:placeholder-shown)")[2]', 'document.getElementById("target3")');
+
+shouldBe('document.querySelectorAll("input").length', '61')
+
+var allTestCases = document.querySelectorAll("input");
+for (var i = 0; i < 61; ++i)
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("input")[' + i + ']).backgroundColor', allTestCases[i].classList.contains('placeholder-shown') ? 'rgb(255, 255, 255)' : 'rgb(1, 2, 3)');
+
+
+</script>
+<script src=""
+</html>

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-sibling-style-update-expected.txt (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-sibling-style-update-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-sibling-style-update-expected.txt	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,19 @@
+Test style update of the :placeholder-shown pseudo class.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state is without placehoder.
+PASS getComputedStyle(document.getElementById("target1")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("target2")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("target3")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("target4")).backgroundColor is "rgb(255, 255, 255)"
+Adding a placeholder, the targets should match the style.
+FAIL getComputedStyle(document.getElementById("target1")).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255).
+FAIL getComputedStyle(document.getElementById("target2")).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255).
+FAIL getComputedStyle(document.getElementById("target3")).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255).
+FAIL getComputedStyle(document.getElementById("target4")).backgroundColor should be rgb(1, 2, 3). Was rgb(255, 255, 255).
+PASS successfullyParsed is true
+
+TEST COMPLETE
+  

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-sibling-style-update.html (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-sibling-style-update.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-sibling-style-update.html	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,58 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+target {
+    background-color: white;
+}
+:placeholder-shown + target {
+    background-color: rgb(1, 2, 3);
+}
+</style>
+</head>
+<body>
+    <div>
+        <input id="input-with-renderer">
+        <target id="target1"></target>
+        <textarea id="textarea-with-renderer"></textarea>
+        <target id="target2"></target>
+    </div>
+    <div style="display:none;">
+        <input id="input-without-renderer">
+        <target id="target3"></target>
+        <textarea id="textarea-without-renderer"></textarea>
+        <target id="target4"></target>
+    </div>
+</body>
+<script>
+description('Test style update of the :placeholder-shown pseudo class.');
+
+function testBackgroundColor(expectMatch) {
+    shouldBeEqualToString('getComputedStyle(document.getElementById("target1")).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById("target2")).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById("target3")).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById("target4")).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+}
+
+var inputCaseWithRenderer = document.getElementById("input-with-renderer");
+var textareaCaseWithRenderer = document.getElementById("textarea-with-renderer");
+var inputCaseWithoutRenderer = document.getElementById("input-without-renderer");
+var textareaCaseWithoutRenderer = document.getElementById("textarea-without-renderer");
+
+function setAttribute(attribute, value) {
+    inputCaseWithRenderer.setAttribute(attribute, value);
+    textareaCaseWithRenderer.setAttribute(attribute, value);
+    inputCaseWithoutRenderer.setAttribute(attribute, value);
+    textareaCaseWithoutRenderer.setAttribute(attribute, value);
+}
+
+debug("Initial state is without placehoder.");
+testBackgroundColor(false);
+
+debug("Adding a placeholder, the targets should match the style.");
+setAttribute("placeholder", "WebKit")
+testBackgroundColor(true);
+</script>
+<script src=""
+</html>

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-style-update-expected.txt (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-style-update-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-style-update-expected.txt	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,69 @@
+Test style update of the :placeholder-shown pseudo class.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state is without placehoder.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+Adding a valid placeholder matches.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
+Using an invalid placeholder value does not match.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+Adding back a placehoder and an empty value. An empty value does not prevent matching.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
+Changing the type of the input to something that does not support placeholder. The input element should not match.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
+Changing the type of the input to text should add the style back.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
+Adding a non empty value should remove the style.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+Removing the placeholder, we should not match.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+Removing the value. We should still not match since the placeholder attribute was removed.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+Putting back a value, no reason to match.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+Adding back the placeholder, the value is still there so we cannot match yet.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(255, 255, 255)"
+Removing the value. A placeholder was added while the value was up, we should get the style now.
+PASS getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor is "rgb(1, 2, 3)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+  

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-style-update.html (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-style-update.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-style-update.html	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,115 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+input, textarea {
+    background-color: white;
+}
+:placeholder-shown {
+    background-color: rgb(1, 2, 3);
+}
+</style>
+</head>
+<body>
+    <div>
+        <input id="input-with-renderer">
+        <textarea id="textarea-with-renderer"></textarea>
+    </div>
+    <div style="display:none;">
+        <input id="input-without-renderer">
+        <textarea id="textarea-without-renderer"></textarea>
+    </div>
+</body>
+<script>
+description('Test style update of the :placeholder-shown pseudo class.');
+
+var inputCaseWithRenderer = document.getElementById("input-with-renderer");
+var textareaCaseWithRenderer = document.getElementById("textarea-with-renderer");
+var inputCaseWithoutRenderer = document.getElementById("input-without-renderer");
+var textareaCaseWithoutRenderer = document.getElementById("textarea-without-renderer");
+
+function testBackgroundColor(expectMatch) {
+    shouldBeEqualToString('getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor', expectMatch ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+}
+
+function setAttribute(attribute, value) {
+    inputCaseWithRenderer.setAttribute(attribute, value);
+    textareaCaseWithRenderer.setAttribute(attribute, value);
+    inputCaseWithoutRenderer.setAttribute(attribute, value);
+    textareaCaseWithoutRenderer.setAttribute(attribute, value);
+}
+
+debug("Initial state is without placehoder.");
+testBackgroundColor(false);
+
+debug("Adding a valid placeholder matches.");
+setAttribute("placeholder", "WebKit!");
+testBackgroundColor(true);
+
+debug("Using an invalid placeholder value does not match.");
+setAttribute("placeholder", "\n");
+testBackgroundColor(false);
+
+debug("Adding back a placehoder and an empty value. An empty value does not prevent matching.");
+setAttribute("placeholder", "WebKit!");
+inputCaseWithRenderer.value = "";
+textareaCaseWithRenderer.appendChild(document.createTextNode(""));
+inputCaseWithoutRenderer.value = "";
+textareaCaseWithoutRenderer.appendChild(document.createTextNode(""));
+testBackgroundColor(true);
+
+debug("Changing the type of the input to something that does not support placeholder. The input element should not match.");
+inputCaseWithRenderer.type = "button";
+inputCaseWithoutRenderer.type = "button";
+shouldBeEqualToString('getComputedStyle(document.getElementById("input-with-renderer")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("textarea-with-renderer")).backgroundColor', 'rgb(1, 2, 3)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("input-without-renderer")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("textarea-without-renderer")).backgroundColor', 'rgb(1, 2, 3)');
+
+debug("Changing the type of the input to text should add the style back.");
+inputCaseWithRenderer.type = "text";
+inputCaseWithoutRenderer.type = "text";
+testBackgroundColor(true);
+
+debug("Adding a non empty value should remove the style.");
+inputCaseWithRenderer.value = "Foobar";
+textareaCaseWithRenderer.appendChild(document.createTextNode("Foobar"));
+inputCaseWithoutRenderer.value = "Foobar";
+textareaCaseWithoutRenderer.appendChild(document.createTextNode("Foobar"));
+testBackgroundColor(false);
+
+debug("Removing the placeholder, we should not match.");
+setAttribute("placeholder", "");
+testBackgroundColor(false);
+
+debug("Removing the value. We should still not match since the placeholder attribute was removed.");
+inputCaseWithRenderer.value = "";
+textareaCaseWithRenderer.removeChild(textareaCaseWithRenderer.lastChild);
+inputCaseWithoutRenderer.value = "";
+textareaCaseWithoutRenderer.removeChild(textareaCaseWithoutRenderer.lastChild);
+testBackgroundColor(false);
+
+debug("Putting back a value, no reason to match.");
+inputCaseWithRenderer.value = "Foobar";
+textareaCaseWithRenderer.appendChild(document.createTextNode("Foobar"));
+inputCaseWithoutRenderer.value = "Foobar";
+textareaCaseWithoutRenderer.appendChild(document.createTextNode("Foobar"));
+testBackgroundColor(false);
+
+debug("Adding back the placeholder, the value is still there so we cannot match yet.");
+setAttribute("placeholder", "WebKit!");
+testBackgroundColor(false);
+
+debug("Removing the value. A placeholder was added while the value was up, we should get the style now.");
+inputCaseWithRenderer.value = "";
+textareaCaseWithRenderer.removeChild(textareaCaseWithRenderer.lastChild);
+inputCaseWithoutRenderer.value = "";
+textareaCaseWithoutRenderer.removeChild(textareaCaseWithoutRenderer.lastChild);
+testBackgroundColor(true);
+</script>
+<script src=""
+</html>

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-with-input-basics-expected.txt (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-with-input-basics-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-with-input-basics-expected.txt	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,39 @@
+Check the basic features of the ":placeholder-shown" pseudo class with the <input> element.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll(":placeholder-shown").length is 3
+PASS document.querySelectorAll(":placeholder-shown")[0] is document.getElementById("valid-placeholder")
+PASS document.querySelectorAll(":placeholder-shown")[1] is document.getElementById("valid-placeholder-with-empty-value")
+PASS document.querySelectorAll(":placeholder-shown")[2] is document.getElementById("valid-placeholder-with-empty-value2")
+PASS getComputedStyle(document.getElementById("no-placeholder")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("empty-placeholder")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("empty-placeholder2")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("placeholder-contains-only-newline")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("placeholder-contains-only-carriageReturn")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("with-value")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("valid-placeholder")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-empty-value")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-empty-value2")).backgroundColor is "rgb(1, 2, 3)"
+
+PASS document.querySelectorAll("input:not(:placeholder-shown)").length is 6
+PASS document.querySelectorAll("input:not(:placeholder-shown)")[0] is document.getElementById("no-placeholder")
+PASS document.querySelectorAll("input:not(:placeholder-shown)")[1] is document.getElementById("empty-placeholder")
+PASS document.querySelectorAll("input:not(:placeholder-shown)")[2] is document.getElementById("empty-placeholder2")
+PASS document.querySelectorAll("input:not(:placeholder-shown)")[3] is document.getElementById("placeholder-contains-only-newline")
+PASS document.querySelectorAll("input:not(:placeholder-shown)")[4] is document.getElementById("placeholder-contains-only-carriageReturn")
+PASS document.querySelectorAll("input:not(:placeholder-shown)")[5] is document.getElementById("with-value")
+PASS getComputedStyle(document.getElementById("no-placeholder")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("empty-placeholder")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("empty-placeholder2")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("placeholder-contains-only-newline")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("placeholder-contains-only-carriageReturn")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("with-value")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("valid-placeholder")).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-empty-value")).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-empty-value2")).color is "rgb(0, 0, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-with-input-basics.html (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-with-input-basics.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-with-input-basics.html	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,83 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+input {
+    background-color: white;
+    color: black;
+}
+input:placeholder-shown {
+    background-color: rgb(1, 2, 3);
+}
+input:not(:placeholder-shown) {
+    color: rgb(4, 5, 6);
+}
+</style>
+</head>
+<body>
+    <div style="display:none">
+        <!-- Does not match: no placeholder defined. -->
+        <input type="text" id="no-placeholder">
+
+        <!-- Does not match: empty placeholder. -->
+        <input type="text" id="empty-placeholder" placeholder>
+        <input type="text" id="empty-placeholder2" placeholder="">
+
+        <!-- Does not match: placeholder contains only newline or carriage return characters. -->
+        <input type="text" id="placeholder-contains-only-newline">
+        <input type="text" id="placeholder-contains-only-carriageReturn">
+
+        <!-- Does not match: the placeholder is not shown when a value is set -->
+        <input type="text" id="with-value" placeholder="WebKit" value="FooBar">
+
+        <!-- Valid cases -->
+        <input type="text" id="valid-placeholder" placeholder="WebKit">
+        <input type="text" id="valid-placeholder-with-empty-value" placeholder="WebKit" value>
+        <input type="text" id="valid-placeholder-with-empty-value2" placeholder="WebKit" value="">
+    </div>
+</body>
+<script>
+description('Check the basic features of the ":placeholder-shown" pseudo class with the &lt;input&gt; element.');
+
+document.getElementById('placeholder-contains-only-newline').setAttribute('placeholder', '\n');
+document.getElementById('placeholder-contains-only-carriageReturn').setAttribute('placeholder', '\r');
+
+shouldBe('document.querySelectorAll(":placeholder-shown").length', '3');
+shouldBe('document.querySelectorAll(":placeholder-shown")[0]', 'document.getElementById("valid-placeholder")');
+shouldBe('document.querySelectorAll(":placeholder-shown")[1]', 'document.getElementById("valid-placeholder-with-empty-value")');
+shouldBe('document.querySelectorAll(":placeholder-shown")[2]', 'document.getElementById("valid-placeholder-with-empty-value2")');
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("no-placeholder")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("empty-placeholder")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("empty-placeholder2")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("placeholder-contains-only-newline")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("placeholder-contains-only-carriageReturn")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("with-value")).backgroundColor', 'rgb(255, 255, 255)');
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder")).backgroundColor', 'rgb(1, 2, 3)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-empty-value")).backgroundColor', 'rgb(1, 2, 3)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-empty-value2")).backgroundColor', 'rgb(1, 2, 3)');
+
+debug("");
+shouldBe('document.querySelectorAll("input:not(:placeholder-shown)").length', '6');
+shouldBe('document.querySelectorAll("input:not(:placeholder-shown)")[0]', 'document.getElementById("no-placeholder")');
+shouldBe('document.querySelectorAll("input:not(:placeholder-shown)")[1]', 'document.getElementById("empty-placeholder")');
+shouldBe('document.querySelectorAll("input:not(:placeholder-shown)")[2]', 'document.getElementById("empty-placeholder2")');
+shouldBe('document.querySelectorAll("input:not(:placeholder-shown)")[3]', 'document.getElementById("placeholder-contains-only-newline")');
+shouldBe('document.querySelectorAll("input:not(:placeholder-shown)")[4]', 'document.getElementById("placeholder-contains-only-carriageReturn")');
+shouldBe('document.querySelectorAll("input:not(:placeholder-shown)")[5]', 'document.getElementById("with-value")');
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("no-placeholder")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("empty-placeholder")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("empty-placeholder2")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("placeholder-contains-only-newline")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("placeholder-contains-only-carriageReturn")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("with-value")).color', 'rgb(4, 5, 6)');
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder")).color', 'rgb(0, 0, 0)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-empty-value")).color', 'rgb(0, 0, 0)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-empty-value2")).color', 'rgb(0, 0, 0)');
+</script>
+<script src=""
+</html>

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-with-textarea-basics-expected.txt (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-with-textarea-basics-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-with-textarea-basics-expected.txt	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,42 @@
+Check the basic features of the ":placeholder-shown" pseudo class with the <textarea> element.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.querySelectorAll(":placeholder-shown").length is 4
+PASS document.querySelectorAll(":placeholder-shown")[0] is document.getElementById("valid-placeholder")
+PASS document.querySelectorAll(":placeholder-shown")[1] is document.getElementById("valid-placeholder-with-value-attribute")
+PASS document.querySelectorAll(":placeholder-shown")[2] is document.getElementById("valid-placeholder-with-value-attribute2")
+PASS document.querySelectorAll(":placeholder-shown")[3] is document.getElementById("valid-placeholder-with-value-attribute3")
+PASS getComputedStyle(document.getElementById("no-placeholder")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("empty-placeholder")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("empty-placeholder2")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("placeholder-contains-only-newline")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("placeholder-contains-only-carriageReturn")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("with-value")).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.getElementById("valid-placeholder")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute2")).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute3")).backgroundColor is "rgb(1, 2, 3)"
+
+PASS document.querySelectorAll("textarea:not(:placeholder-shown)").length is 6
+PASS document.querySelectorAll("textarea:not(:placeholder-shown)")[0] is document.getElementById("no-placeholder")
+PASS document.querySelectorAll("textarea:not(:placeholder-shown)")[1] is document.getElementById("empty-placeholder")
+PASS document.querySelectorAll("textarea:not(:placeholder-shown)")[2] is document.getElementById("empty-placeholder2")
+PASS document.querySelectorAll("textarea:not(:placeholder-shown)")[3] is document.getElementById("placeholder-contains-only-newline")
+PASS document.querySelectorAll("textarea:not(:placeholder-shown)")[4] is document.getElementById("placeholder-contains-only-carriageReturn")
+PASS document.querySelectorAll("textarea:not(:placeholder-shown)")[5] is document.getElementById("with-value")
+PASS getComputedStyle(document.getElementById("no-placeholder")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("empty-placeholder")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("empty-placeholder2")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("placeholder-contains-only-newline")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("placeholder-contains-only-carriageReturn")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("with-value")).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.getElementById("valid-placeholder")).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute")).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute2")).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute3")).color is "rgb(0, 0, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/placeholder-shown-with-textarea-basics.html (0 => 172826)


--- trunk/LayoutTests/fast/selectors/placeholder-shown-with-textarea-basics.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/placeholder-shown-with-textarea-basics.html	2014-08-21 03:33:18 UTC (rev 172826)
@@ -0,0 +1,89 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+textarea {
+    background-color: white;
+    color: black;
+}
+textarea:placeholder-shown {
+    background-color: rgb(1, 2, 3);
+}
+textarea:not(:placeholder-shown) {
+    color: rgb(4, 5, 6);
+}
+</style>
+</head>
+<body>
+    <div style="display:none">
+        <!-- Does not match: no placeholder defined. -->
+        <textarea id="no-placeholder"></textarea>
+
+        <!-- Does not match: empty placeholder. -->
+        <textarea id="empty-placeholder" placeholder></textarea>
+        <textarea id="empty-placeholder2" placeholder=""></textarea>
+
+        <!-- Does not match: placeholder contains only newline or carriage return characters. -->
+        <textarea id="placeholder-contains-only-newline"></textarea>
+        <textarea id="placeholder-contains-only-carriageReturn"></textarea>
+
+        <!-- Does not match: the placeholder is not shown when a value is set -->
+        <textarea id="with-value" placeholder="WebKit">FooBar</textarea>
+
+        <!-- Valid cases -->
+        <textarea id="valid-placeholder" placeholder="WebKit"></textarea>
+
+        <!-- Value does not do anything on <textarea>, the content is the innerText -->
+        <textarea id="valid-placeholder-with-value-attribute" placeholder="WebKit" value></textarea>
+        <textarea id="valid-placeholder-with-value-attribute2" placeholder="WebKit" value=""></textarea>
+        <textarea id="valid-placeholder-with-value-attribute3" placeholder="WebKit" value="Rocks!"></textarea>
+    </div>
+</body>
+<script>
+description('Check the basic features of the ":placeholder-shown" pseudo class with the &lt;textarea&gt; element.');
+
+document.getElementById('placeholder-contains-only-newline').setAttribute('placeholder', '\n');
+document.getElementById('placeholder-contains-only-carriageReturn').setAttribute('placeholder', '\r');
+
+shouldBe('document.querySelectorAll(":placeholder-shown").length', '4');
+shouldBe('document.querySelectorAll(":placeholder-shown")[0]', 'document.getElementById("valid-placeholder")');
+shouldBe('document.querySelectorAll(":placeholder-shown")[1]', 'document.getElementById("valid-placeholder-with-value-attribute")');
+shouldBe('document.querySelectorAll(":placeholder-shown")[2]', 'document.getElementById("valid-placeholder-with-value-attribute2")');
+shouldBe('document.querySelectorAll(":placeholder-shown")[3]', 'document.getElementById("valid-placeholder-with-value-attribute3")');
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("no-placeholder")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("empty-placeholder")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("empty-placeholder2")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("placeholder-contains-only-newline")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("placeholder-contains-only-carriageReturn")).backgroundColor', 'rgb(255, 255, 255)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("with-value")).backgroundColor', 'rgb(255, 255, 255)');
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder")).backgroundColor', 'rgb(1, 2, 3)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute")).backgroundColor', 'rgb(1, 2, 3)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute2")).backgroundColor', 'rgb(1, 2, 3)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute3")).backgroundColor', 'rgb(1, 2, 3)');
+
+debug("");
+shouldBe('document.querySelectorAll("textarea:not(:placeholder-shown)").length', '6');
+shouldBe('document.querySelectorAll("textarea:not(:placeholder-shown)")[0]', 'document.getElementById("no-placeholder")');
+shouldBe('document.querySelectorAll("textarea:not(:placeholder-shown)")[1]', 'document.getElementById("empty-placeholder")');
+shouldBe('document.querySelectorAll("textarea:not(:placeholder-shown)")[2]', 'document.getElementById("empty-placeholder2")');
+shouldBe('document.querySelectorAll("textarea:not(:placeholder-shown)")[3]', 'document.getElementById("placeholder-contains-only-newline")');
+shouldBe('document.querySelectorAll("textarea:not(:placeholder-shown)")[4]', 'document.getElementById("placeholder-contains-only-carriageReturn")');
+shouldBe('document.querySelectorAll("textarea:not(:placeholder-shown)")[5]', 'document.getElementById("with-value")');
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("no-placeholder")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("empty-placeholder")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("empty-placeholder2")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("placeholder-contains-only-newline")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("placeholder-contains-only-carriageReturn")).color', 'rgb(4, 5, 6)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("with-value")).color', 'rgb(4, 5, 6)');
+
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder")).color', 'rgb(0, 0, 0)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute")).color', 'rgb(0, 0, 0)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute2")).color', 'rgb(0, 0, 0)');
+shouldBeEqualToString('getComputedStyle(document.getElementById("valid-placeholder-with-value-attribute3")).color', 'rgb(0, 0, 0)');
+</script>
+<script src=""
+</html>

Modified: trunk/Source/WebCore/ChangeLog (172825 => 172826)


--- trunk/Source/WebCore/ChangeLog	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/ChangeLog	2014-08-21 03:33:18 UTC (rev 172826)
@@ -1,3 +1,82 @@
+2014-08-20  Benjamin Poulain  <[email protected]>
+
+        CSS: Implement the :placeholder-shown pseudo-class from Selectors Level 4
+        https://bugs.webkit.org/show_bug.cgi?id=118162
+
+        Reviewed by Antti Koivisto.
+
+        Previously, HTMLTextFormControlElement was using some mix of its own state
+        and style to change the visibility of the placeholder. That approach was a little
+        bit too fragile, and we do not want the style to depends on the renderer() since
+        that creates circular dependencies.
+
+        The biggest change here is refactoring HTMLTextFormControlElement to have
+        1) An explicit "visible placeholder" state.
+        2) Separate the textUpdate() from the visibilityUpdate().
+        3) Remove the dependencies between the Element's style and the placeholder's style.
+           This is done by simply using display:none; on the placeholder so that its parent's visibility
+           is irrelevant.
+
+        When matching the selector, the style is set as unique since style sharing does not deal with
+        the changes of HTMLTextFormControlElement.
+
+        Tests: fast/css/placeholder-shown-basics.html
+               fast/selectors/placeholder-shown-long-adjacent-backtracking.html
+               fast/selectors/placeholder-shown-sibling-style-update.html
+               fast/selectors/placeholder-shown-style-update.html
+               fast/selectors/placeholder-shown-with-input-basics.html
+               fast/selectors/placeholder-shown-with-textarea-basics.html
+
+        * css/CSSSelector.cpp:
+        (WebCore::CSSSelector::selectorText):
+        Add the CSS Selector description for CSSOM.
+
+        * css/CSSSelector.h:
+        * css/SelectorChecker.cpp:
+        (WebCore::SelectorChecker::checkOne):
+        * css/SelectorCheckerTestFunctions.h:
+        (WebCore::isPlaceholderShown):
+        * css/SelectorPseudoClassAndCompatibilityElementMap.in:
+        * css/html.css:
+        (::-webkit-input-placeholder):
+        Previously, the display was forced through the UA stylesheet. Since the display is now part
+        of the placeholder visibility, it is explicitly handled by HTMLTextFormControlElement and
+        its subclasses.
+
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::addPseudoClassType):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching):
+        (WebCore::SelectorCompiler::makeUniqueIfNecessaryAndTestIsPlaceholderShown):
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasPlaceholderShown):
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::parseAttribute):
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::updateValue):
+        (WebCore::HTMLTextAreaElement::setValueCommon):
+        (WebCore::HTMLTextAreaElement::updatePlaceholderText):
+        * html/HTMLTextFormControlElement.cpp:
+        (WebCore::HTMLTextFormControlElement::HTMLTextFormControlElement):
+        (WebCore::HTMLTextFormControlElement::dispatchFocusEvent):
+        (WebCore::HTMLTextFormControlElement::dispatchBlurEvent):
+        (WebCore::HTMLTextFormControlElement::placeholderShouldBeVisible):
+        (WebCore::HTMLTextFormControlElement::updatePlaceholderVisibility):
+        (WebCore::HTMLTextFormControlElement::selectionDirection):
+        (WebCore::HTMLTextFormControlElement::restoreCachedSelection):
+        (WebCore::HTMLTextFormControlElement::parseAttribute):
+        (WebCore::HTMLTextFormControlElement::hidePlaceholder):
+        (WebCore::HTMLTextFormControlElement::showPlaceholderIfNecessary):
+        * html/HTMLTextFormControlElement.h:
+        (WebCore::HTMLTextFormControlElement::isPlaceholderVisible):
+        (WebCore::HTMLTextFormControlElement::cachedSelectionDirection):
+        * html/TextFieldInputType.cpp:
+        (WebCore::TextFieldInputType::updatePlaceholderText):
+        (WebCore::TextFieldInputType::subtreeHasChanged):
+        (WebCore::TextFieldInputType::updateInnerTextValue):
+        * rendering/RenderTextControl.cpp:
+        (WebCore::RenderTextControl::styleDidChange):
+        * testing/Internals.cpp:
+        (WebCore::Internals::visiblePlaceholder):
+
 2014-08-20  Mark Rowe  <[email protected]>
 
         Fix the release build after r172806.

Modified: trunk/Source/WebCore/WebCore.exp.in (172825 => 172826)


--- trunk/Source/WebCore/WebCore.exp.in	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/WebCore.exp.in	2014-08-21 03:33:18 UTC (rev 172826)
@@ -1852,7 +1852,6 @@
 __ZNK7WebCore23FrameLoaderStateMachine15firstLayoutDoneEv
 __ZNK7WebCore23FrameLoaderStateMachine23committingFirstRealLoadEv
 __ZNK7WebCore26HTMLTextFormControlElement21lastChangeWasUserEditEv
-__ZNK7WebCore26HTMLTextFormControlElement26placeholderShouldBeVisibleEv
 __ZNK7WebCore26NetscapePlugInStreamLoader6isDoneEv
 __ZNK7WebCore27AuthenticationChallengeBase15failureResponseEv
 __ZNK7WebCore27AuthenticationChallengeBase15protectionSpaceEv

Modified: trunk/Source/WebCore/css/CSSSelector.cpp (172825 => 172826)


--- trunk/Source/WebCore/css/CSSSelector.cpp	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/css/CSSSelector.cpp	2014-08-21 03:33:18 UTC (rev 172826)
@@ -417,6 +417,11 @@
             case CSSSelector::PseudoClassOptional:
                 str.appendLiteral(":optional");
                 break;
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+            case CSSSelector::PseudoClassPlaceholderShown:
+                str.appendLiteral(":placeholder-shown");
+                break;
+#endif
             case CSSSelector::PseudoClassOutOfRange:
                 str.appendLiteral(":out-of-range");
                 break;
@@ -461,7 +466,7 @@
             case CSSSelector::PseudoClassWindowInactive:
                 str.appendLiteral(":window-inactive");
                 break;
-            default:
+            case CSSSelector::PseudoClassUnknown:
                 ASSERT_NOT_REACHED();
             }
         } else if (cs->m_match == CSSSelector::PseudoElement) {

Modified: trunk/Source/WebCore/css/CSSSelector.h (172825 => 172826)


--- trunk/Source/WebCore/css/CSSSelector.h	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/css/CSSSelector.h	2014-08-21 03:33:18 UTC (rev 172826)
@@ -1,7 +1,7 @@
 /*
  * Copyright (C) 1999-2003 Lars Knoll ([email protected])
  *               1999 Waldo Bastian ([email protected])
- * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2013, 2014 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -106,6 +106,9 @@
             PseudoClassDefault,
             PseudoClassDisabled,
             PseudoClassOptional,
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+            PseudoClassPlaceholderShown,
+#endif
             PseudoClassRequired,
             PseudoClassReadOnly,
             PseudoClassReadWrite,

Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (172825 => 172826)


--- trunk/Source/WebCore/css/SelectorChecker.cpp	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp	2014-08-21 03:33:18 UTC (rev 172826)
@@ -604,6 +604,14 @@
                 return isFirstOfType(element, element->tagQName()) && isLastOfType(element, element->tagQName());
             }
             break;
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+        case CSSSelector::PseudoClassPlaceholderShown:
+            if (m_mode == Mode::ResolvingStyle) {
+                if (RenderStyle* style = context.elementStyle ? context.elementStyle : element->renderStyle())
+                    style->setUnique();
+            }
+            return isPlaceholderShown(element);
+#endif
         case CSSSelector::PseudoClassNthChild:
             if (!selector->parseNth())
                 break;

Modified: trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h (172825 => 172826)


--- trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h	2014-08-21 03:33:18 UTC (rev 172826)
@@ -114,6 +114,15 @@
     return element->isOptionalFormControl();
 }
 
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+ALWAYS_INLINE bool isPlaceholderShown(Element* element)
+{
+    if (isHTMLTextFormControlElement(*element))
+        return toHTMLTextFormControlElement(*element).isPlaceholderVisible();
+    return false;
+}
+#endif
+
 ALWAYS_INLINE bool isRequiredFormControl(const Element* element)
 {
     return element->isRequiredFormControl();

Modified: trunk/Source/WebCore/css/SelectorPseudoClassAndCompatibilityElementMap.in (172825 => 172826)


--- trunk/Source/WebCore/css/SelectorPseudoClassAndCompatibilityElementMap.in	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/css/SelectorPseudoClassAndCompatibilityElementMap.in	2014-08-21 03:33:18 UTC (rev 172826)
@@ -41,6 +41,9 @@
 only-of-type
 optional
 out-of-range
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+placeholder-shown
+#endif
 read-only
 read-write
 required

Modified: trunk/Source/WebCore/css/html.css (172825 => 172826)


--- trunk/Source/WebCore/css/html.css	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/css/html.css	2014-08-21 03:33:18 UTC (rev 172826)
@@ -611,7 +611,6 @@
 ::-webkit-input-placeholder {
     -webkit-text-security: none;
     color: darkGray;
-    display: block !important;
     pointer-events: none !important;
 }
 

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (172825 => 172826)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2014-08-21 03:33:18 UTC (rev 172826)
@@ -244,6 +244,9 @@
     void generateElementIsInLanguage(Assembler::JumpList& failureCases, const AtomicString&);
     void generateElementIsLastChild(Assembler::JumpList& failureCases, const SelectorFragment&);
     void generateElementIsOnlyChild(Assembler::JumpList& failureCases, const SelectorFragment&);
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+    void generateElementHasPlaceholderShown(Assembler::JumpList& failureCases, const SelectorFragment&);
+#endif
     void generateSynchronizeStyleAttribute(Assembler::RegisterID elementDataArraySizeAndFlags);
     void generateSynchronizeAllAnimatedSVGAttribute(Assembler::RegisterID elementDataArraySizeAndFlags);
     void generateElementAttributesMatching(Assembler::JumpList& failureCases, const LocalRegister& elementDataAddress, const SelectorFragment&);
@@ -536,6 +539,9 @@
     case CSSSelector::PseudoClassHover:
     case CSSSelector::PseudoClassLastChild:
     case CSSSelector::PseudoClassOnlyChild:
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+    case CSSSelector::PseudoClassPlaceholderShown:
+#endif
         fragment.pseudoClasses.add(type);
         if (selectorContext == SelectorContext::QuerySelector)
             return FunctionType::SimpleSelectorChecker;
@@ -1972,6 +1978,10 @@
         generateElementIsHovered(matchingPostTagNameFailureCases, fragment);
     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassOnlyChild))
         generateElementIsOnlyChild(matchingPostTagNameFailureCases, fragment);
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+    if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassPlaceholderShown))
+        generateElementHasPlaceholderShown(matchingPostTagNameFailureCases, fragment);
+#endif
     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassFirstChild))
         generateElementIsFirstChild(matchingPostTagNameFailureCases, fragment);
     if (fragment.pseudoClasses.contains(CSSSelector::PseudoClassLastChild))
@@ -2798,6 +2808,51 @@
     failureCases.append(m_assembler.branchTest32(Assembler::NonZero, isOnlyChildRegister));
 }
 
+#if ENABLE(CSS_SELECTORS_LEVEL4)
+static bool makeUniqueIfNecessaryAndTestIsPlaceholderShown(Element* element, const CheckingContext* checkingContext)
+{
+    if (checkingContext->resolvingMode == SelectorChecker::Mode::ResolvingStyle) {
+        if (RenderStyle* style = element->renderStyle())
+            style->setUnique();
+    }
+    return isPlaceholderShown(element);
+}
+
+void SelectorCodeGenerator::generateElementHasPlaceholderShown(Assembler::JumpList& failureCases, const SelectorFragment& fragment)
+{
+    if (m_selectorContext == SelectorContext::QuerySelector) {
+        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+        functionCall.setFunctionAddress(isPlaceholderShown);
+        functionCall.setOneArgument(elementAddressRegister);
+        failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
+        return;
+    }
+
+    if (fragmentMatchesTheRightmostElement(m_selectorContext, fragment)) {
+        {
+            LocalRegister checkingContext(m_registerAllocator);
+            Assembler::Jump notResolvingStyle = jumpIfNotResolvingStyle(checkingContext);
+            addFlagsToElementStyleFromContext(checkingContext, RenderStyle::NonInheritedFlags::flagIsUnique());
+            notResolvingStyle.link(&m_assembler);
+        }
+
+        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+        functionCall.setFunctionAddress(isPlaceholderShown);
+        functionCall.setOneArgument(elementAddressRegister);
+        failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
+    } else {
+        Assembler::RegisterID checkingContext = m_registerAllocator.allocateRegisterWithPreference(JSC::GPRInfo::argumentGPR1);
+        loadCheckingContext(checkingContext);
+        m_registerAllocator.deallocateRegister(checkingContext);
+
+        FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
+        functionCall.setFunctionAddress(makeUniqueIfNecessaryAndTestIsPlaceholderShown);
+        functionCall.setTwoArguments(elementAddressRegister, checkingContext);
+        failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
+    }
+}
+#endif
+
 inline void SelectorCodeGenerator::generateElementHasTagName(Assembler::JumpList& failureCases, const QualifiedName& nameToMatch)
 {
     if (nameToMatch == anyQName())

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (172825 => 172826)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2014-08-21 03:33:18 UTC (rev 172826)
@@ -636,7 +636,7 @@
         }
         // We only need to setChanged if the form is looking at the default value right now.
         if (!hasDirtyValue()) {
-            updatePlaceholderVisibility(false);
+            updatePlaceholderVisibility();
             setNeedsStyleRecalc();
         }
         setFormControlValueMatchesRenderer(false);

Modified: trunk/Source/WebCore/html/HTMLTextAreaElement.cpp (172825 => 172826)


--- trunk/Source/WebCore/html/HTMLTextAreaElement.cpp	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/html/HTMLTextAreaElement.cpp	2014-08-21 03:33:18 UTC (rev 172826)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll ([email protected])
  *           (C) 1999 Antti Koivisto ([email protected])
  *           (C) 2001 Dirk Mueller ([email protected])
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2014 Apple Inc. All rights reserved.
  *           (C) 2006 Alexey Proskuryakov ([email protected])
  * Copyright (C) 2007 Samuel Weinig ([email protected])
  *
@@ -345,7 +345,7 @@
     const_cast<HTMLTextAreaElement*>(this)->setFormControlValueMatchesRenderer(true);
     m_isDirty = true;
     m_wasModifiedByUser = true;
-    const_cast<HTMLTextAreaElement*>(this)->updatePlaceholderVisibility(false);
+    const_cast<HTMLTextAreaElement*>(this)->updatePlaceholderVisibility();
 }
 
 String HTMLTextAreaElement::value() const
@@ -385,7 +385,7 @@
     m_value = normalizedValue;
     setInnerTextValue(m_value);
     setLastChangeWasNotUserEdit();
-    updatePlaceholderVisibility(false);
+    updatePlaceholderVisibility();
     setNeedsStyleRecalc();
     setFormControlValueMatchesRenderer(true);
 
@@ -539,6 +539,7 @@
         RefPtr<HTMLDivElement> placeholder = HTMLDivElement::create(document());
         m_placeholder = placeholder.get();
         m_placeholder->setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral));
+        m_placeholder->setInlineStyleProperty(CSSPropertyDisplay, isPlaceholderVisible() ? CSSValueBlock : CSSValueNone, true);
         userAgentShadowRoot()->insertBefore(m_placeholder, innerTextElement()->nextSibling());
     }
     m_placeholder->setInnerText(placeholderText, ASSERT_NO_EXCEPTION);

Modified: trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp (172825 => 172826)


--- trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/html/HTMLTextFormControlElement.cpp	2014-08-21 03:33:18 UTC (rev 172826)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll ([email protected])
  *           (C) 1999 Antti Koivisto ([email protected])
  *           (C) 2001 Dirk Mueller ([email protected])
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2014 Apple Inc. All rights reserved.
  *           (C) 2006 Alexey Proskuryakov ([email protected])
  *
  * This library is free software; you can redistribute it and/or
@@ -38,6 +38,7 @@
 #include "HTMLInputElement.h"
 #include "HTMLNames.h"
 #include "NodeTraversal.h"
+#include "Page.h"
 #include "RenderBlockFlow.h"
 #include "RenderTextControlSingleLine.h"
 #include "RenderTheme.h"
@@ -55,10 +56,11 @@
 
 HTMLTextFormControlElement::HTMLTextFormControlElement(const QualifiedName& tagName, Document& document, HTMLFormElement* form)
     : HTMLFormControlElementWithState(tagName, document, form)
-    , m_lastChangeWasUserEdit(false)
     , m_cachedSelectionStart(-1)
     , m_cachedSelectionEnd(-1)
     , m_cachedSelectionDirection(SelectionHasNoDirection)
+    , m_lastChangeWasUserEdit(false)
+    , m_isPlaceholderVisible(false)
 {
 }
 
@@ -88,7 +90,7 @@
 void HTMLTextFormControlElement::dispatchFocusEvent(PassRefPtr<Element> oldFocusedElement, FocusDirection direction)
 {
     if (supportsPlaceholder())
-        updatePlaceholderVisibility(false);
+        updatePlaceholderVisibility();
     handleFocusEvent(oldFocusedElement.get(), direction);
     HTMLFormControlElementWithState::dispatchFocusEvent(oldFocusedElement, direction);
 }
@@ -96,7 +98,7 @@
 void HTMLTextFormControlElement::dispatchBlurEvent(PassRefPtr<Element> newFocusedElement)
 {
     if (supportsPlaceholder())
-        updatePlaceholderVisibility(false);
+        updatePlaceholderVisibility();
     handleBlurEvent();
     HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement);
 }
@@ -147,23 +149,26 @@
 
 bool HTMLTextFormControlElement::placeholderShouldBeVisible() const
 {
+    // This function is used by the style resolver to match the :placeholder-shown pseudo class.
+    // Since it is used for styling, it must not use any value depending on the style.
     return supportsPlaceholder()
         && isEmptyValue()
         && !isPlaceholderEmpty()
-        && (document().focusedElement() != this || (renderer() && renderer()->theme().shouldShowPlaceholderWhenFocused()))
-        && (!renderer() || renderer()->style().visibility() == VISIBLE);
+        && (document().focusedElement() != this || (document().page()->theme().shouldShowPlaceholderWhenFocused()));
 }
 
-void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderValueChanged)
+void HTMLTextFormControlElement::updatePlaceholderVisibility()
 {
-    if (!supportsPlaceholder())
+    bool placeHolderWasVisible = m_isPlaceholderVisible;
+    m_isPlaceholderVisible = placeholderShouldBeVisible();
+
+    if (placeHolderWasVisible == m_isPlaceholderVisible)
         return;
-    if (!placeholderElement() || placeholderValueChanged)
-        updatePlaceholderText();
-    HTMLElement* placeholder = placeholderElement();
-    if (!placeholder)
-        return;
-    placeholder->setInlineStyleProperty(CSSPropertyVisibility, placeholderShouldBeVisible() ? CSSValueVisible : CSSValueHidden);
+
+    setNeedsStyleRecalc();
+
+    if (HTMLElement* placeholder = placeholderElement())
+        placeholder->setInlineStyleProperty(CSSPropertyDisplay, m_isPlaceholderVisible ? CSSValueBlock : CSSValueNone, true);
 }
 
 void HTMLTextFormControlElement::setSelectionStart(int start)
@@ -396,7 +401,7 @@
     if (!isTextFormControl())
         return directionString(SelectionHasNoDirection);
     if (document().focusedElement() != this && hasCachedSelection())
-        return directionString(m_cachedSelectionDirection);
+        return directionString(cachedSelectionDirection());
 
     return directionString(computeSelectionDirection());
 }
@@ -466,7 +471,7 @@
 
 void HTMLTextFormControlElement::restoreCachedSelection()
 {
-    setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSelectionDirection);
+    setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, cachedSelectionDirection());
 }
 
 void HTMLTextFormControlElement::selectionChanged(bool shouldFireSelectEvent)
@@ -484,9 +489,10 @@
 
 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
-    if (name == placeholderAttr)
-        updatePlaceholderVisibility(true);
-    else
+    if (name == placeholderAttr) {
+        updatePlaceholderText();
+        updatePlaceholderVisibility();
+    } else
         HTMLFormControlElementWithState::parseAttribute(name, value);
 }
 
@@ -626,19 +632,14 @@
 #if PLATFORM(IOS)
 void HTMLTextFormControlElement::hidePlaceholder()
 {
-    if (!supportsPlaceholder())
-        return;
-    HTMLElement* placeholder = placeholderElement();
-    if (!placeholder) {
-        updatePlaceholderText();
-        return;
-    }
-    placeholder->setInlineStyleProperty(CSSPropertyVisibility, ASCIILiteral("hidden"));
+    if (HTMLElement* placeholder = placeholderElement())
+        placeholder->setInlineStyleProperty(CSSPropertyVisibility, CSSValueHidden, true);
 }
 
 void HTMLTextFormControlElement::showPlaceholderIfNecessary()
 {
-    updatePlaceholderVisibility(false);
+    if (HTMLElement* placeholder = placeholderElement())
+        placeholder->setInlineStyleProperty(CSSPropertyVisibility, CSSValueVisible, true);
 }
 #endif
 

Modified: trunk/Source/WebCore/html/HTMLTextFormControlElement.h (172825 => 172826)


--- trunk/Source/WebCore/html/HTMLTextFormControlElement.h	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/html/HTMLTextFormControlElement.h	2014-08-21 03:33:18 UTC (rev 172826)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll ([email protected])
  *           (C) 1999 Antti Koivisto ([email protected])
  *           (C) 2000 Dirk Mueller ([email protected])
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2014 Apple Inc. All rights reserved.
  * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -50,11 +50,11 @@
     virtual InsertionNotificationRequest insertedInto(ContainerNode&) override;
 
     // The derived class should return true if placeholder processing is needed.
+    bool isPlaceholderVisible() const { return m_isPlaceholderVisible; }
     virtual bool supportsPlaceholder() const = 0;
     String strippedPlaceholder() const;
-    bool placeholderShouldBeVisible() const;
     virtual HTMLElement* placeholderElement() const = 0;
-    void updatePlaceholderVisibility(bool);
+    void updatePlaceholderVisibility();
 
     int indexForVisiblePosition(const VisiblePosition&) const;
     VisiblePosition visiblePositionForIndex(int index) const;
@@ -120,6 +120,8 @@
     String valueWithHardLineBreaks() const;
 
 private:
+    TextFieldSelectionDirection cachedSelectionDirection() const { return static_cast<TextFieldSelectionDirection>(m_cachedSelectionDirection); }
+
     int computeSelectionStart() const;
     int computeSelectionEnd() const;
     TextFieldSelectionDirection computeSelectionDirection() const;
@@ -137,12 +139,16 @@
     // Called in dispatchBlurEvent(), after placeholder process, before calling parent's dispatchBlurEvent().
     virtual void handleBlurEvent() { }
 
+    bool placeholderShouldBeVisible() const;
+
     String m_textAsOfLastFormControlChangeEvent;
-    bool m_lastChangeWasUserEdit;
-    
+
     int m_cachedSelectionStart;
     int m_cachedSelectionEnd;
-    TextFieldSelectionDirection m_cachedSelectionDirection;
+
+    unsigned char m_cachedSelectionDirection : 2;
+    unsigned char m_lastChangeWasUserEdit : 1;
+    unsigned char m_isPlaceholderVisible : 1;
 };
 
 void isHTMLTextFormControlElement(const HTMLTextFormControlElement&); // Catch unnecessary runtime check of type known at compile time.

Modified: trunk/Source/WebCore/html/TextFieldInputType.cpp (172825 => 172826)


--- trunk/Source/WebCore/html/TextFieldInputType.cpp	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/html/TextFieldInputType.cpp	2014-08-21 03:33:18 UTC (rev 172826)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -409,6 +409,7 @@
     if (!m_placeholder) {
         m_placeholder = HTMLDivElement::create(element().document());
         m_placeholder->setPseudo(AtomicString("-webkit-input-placeholder", AtomicString::ConstructFromLiteral));
+        m_placeholder->setInlineStyleProperty(CSSPropertyDisplay, element().isPlaceholderVisible() ? CSSValueBlock : CSSValueNone, true);
         element().userAgentShadowRoot()->insertBefore(m_placeholder, m_container ? m_container.get() : innerTextElement(), ASSERT_NO_EXCEPTION);
     }
     m_placeholder->setInnerText(placeholderText, ASSERT_NO_EXCEPTION);
@@ -438,7 +439,7 @@
     // sanitizeUserInputValue().
     // sanitizeValue() is needed because IME input doesn't dispatch BeforeTextInsertedEvent.
     element().setValueFromRenderer(sanitizeValue(convertFromVisibleValue(element().innerTextValue())));
-    element().updatePlaceholderVisibility(false);
+    element().updatePlaceholderVisibility();
     // Recalc for :invalid change.
     element().setNeedsStyleRecalc();
 
@@ -472,7 +473,7 @@
         // Update the renderer value if the formControlValueMatchesRenderer() flag is false.
         // It protects an unacceptable renderer value from being overwritten with the DOM value.
         element().setInnerTextValue(visibleValue());
-        element().updatePlaceholderVisibility(false);
+        element().updatePlaceholderVisibility();
     }
 }
 

Modified: trunk/Source/WebCore/rendering/RenderTextControl.cpp (172825 => 172826)


--- trunk/Source/WebCore/rendering/RenderTextControl.cpp	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/rendering/RenderTextControl.cpp	2014-08-21 03:33:18 UTC (rev 172826)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2014 Apple Inc. All rights reserved.
  *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)  
  *
  * This library is free software; you can redistribute it and/or
@@ -70,7 +70,7 @@
         innerTextRenderer->style().setWidth(Length());
         innerTextRenderer->setStyle(createInnerTextStyle(&style()));
     }
-    textFormControlElement().updatePlaceholderVisibility(false);
+    textFormControlElement().updatePlaceholderVisibility();
 }
 
 void RenderTextControl::adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const

Modified: trunk/Source/WebCore/testing/Internals.cpp (172825 => 172826)


--- trunk/Source/WebCore/testing/Internals.cpp	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebCore/testing/Internals.cpp	2014-08-21 03:33:18 UTC (rev 172826)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2012 Google Inc. All rights reserved.
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -617,8 +617,11 @@
 String Internals::visiblePlaceholder(Element* element)
 {
     if (element && isHTMLTextFormControlElement(*element)) {
-        if (toHTMLTextFormControlElement(*element).placeholderShouldBeVisible())
-            return toHTMLTextFormControlElement(*element).placeholderElement()->textContent();
+        const HTMLTextFormControlElement& textFormControlElement = toHTMLTextFormControlElement(*element);
+        if (!textFormControlElement.isPlaceholderVisible())
+            return String();
+        if (HTMLElement* placeholderElement = textFormControlElement.placeholderElement())
+            return placeholderElement->textContent();
     }
 
     return String();

Modified: trunk/Source/WebKit/WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in (172825 => 172826)


--- trunk/Source/WebKit/WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in	2014-08-21 03:24:33 UTC (rev 172825)
+++ trunk/Source/WebKit/WebKit.vcxproj/WebKitExportGenerator/WebKitExports.def.in	2014-08-21 03:33:18 UTC (rev 172826)
@@ -262,7 +262,6 @@
         symbolWithPointer(?page@Document@WebCore@@QBEPAVPage@2@XZ, ?page@Document@WebCore@@QEBAPEAVPage@2@XZ)
         symbolWithPointer(?pageNumberForElement@PrintContext@WebCore@@SAHPAVElement@2@ABVFloatSize@2@@Z, ?pageNumberForElement@PrintContext@WebCore@@SAHPEAVElement@2@AEBVFloatSize@2@@Z)
         symbolWithPointer(?paintControlTints@FrameView@WebCore@@AAEXXZ, ?paintControlTints@FrameView@WebCore@@AEAAXXZ)
-        symbolWithPointer(?placeholderShouldBeVisible@HTMLTextFormControlElement@WebCore@@QBE_NXZ, ?placeholderShouldBeVisible@HTMLTextFormControlElement@WebCore@@QEBA_NXZ)
         symbolWithPointer(?rangeFromLocationAndLength@TextIterator@WebCore@@SA?AV?$PassRefPtr@VRange@WebCore@@@WTF@@PAVContainerNode@2@HH_N@Z, ?rangeFromLocationAndLength@TextIterator@WebCore@@SA?AV?$PassRefPtr@VRange@WebCore@@@WTF@@PEAVContainerNode@2@HH_N@Z)
         symbolWithPointer(?rectBasedTestResult@HitTestResult@WebCore@@QBEABV?$ListHashSet@V?$RefPtr@VNode@WebCore@@@WTF@@$0BAA@U?$PtrHash@V?$RefPtr@VNode@WebCore@@@WTF@@@2@@WTF@@XZ, ?rectBasedTestResult@HitTestResult@WebCore@@QEBAAEBV?$ListHashSet@V?$RefPtr@VNode@WebCore@@@WTF@@$0BAA@U?$PtrHash@V?$RefPtr@VNode@WebCore@@@WTF@@@2@@WTF@@XZ)
         symbolWithPointer(?rectForPoint@HitTestLocation@WebCore@@SA?AVIntRect@2@ABVLayoutPoint@2@IIII@Z, ?rectForPoint@HitTestLocation@WebCore@@SA?AVIntRect@2@AEBVLayoutPoint@2@IIII@Z)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to