Title: [202245] trunk
Revision
202245
Author
benja...@webkit.org
Date
2016-06-20 14:30:36 -0700 (Mon, 20 Jun 2016)

Log Message

:default CSS pseudo-class should match checkboxes+radios with a `checked` attribute
https://bugs.webkit.org/show_bug.cgi?id=156230

Reviewed by Alex Christensen.

LayoutTests/imported/w3c:

* web-platform-tests/html/semantics/selectors/pseudo-classes/default-expected.txt:

Source/WebCore:

This patch update the :default pseudo class matching to be closer to the spec:
https://html.spec.whatwg.org/multipage/scripting.html#selector-default

The main remaining difference with the spec is the definition of "default button".
This is an unrelated problem that should be addressed separately.

The implementation was missing support for:
-input elements of type "checkbox" or "radio" with the "checked" attribute defined.
-option elements with the "selected" attribute defined.

The existing support for default button was pretty bad, I fixed that too.
The owner form now has a resetDefaultButton() API. When a Form Associated Element
becomes a submit button or loses that property, the element calls its form
to update the style as needed.

Whenever the submit button changes, 2 elements needs to have their style invalidated:
-The former default button.
-The new default button.
To invalidate the former button, FormElement now caches the computed
default button. When the default button changes, the cached value is invalidated
in addition to the new value.

Computing the new default button takes linear time in the number of form associated element.
To mitigate that, resetDefaultButton() is only called when changes are related
to submit buttons. Since those changes are rare, I don't expect the invalidation
to be a problem.

Tests: fast/css/pseudo-default-basics.html
       fast/selectors/default-style-update.html

* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkOne):
* css/SelectorCheckerTestFunctions.h:
(WebCore::matchesDefaultPseudoClass):
(WebCore::isDefaultButtonForForm): Deleted.
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::addPseudoClassType):
* dom/Element.cpp:
(WebCore::Element::matchesValidPseudoClass):
(WebCore::Element::matchesInvalidPseudoClass):
(WebCore::Element::matchesDefaultPseudoClass):
* dom/Element.h:
(WebCore::Element::matchesValidPseudoClass): Deleted.
(WebCore::Element::matchesInvalidPseudoClass): Deleted.
(WebCore::Element::isDefaultButtonForForm): Deleted.
* html/HTMLButtonElement.cpp:
(WebCore::HTMLButtonElement::parseAttribute):
(WebCore::HTMLButtonElement::matchesDefaultPseudoClass):
* html/HTMLButtonElement.h:
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::isDefaultButtonForForm): Deleted.
* html/HTMLFormControlElement.h:
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::~HTMLFormElement):
(WebCore::HTMLFormElement::registerFormElement):
(WebCore::HTMLFormElement::removeFormElement):
(WebCore::HTMLFormElement::defaultButton):
(WebCore::HTMLFormElement::resetDefaultButton):
* html/HTMLFormElement.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::updateType):
(WebCore::HTMLInputElement::parseAttribute):
(WebCore::HTMLInputElement::matchesDefaultPseudoClass):
* html/HTMLInputElement.h:
* html/HTMLOptionElement.cpp:
(WebCore::HTMLOptionElement::matchesDefaultPseudoClass):
(WebCore::HTMLOptionElement::parseAttribute):
* html/HTMLOptionElement.h:
* style/StyleSharingResolver.cpp:
(WebCore::Style::SharingResolver::canShareStyleWithElement):
(WebCore::Style::canShareStyleWithControl): Deleted.

LayoutTests:

* fast/css/pseudo-default-basics-expected.html: Added.
* fast/css/pseudo-default-basics.html: Added.
* fast/selectors/default-style-update-expected.txt: Added.
* fast/selectors/default-style-update.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (202244 => 202245)


--- trunk/LayoutTests/ChangeLog	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/LayoutTests/ChangeLog	2016-06-20 21:30:36 UTC (rev 202245)
@@ -1,3 +1,15 @@
+2016-06-20  Benjamin Poulain  <benja...@webkit.org>
+
+        :default CSS pseudo-class should match checkboxes+radios with a `checked` attribute
+        https://bugs.webkit.org/show_bug.cgi?id=156230
+
+        Reviewed by Alex Christensen.
+
+        * fast/css/pseudo-default-basics-expected.html: Added.
+        * fast/css/pseudo-default-basics.html: Added.
+        * fast/selectors/default-style-update-expected.txt: Added.
+        * fast/selectors/default-style-update.html: Added.
+
 2016-06-20  Simon Fraser  <simon.fra...@apple.com>
 
         Focus event dispatched in iframe causes parent document to scroll incorrectly

Added: trunk/LayoutTests/fast/css/pseudo-default-basics-expected.html (0 => 202245)


--- trunk/LayoutTests/fast/css/pseudo-default-basics-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/pseudo-default-basics-expected.html	2016-06-20 21:30:36 UTC (rev 202245)
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<style>
+    * {
+        -webkit-appearance: none;
+    }
+    form, fieldset, option {
+        display: inline;
+    }
+    .default, .default + span {
+        background-color: green;
+        padding: 2px;
+    }
+    input:matches([type=checkbox], [type=radio] {
+        width: 30px;
+        height: 30px;
+    }
+</style>
+</head>
+<body>
+    <div>
+        <!-- Default button of type button -->
+        <button>Out of form</button>
+        <form>
+            <button class="default">First</button>
+        </form>
+        <form>
+            <button class="default">First</button>
+            <button>Second</button>
+        </form>
+        <form>
+            <fieldset>
+                <button class="default">First</button>
+            </fieldset>
+            <button>Second</button>
+        </form>
+    </div>
+    <div>
+        <!-- Default button of type input-->
+        <input>
+        <input type="text">
+        <input type="submit">
+        <input type="image">
+        <input value="WebKit">
+        <input type="text" value="WebKit">
+        <input type="submit" value="WebKit">
+        <input type="image" value="WebKit">
+        <form>
+            <input>
+        </form>
+        <form>
+            <input type="submit" class="default">
+        </form>
+        <form>
+            <input type="image" class="default">
+        </form>
+        <form>
+            <input>
+            <input type="submit" class="default">
+            <input type="image">
+        </form>
+        <form>
+            <input type="text">
+            <input type="image" class="default">
+            <input type="submit">
+        </form>
+        <form>
+            <button class="default">Button</button>
+            <input type="image">
+            <input type="submit">
+        </form>
+        <form>
+            <input type="submit" class="default">
+            <button>Button</button>
+            <input type="image">
+        </form>
+        <form>
+            <input type="image" class="default">
+            <input type="submit">
+            <button>Button</button>
+        </form>
+    </div>
+    <div>
+        <!-- Check boxes and radio button -->
+        <input type="checkbox"><span>A</span>
+        <input type="radio"><span>A</span>
+        <input type="checkbox" name="group1"><span>A</span>
+        <input type="radio" name="group1"><span>A</span>
+        <input type="checkbox" checked class="default"><span>A</span>
+        <input type="radio" checked class="default"><span>A</span>
+        <input type="checkbox" name="group1" checked class="default"><span>A</span>
+        <input type="radio" name="group1" checked class="default"><span>A</span>
+        <input type="checkbox" checked=false class="default"><span>A</span>
+        <input type="radio" checked=false class="default"><span>A</span>
+        <input type="checkbox" name="group1" checked=false class="default"><span>A</span>
+        <input type="radio" name="group1" checked=false class="default"><span>A</span>
+        <input type="checkbox" checked=webkit class="default"><span>A</span>
+        <input type="radio" checked=webkit class="default"><span>A</span>
+        <input type="checkbox" name="group1" checked=webkit class="default"><span>A</span>
+        <input type="radio" name="group1" checked=webkit class="default"><span>A</span>
+        <input type="checkbox" disabled><span>A</span>
+        <input type="radio" disabled><span>A</span>
+        <input type="checkbox" name="group1" disabled><span>A</span>
+        <input type="radio" name="group1" disabled><span>A</span>
+        <input type="checkbox" checked disabled class="default"><span>A</span>
+        <input type="radio" checked disabled class="default"><span>A</span>
+        <input type="checkbox" name="group1" checked disabled class="default"><span>A</span>
+        <input type="radio" name="group1" checked disabled class="default"><span>A</span>
+        <form>
+            <input type="checkbox"><span>A</span>
+            <input type="radio"><span>A</span>
+            <input type="checkbox" name="group1"><span>A</span>
+            <input type="radio" name="group1"><span>A</span>
+            <input type="checkbox" checked class="default"><span>A</span>
+            <input type="radio" checked class="default"><span>A</span>
+            <input type="checkbox" name="group1" checked class="default"><span>A</span>
+            <input type="radio" name="group1" checked class="default"><span>A</span>
+            <input type="checkbox" checked=false class="default"><span>A</span>
+            <input type="radio" checked=false class="default"><span>A</span>
+            <input type="checkbox" name="group1" checked=false class="default"><span>A</span>
+            <input type="radio" name="group1" checked=false class="default"><span>A</span>
+            <input type="checkbox" checked=webkit class="default"><span>A</span>
+            <input type="radio" checked=webkit class="default"><span>A</span>
+            <input type="checkbox" name="group1" checked=webkit class="default"><span>A</span>
+            <input type="radio" name="group1" checked=webkit class="default"><span>A</span>
+            <input type="checkbox" disabled><span>A</span>
+            <input type="radio" disabled><span>A</span>
+            <input type="checkbox" name="group1" disabled><span>A</span>
+            <input type="radio" name="group1" disabled><span>A</span>
+            <input type="checkbox" checked disabled class="default"><span>A</span>
+            <input type="radio" checked disabled class="default"><span>A</span>
+            <input type="checkbox" name="group1" checked disabled class="default"><span>A</span>
+            <input type="radio" name="group1" checked disabled class="default"><span>A</span>
+        </form>
+    </div>
+    <div>
+        <option>Option</option><span>Option</span>
+        <option selected class="default">Option</option><span>Option</span>
+        <option selected=false class="default">Option</option><span>Option</span>
+        <option selected=WebKit class="default">Option</option><span>Option</span>
+        <select>
+            <option>Option</option><span>Option</span>
+            <option selected class="default">Option</option><span>Option</span>
+            <option selected=false class="default">Option</option><span>Option</span>
+            <option selected=WebKit class="default">Option</option><span>Option</span>
+        </select>
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/css/pseudo-default-basics.html (0 => 202245)


--- trunk/LayoutTests/fast/css/pseudo-default-basics.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/pseudo-default-basics.html	2016-06-20 21:30:36 UTC (rev 202245)
@@ -0,0 +1,150 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<style>
+    * {
+        -webkit-appearance: none;
+    }
+    form, fieldset, option {
+        display: inline;
+    }
+    :default, :default + span {
+        background-color: green;
+        padding: 2px;
+    }
+    input:matches([type=checkbox], [type=radio] {
+        width: 30px;
+        height: 30px;
+    }
+</style>
+</head>
+<body>
+    <div>
+        <!-- Default button of type button -->
+        <button>Out of form</button>
+        <form>
+            <button>First</button>
+        </form>
+        <form>
+            <button>First</button>
+            <button>Second</button>
+        </form>
+        <form>
+            <fieldset>
+                <button>First</button>
+            </fieldset>
+            <button>Second</button>
+        </form>
+    </div>
+    <div>
+        <!-- Default button of type input-->
+        <input>
+        <input type="text">
+        <input type="submit">
+        <input type="image">
+        <input value="WebKit">
+        <input type="text" value="WebKit">
+        <input type="submit" value="WebKit">
+        <input type="image" value="WebKit">
+        <form>
+            <input>
+        </form>
+        <form>
+            <input type="submit">
+        </form>
+        <form>
+            <input type="image">
+        </form>
+        <form>
+            <input>
+            <input type="submit">
+            <input type="image">
+        </form>
+        <form>
+            <input type="text">
+            <input type="image">
+            <input type="submit">
+        </form>
+        <form>
+            <button>Button</button>
+            <input type="image">
+            <input type="submit">
+        </form>
+        <form>
+            <input type="submit">
+            <button>Button</button>
+            <input type="image">
+        </form>
+        <form>
+            <input type="image">
+            <input type="submit">
+            <button>Button</button>
+        </form>
+    </div>
+    <div>
+        <!-- Check boxes and radio button -->
+        <input type="checkbox"><span>A</span>
+        <input type="radio"><span>A</span>
+        <input type="checkbox" name="group1"><span>A</span>
+        <input type="radio" name="group1"><span>A</span>
+        <input type="checkbox" checked><span>A</span>
+        <input type="radio" checked><span>A</span>
+        <input type="checkbox" name="group1" checked><span>A</span>
+        <input type="radio" name="group1" checked><span>A</span>
+        <input type="checkbox" checked=false><span>A</span>
+        <input type="radio" checked=false><span>A</span>
+        <input type="checkbox" name="group1" checked=false><span>A</span>
+        <input type="radio" name="group1" checked=false><span>A</span>
+        <input type="checkbox" checked=webkit><span>A</span>
+        <input type="radio" checked=webkit><span>A</span>
+        <input type="checkbox" name="group1" checked=webkit><span>A</span>
+        <input type="radio" name="group1" checked=webkit><span>A</span>
+        <input type="checkbox" disabled><span>A</span>
+        <input type="radio" disabled><span>A</span>
+        <input type="checkbox" name="group1" disabled><span>A</span>
+        <input type="radio" name="group1" disabled><span>A</span>
+        <input type="checkbox" checked disabled><span>A</span>
+        <input type="radio" checked disabled><span>A</span>
+        <input type="checkbox" name="group1" checked disabled><span>A</span>
+        <input type="radio" name="group1" checked disabled><span>A</span>
+        <form>
+            <input type="checkbox"><span>A</span>
+            <input type="radio"><span>A</span>
+            <input type="checkbox" name="group1"><span>A</span>
+            <input type="radio" name="group1"><span>A</span>
+            <input type="checkbox" checked><span>A</span>
+            <input type="radio" checked><span>A</span>
+            <input type="checkbox" name="group1" checked><span>A</span>
+            <input type="radio" name="group1" checked><span>A</span>
+            <input type="checkbox" checked=false><span>A</span>
+            <input type="radio" checked=false><span>A</span>
+            <input type="checkbox" name="group1" checked=false><span>A</span>
+            <input type="radio" name="group1" checked=false><span>A</span>
+            <input type="checkbox" checked=webkit><span>A</span>
+            <input type="radio" checked=webkit><span>A</span>
+            <input type="checkbox" name="group1" checked=webkit><span>A</span>
+            <input type="radio" name="group1" checked=webkit><span>A</span>
+            <input type="checkbox" disabled><span>A</span>
+            <input type="radio" disabled><span>A</span>
+            <input type="checkbox" name="group1" disabled><span>A</span>
+            <input type="radio" name="group1" disabled><span>A</span>
+            <input type="checkbox" checked disabled><span>A</span>
+            <input type="radio" checked disabled><span>A</span>
+            <input type="checkbox" name="group1" checked disabled><span>A</span>
+            <input type="radio" name="group1" checked disabled><span>A</span>
+        </form>
+    </div>
+    <div>
+        <option>Option</option><span>Option</span>
+        <option selected>Option</option><span>Option</span>
+        <option selected=false>Option</option><span>Option</span>
+        <option selected=WebKit>Option</option><span>Option</span>
+        <select>
+            <option>Option</option><span>Option</span>
+            <option selected>Option</option><span>Option</span>
+            <option selected=false>Option</option><span>Option</span>
+            <option selected=WebKit>Option</option><span>Option</span>
+        </select>
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/selectors/default-style-update-expected.txt (0 => 202245)


--- trunk/LayoutTests/fast/selectors/default-style-update-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/default-style-update-expected.txt	2016-06-20 21:30:36 UTC (rev 202245)
@@ -0,0 +1,148 @@
+Check the basic features of the :default pseudo class
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial State
+PASS elementsStyledWithDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Changing input1 input a submit button, it should become the form's default button
+PASS elementsStyledWithDefaultSelector() is ["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Changing button order in the first form
+PASS elementsStyledWithDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Removing button2 from its form
+PASS elementsStyledWithDefaultSelector() is ["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS button2.matches(":default") is false
+Adding back button2
+PASS elementsStyledWithDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Setting button2 type to button
+PASS elementsStyledWithDefaultSelector() is ["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Setting button2 type to submit
+PASS elementsStyledWithDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Setting button2 type to reset
+PASS elementsStyledWithDefaultSelector() is ["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Setting button2 type to webkit
+PASS elementsStyledWithDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Removing the type attribute from button2
+PASS elementsStyledWithDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Removing input1, button2 is still the first button
+PASS elementsStyledWithDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS input1.matches(":default") is false
+Removing the form from the tree
+PASS elementsStyledWithDefaultSelector() is ["input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS button2.matches(":default") is true
+PASS input1.matches(":default") is false
+Changing the type of input2 to password
+PASS elementsStyledWithDefaultSelector() is ["button3", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Changing the type of input2 to image
+PASS elementsStyledWithDefaultSelector() is ["input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Moving input2 to the form of input3, before input3
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Moving button5 inside the first form, but button5 has a form attribute
+PASS elementsStyledWithDefaultSelector() is ["button5", "button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button5", "button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]
+Removing button 5
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS button5.matches(":default") is false
+Moving input5 above button 6
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input4", "input5", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input4", "input5", "input7", "input9", "input11", "option2", "option4"]
+Changing input5's type to submit
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input4", "input5", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input4", "input5", "input7", "input9", "input11", "option2", "option4"]
+Changing input5's type to reset
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]
+Removing free-form-1
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]
+Changing input5's type to image
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input5", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input5", "input7", "input9", "input11", "option2", "option4"]
+Removing input5
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]
+PASS input5.matches(":default") is false
+Removing button6
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input7", "input9", "input11", "option2", "option4"]
+PASS button6.matches(":default") is false
+Setting input6 as checked
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input7", "input9", "input11", "option2", "option4"]
+Setting the checked attribute to input6
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]
+Setting input7 as unchecked
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]
+Setting input7's checked attribute to 'WebKit'
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]
+Removing input7's checked attribute
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input6", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input6", "input9", "input11", "option2", "option4"]
+Setting input7's selected attribute
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input6", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input6", "input9", "input11", "option2", "option4"]
+Removing input6
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input9", "input11", "option2", "option4"]
+PASS input6.matches(":default") is true
+Setting input8 as checked
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input9", "input11", "option2", "option4"]
+Setting the checked attribute to input8
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "input9", "input11", "option2", "option4"]
+Setting input9 as unchecked
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "input9", "input11", "option2", "option4"]
+Setting input9's checked attribute to 'WebKit'
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "input9", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "input9", "input11", "option2", "option4"]
+Removing input9's checked attribute
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "input11", "option2", "option4"]
+Setting input9's selected attribute
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "input11", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "input11", "option2", "option4"]
+Removing input11
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "option2", "option4"]
+PASS input11.matches(":default") is true
+Add the selected attribute to option1
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "option1", "option2", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "option1", "option2", "option4"]
+Remove the selected attribute from option2
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "option1", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "option1", "option4"]
+Set the checked attribute on option2
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "option1", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "option1", "option4"]
+Add the selected attribute to false on  option3
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "option1", "option3", "option4"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "option1", "option3", "option4"]
+Remove option4
+PASS elementsStyledWithDefaultSelector() is ["button3", "input2", "input8", "option1", "option3"]
+PASS elementsMatchingDefaultSelector() is ["button3", "input2", "input8", "option1", "option3"]
+PASS option4.matches(":default") is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/default-style-update.html (0 => 202245)


--- trunk/LayoutTests/fast/selectors/default-style-update.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/default-style-update.html	2016-06-20 21:30:36 UTC (rev 202245)
@@ -0,0 +1,337 @@
+<!doctype html>
+<html>
+<head>
+<script src=""
+<style>
+#webkit-test * {
+    background-color: white;
+}
+#webkit-test :default {
+    background-color: rgb(1, 2, 3);
+}
+</style>
+</head>
+<body>
+    <div style="display:none" id="webkit-test">
+        <button id="button1">Button1</button>
+        <form>
+            <input id="input1">
+            <button id="button2">Button2</button>
+        </form>
+        <form>
+            <input id="input2" type="submit">
+            <button id="button3">Button3</button>
+        </form>
+        <form>
+            <input id="input3" type="image">
+            <button id="button4">Button4</button>
+        </form>
+        <form id="free-form-1">
+        </form>
+        <input id="input4" type="submit" form="free-form-1">
+        <button id="button5" form="free-form-1">Button5</button>
+        <form id="free-form-2">
+        </form>
+        <button id="button6" form="free-form-2">Button6</button>
+        <input id="input5" type="image" form="free-form-2">
+        <input type="checkbox" id="input6">
+        <input type="checkbox" id="input7" checked>
+        <input type="radio" id="input8">
+        <input type="radio" id="input9" checked>
+        <input type="radio" id="input10" name="group1">
+        <input type="radio" id="input11" name="group1" checked>
+        <option id="option1">Option</option>
+        <option selected id="option2">Option</option>
+        <select>
+            <option id="option3">Option</option>
+            <option selected id="option4">Option</option>
+        </select>
+    </div>
+</body>
+<script>
+"use strict";
+description('Check the basic features of the :default pseudo class');
+
+function elementsStyledWithDefaultSelector() {
+    let elements = [];
+    for (let element of document.querySelectorAll("#webkit-test *")) {
+        if (getComputedStyle(element).backgroundColor === 'rgb(1, 2, 3)') {
+            elements.push(element.id);
+        }
+    }
+    return elements;
+}
+
+function elementsMatchingDefaultSelector() {
+    let elements = [];
+    for (let element of document.querySelectorAll(":default")) {
+        elements.push(element.id);
+    }
+    return elements;
+}
+
+debug("Initial State");
+shouldBe('elementsStyledWithDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Changing input1 input a submit button, it should become the form's default button");
+var input1 = document.getElementById("input1");
+input1.type = "submit";
+shouldBe('elementsStyledWithDefaultSelector()', '["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Changing button order in the first form");
+input1.parentElement.appendChild(input1);
+shouldBe('elementsStyledWithDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Removing button2 from its form");
+var button2 = document.getElementById("button2");
+button2.parentElement.removeChild(button2);
+shouldBe('elementsStyledWithDefaultSelector()', '["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBeFalse('button2.matches(":default")');
+
+debug("Adding back button2");
+input1.parentElement.insertBefore(button2, input1);
+shouldBe('elementsStyledWithDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Setting button2 type to button");
+button2.setAttribute("type", "button");
+shouldBe('elementsStyledWithDefaultSelector()', '["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Setting button2 type to submit");
+button2.setAttribute("type", "submit");
+shouldBe('elementsStyledWithDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Setting button2 type to reset");
+button2.setAttribute("type", "reset");
+shouldBe('elementsStyledWithDefaultSelector()', '["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["input1", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Setting button2 type to webkit");
+button2.setAttribute("type", "webkit");
+shouldBe('elementsStyledWithDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Removing the type attribute from button2");
+button2.removeAttribute("type");
+shouldBe('elementsStyledWithDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Removing input1, button2 is still the first button");
+input1.parentElement.removeChild(input1);
+shouldBe('elementsStyledWithDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button2", "input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBeFalse('input1.matches(":default")');
+
+debug("Removing the form from the tree");
+var firstRemovedForm = button2.parentElement;
+firstRemovedForm.parentElement.removeChild(firstRemovedForm);
+shouldBe('elementsStyledWithDefaultSelector()', '["input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBeTrue('button2.matches(":default")');
+shouldBeFalse('input1.matches(":default")');
+
+// Give GC a chance to collect.
+firstRemovedForm = undefined;
+input1 = undefined;
+button2 = undefined;
+
+debug("Changing the type of input2 to password");
+var input2 = document.getElementById("input2");
+input2.setAttribute("type", "password");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Changing the type of input2 to image");
+input2.setAttribute("type", "image");
+shouldBe('elementsStyledWithDefaultSelector()', '["input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["input2", "input3", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Moving input2 to the form of input3, before input3");
+var input3 = document.getElementById("input3");
+input3.parentElement.insertBefore(input2, input3);
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Moving button5 inside the first form, but button5 has a form attribute");
+var button3 = document.getElementById("button3");
+var button5 = document.getElementById("button5");
+button3.parentElement.insertBefore(button5, button3);
+shouldBe('elementsStyledWithDefaultSelector()', '["button5", "button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button5", "button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Removing button 5");
+button5.parentElement.removeChild(button5);
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBeFalse('button5.matches(":default")');
+button5 = undefined;
+
+debug("Moving input5 above button 6");
+var input5 = document.getElementById("input5");
+var button6 = document.getElementById("button6");
+input5.parentElement.insertBefore(input5, button6)
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input4", "input5", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input4", "input5", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Changing input5's type to submit");
+input5.type = "SUBMIT";
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input4", "input5", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input4", "input5", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Changing input5's type to reset");
+input5.type = "reset";
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input4", "button6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Removing free-form-1");
+var freeForm1 = document.getElementById("free-form-1");
+freeForm1.parentElement.removeChild(freeForm1);
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]');
+freeForm1 = undefined;
+
+debug("Changing input5's type to image");
+input5.type = "image";
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input5", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input5", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Removing input5");
+input5.parentElement.removeChild(input5);
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "button6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBeFalse('input5.matches(":default")');
+input5 = undefined;
+
+debug("Removing button6");
+button6.parentElement.removeChild(button6);
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input7", "input9", "input11", "option2", "option4"]');
+shouldBeFalse('button6.matches(":default")');
+button6 = undefined;
+
+debug("Setting input6 as checked");
+var input6 = document.getElementById("input6");
+// Interestingly, the selector looks for the attribute, not the state.
+input6.checked = true;
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Setting the checked attribute to input6");
+input6.setAttribute("checked", "");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Setting input7 as unchecked");
+var input7 = document.getElementById("input7");
+// Interestingly, the selector looks for the attribute, not the state.
+input7.checked = false;
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Setting input7's checked attribute to 'WebKit'");
+input7.setAttribute("checked", "WebKit");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input6", "input7", "input9", "input11", "option2", "option4"]');
+
+debug("Removing input7's checked attribute");
+input7.removeAttribute("checked");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input6", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input6", "input9", "input11", "option2", "option4"]');
+
+debug("Setting input7's selected attribute");
+input7.setAttribute("selected", "");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input6", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input6", "input9", "input11", "option2", "option4"]');
+
+debug("Removing input6");
+input6.parentElement.removeChild(input6);
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input9", "input11", "option2", "option4"]');
+shouldBeTrue('input6.matches(":default")');
+input6 = undefined;
+
+debug("Setting input8 as checked");
+var input8 = document.getElementById("input8");
+// Interestingly, the selector looks for the attribute, not the state.
+input8.checked = true;
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input9", "input11", "option2", "option4"]');
+
+debug("Setting the checked attribute to input8");
+input8.setAttribute("checked", "");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "input9", "input11", "option2", "option4"]');
+
+debug("Setting input9 as unchecked");
+var input9 = document.getElementById("input9");
+// Interestingly, the selector looks for the attribute, not the state.
+input9.checked = false;
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "input9", "input11", "option2", "option4"]');
+
+debug("Setting input9's checked attribute to 'WebKit'");
+input9.setAttribute("checked", "WebKit");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "input9", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "input9", "input11", "option2", "option4"]');
+
+debug("Removing input9's checked attribute");
+input9.removeAttribute("checked");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "input11", "option2", "option4"]');
+
+debug("Setting input9's selected attribute");
+input9.setAttribute("selected", "");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "input11", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "input11", "option2", "option4"]');
+
+debug("Removing input11");
+var input11 = document.getElementById("input11");
+input11.parentElement.removeChild(input11);
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "option2", "option4"]');
+shouldBeTrue('input11.matches(":default")');
+input11 = undefined;
+
+debug("Add the selected attribute to option1");
+var option1 = document.getElementById("option1");
+option1.setAttribute("selected", "");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "option1", "option2", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "option1", "option2", "option4"]');
+
+debug("Remove the selected attribute from option2");
+var option2 = document.getElementById("option2");
+option2.removeAttribute("selected");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "option1", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "option1", "option4"]');
+
+debug("Set the checked attribute on option2");
+var option2 = document.getElementById("option2");
+option2.setAttribute("checked", "");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "option1", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "option1", "option4"]');
+
+debug("Add the selected attribute to false on  option3");
+var option3 = document.getElementById("option3");
+option3.setAttribute("selected", "false");
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "option1", "option3", "option4"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "option1", "option3", "option4"]');
+
+debug("Remove option4");
+var option4 = document.getElementById("option4");
+option4.parentElement.removeChild(option4);
+shouldBe('elementsStyledWithDefaultSelector()', '["button3", "input2", "input8", "option1", "option3"]');
+shouldBe('elementsMatchingDefaultSelector()', '["button3", "input2", "input8", "option1", "option3"]');
+shouldBeTrue('option4.matches(":default")');
+option4 = undefined;
+
+gc();
+
+</script>
+<script src=""
+</html>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (202244 => 202245)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2016-06-20 21:30:36 UTC (rev 202245)
@@ -1,3 +1,12 @@
+2016-06-20  Benjamin Poulain  <benja...@webkit.org>
+
+        :default CSS pseudo-class should match checkboxes+radios with a `checked` attribute
+        https://bugs.webkit.org/show_bug.cgi?id=156230
+
+        Reviewed by Alex Christensen.
+
+        * web-platform-tests/html/semantics/selectors/pseudo-classes/default-expected.txt:
+
 2016-06-17  Benjamin Poulain  <benja...@webkit.org>
 
         :indeterminate pseudo-class should match radios whose group has no checked radio

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/selectors/pseudo-classes/default-expected.txt (202244 => 202245)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/selectors/pseudo-classes/default-expected.txt	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/html/semantics/selectors/pseudo-classes/default-expected.txt	2016-06-20 21:30:36 UTC (rev 202245)
@@ -10,6 +10,6 @@
 button6  button7
 button8  button9
 
-FAIL ':default' matches <button>s that are their form's default button, <input>s of type submit/image that are their form's default button, checked <input>s and selected <option>s assert_array_equals: lengths differ, expected 10 got 7
-FAIL ':default' matches dynamically changed form's default buttons assert_array_equals: lengths differ, expected 10 got 7
+PASS ':default' matches <button>s that are their form's default button, <input>s of type submit/image that are their form's default button, checked <input>s and selected <option>s 
+PASS ':default' matches dynamically changed form's default buttons 
 

Modified: trunk/Source/WebCore/ChangeLog (202244 => 202245)


--- trunk/Source/WebCore/ChangeLog	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/ChangeLog	2016-06-20 21:30:36 UTC (rev 202245)
@@ -1,3 +1,82 @@
+2016-06-20  Benjamin Poulain  <benja...@webkit.org>
+
+        :default CSS pseudo-class should match checkboxes+radios with a `checked` attribute
+        https://bugs.webkit.org/show_bug.cgi?id=156230
+
+        Reviewed by Alex Christensen.
+
+        This patch update the :default pseudo class matching to be closer to the spec:
+        https://html.spec.whatwg.org/multipage/scripting.html#selector-default
+
+        The main remaining difference with the spec is the definition of "default button".
+        This is an unrelated problem that should be addressed separately.
+
+        The implementation was missing support for:
+        -input elements of type "checkbox" or "radio" with the "checked" attribute defined.
+        -option elements with the "selected" attribute defined.
+
+        The existing support for default button was pretty bad, I fixed that too.
+        The owner form now has a resetDefaultButton() API. When a Form Associated Element
+        becomes a submit button or loses that property, the element calls its form
+        to update the style as needed.
+
+        Whenever the submit button changes, 2 elements needs to have their style invalidated:
+        -The former default button.
+        -The new default button.
+        To invalidate the former button, FormElement now caches the computed
+        default button. When the default button changes, the cached value is invalidated
+        in addition to the new value.
+
+        Computing the new default button takes linear time in the number of form associated element.
+        To mitigate that, resetDefaultButton() is only called when changes are related
+        to submit buttons. Since those changes are rare, I don't expect the invalidation
+        to be a problem.
+
+        Tests: fast/css/pseudo-default-basics.html
+               fast/selectors/default-style-update.html
+
+        * css/SelectorChecker.cpp:
+        (WebCore::SelectorChecker::checkOne):
+        * css/SelectorCheckerTestFunctions.h:
+        (WebCore::matchesDefaultPseudoClass):
+        (WebCore::isDefaultButtonForForm): Deleted.
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::addPseudoClassType):
+        * dom/Element.cpp:
+        (WebCore::Element::matchesValidPseudoClass):
+        (WebCore::Element::matchesInvalidPseudoClass):
+        (WebCore::Element::matchesDefaultPseudoClass):
+        * dom/Element.h:
+        (WebCore::Element::matchesValidPseudoClass): Deleted.
+        (WebCore::Element::matchesInvalidPseudoClass): Deleted.
+        (WebCore::Element::isDefaultButtonForForm): Deleted.
+        * html/HTMLButtonElement.cpp:
+        (WebCore::HTMLButtonElement::parseAttribute):
+        (WebCore::HTMLButtonElement::matchesDefaultPseudoClass):
+        * html/HTMLButtonElement.h:
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::isDefaultButtonForForm): Deleted.
+        * html/HTMLFormControlElement.h:
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::~HTMLFormElement):
+        (WebCore::HTMLFormElement::registerFormElement):
+        (WebCore::HTMLFormElement::removeFormElement):
+        (WebCore::HTMLFormElement::defaultButton):
+        (WebCore::HTMLFormElement::resetDefaultButton):
+        * html/HTMLFormElement.h:
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::updateType):
+        (WebCore::HTMLInputElement::parseAttribute):
+        (WebCore::HTMLInputElement::matchesDefaultPseudoClass):
+        * html/HTMLInputElement.h:
+        * html/HTMLOptionElement.cpp:
+        (WebCore::HTMLOptionElement::matchesDefaultPseudoClass):
+        (WebCore::HTMLOptionElement::parseAttribute):
+        * html/HTMLOptionElement.h:
+        * style/StyleSharingResolver.cpp:
+        (WebCore::Style::SharingResolver::canShareStyleWithElement):
+        (WebCore::Style::canShareStyleWithControl): Deleted.
+
 2016-06-20  Simon Fraser  <simon.fra...@apple.com>
 
         Focus event dispatched in iframe causes parent document to scroll incorrectly

Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (202244 => 202245)


--- trunk/Source/WebCore/css/SelectorChecker.cpp	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp	2016-06-20 21:30:36 UTC (rev 202245)
@@ -965,7 +965,7 @@
         case CSSSelector::PseudoClassFullPageMedia:
             return isMediaDocument(element);
         case CSSSelector::PseudoClassDefault:
-            return isDefaultButtonForForm(element);
+            return matchesDefaultPseudoClass(element);
         case CSSSelector::PseudoClassDisabled:
             return isDisabled(element);
         case CSSSelector::PseudoClassReadOnly:

Modified: trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h (202244 => 202245)


--- trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h	2016-06-20 21:30:36 UTC (rev 202245)
@@ -46,9 +46,9 @@
     return is<HTMLInputElement>(element) && downcast<HTMLInputElement>(element).isAutoFilled();
 }
 
-ALWAYS_INLINE bool isDefaultButtonForForm(const Element& element)
+ALWAYS_INLINE bool matchesDefaultPseudoClass(const Element& element)
 {
-    return element.isDefaultButtonForForm();
+    return element.matchesDefaultPseudoClass();
 }
 
 ALWAYS_INLINE bool isDisabled(const Element& element)

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (202244 => 202245)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2016-06-20 21:30:36 UTC (rev 202245)
@@ -535,7 +535,7 @@
         fragment.unoptimizedPseudoClasses.append(JSC::FunctionPtr(isChecked));
         return FunctionType::SimpleSelectorChecker;
     case CSSSelector::PseudoClassDefault:
-        fragment.unoptimizedPseudoClasses.append(JSC::FunctionPtr(isDefaultButtonForForm));
+        fragment.unoptimizedPseudoClasses.append(JSC::FunctionPtr(matchesDefaultPseudoClass));
         return FunctionType::SimpleSelectorChecker;
     case CSSSelector::PseudoClassDisabled:
         fragment.unoptimizedPseudoClasses.append(JSC::FunctionPtr(isDisabled));

Modified: trunk/Source/WebCore/dom/Element.cpp (202244 => 202245)


--- trunk/Source/WebCore/dom/Element.cpp	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/dom/Element.cpp	2016-06-20 21:30:36 UTC (rev 202245)
@@ -2747,6 +2747,16 @@
     elementRareData()->setAfterPseudoElement(nullptr);
 }
 
+bool Element::matchesValidPseudoClass() const
+{
+    return false;
+}
+
+bool Element::matchesInvalidPseudoClass() const
+{
+    return false;
+}
+
 bool Element::matchesReadWritePseudoClass() const
 {
     return false;
@@ -2757,6 +2767,11 @@
     return shouldAppearIndeterminate();
 }
 
+bool Element::matchesDefaultPseudoClass() const
+{
+    return false;
+}
+
 bool Element::matches(const String& selector, ExceptionCode& ec)
 {
     SelectorQuery* selectorQuery = document().selectorQueryForString(selector, ec);

Modified: trunk/Source/WebCore/dom/Element.h (202244 => 202245)


--- trunk/Source/WebCore/dom/Element.h	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/dom/Element.h	2016-06-20 21:30:36 UTC (rev 202245)
@@ -391,8 +391,11 @@
     bool childNeedsShadowWalker() const;
     void didShadowTreeAwareChildrenChange();
 
+    virtual bool matchesValidPseudoClass() const;
+    virtual bool matchesInvalidPseudoClass() const;
     virtual bool matchesReadWritePseudoClass() const;
     virtual bool matchesIndeterminatePseudoClass() const;
+    virtual bool matchesDefaultPseudoClass() const;
     bool matches(const String& selectors, ExceptionCode&);
     Element* closest(const String& selectors, ExceptionCode&);
     virtual bool shouldAppearIndeterminate() const;
@@ -405,14 +408,11 @@
     virtual bool isMediaElement() const { return false; }
 #endif
 
-    virtual bool matchesValidPseudoClass() const { return false; }
-    virtual bool matchesInvalidPseudoClass() const { return false; }
     virtual bool isFormControlElement() const { return false; }
     virtual bool isSpinButtonElement() const { return false; }
     virtual bool isTextFormControl() const { return false; }
     virtual bool isOptionalFormControl() const { return false; }
     virtual bool isRequiredFormControl() const { return false; }
-    virtual bool isDefaultButtonForForm() const { return false; }
     virtual bool isInRange() const { return false; }
     virtual bool isOutOfRange() const { return false; }
     virtual bool isFrameElementBase() const { return false; }

Modified: trunk/Source/WebCore/html/HTMLButtonElement.cpp (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLButtonElement.cpp	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLButtonElement.cpp	2016-06-20 21:30:36 UTC (rev 202245)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (kn...@kde.org)
  *           (C) 1999 Antti Koivisto (koivi...@kde.org)
  *           (C) 2001 Dirk Mueller (muel...@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2010, 2016 Apple Inc. All rights reserved.
  *           (C) 2006 Alexey Proskuryakov (a...@nypop.com)
  * Copyright (C) 2007 Samuel Weinig (s...@webkit.org)
  *
@@ -96,6 +96,7 @@
 void HTMLButtonElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
     if (name == typeAttr) {
+        Type oldType = m_type;
         if (equalLettersIgnoringASCIICase(value, "reset"))
             m_type = RESET;
         else if (equalLettersIgnoringASCIICase(value, "button"))
@@ -102,7 +103,11 @@
             m_type = BUTTON;
         else
             m_type = SUBMIT;
-        setNeedsWillValidateCheck();
+        if (oldType != m_type) {
+            setNeedsWillValidateCheck();
+            if (form() && (oldType == SUBMIT || m_type == SUBMIT))
+                form()->resetDefaultButton();
+        }
     } else
         HTMLFormControlElement::parseAttribute(name, value);
 }
@@ -164,6 +169,11 @@
     return m_type == SUBMIT && !isDisabledFormControl();
 }
 
+bool HTMLButtonElement::matchesDefaultPseudoClass() const
+{
+    return isSuccessfulSubmitButton() && form() && form()->defaultButton() == this;
+}
+
 bool HTMLButtonElement::isActivatedSubmit() const
 {
     return m_isActivatedSubmit;

Modified: trunk/Source/WebCore/html/HTMLButtonElement.h (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLButtonElement.h	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLButtonElement.h	2016-06-20 21:30:36 UTC (rev 202245)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (kn...@kde.org)
  *           (C) 1999 Antti Koivisto (koivi...@kde.org)
  *           (C) 2000 Dirk Mueller (muel...@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2010, 2016 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
@@ -63,6 +63,7 @@
     bool supportLabels() const override { return true; }
 
     bool isSuccessfulSubmitButton() const override;
+    bool matchesDefaultPseudoClass() const override;
     bool isActivatedSubmit() const override;
     void setActivatedSubmit(bool flag) override;
 

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.cpp (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.cpp	2016-06-20 21:30:36 UTC (rev 202245)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (kn...@kde.org)
  *           (C) 1999 Antti Koivisto (koivi...@kde.org)
  *           (C) 2001 Dirk Mueller (muel...@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2016 Apple Inc. All rights reserved.
  *           (C) 2006 Alexey Proskuryakov (a...@nypop.com)
  *
  * This library is free software; you can redistribute it and/or
@@ -564,11 +564,6 @@
     return FormAssociatedElement::form();
 }
 
-bool HTMLFormControlElement::isDefaultButtonForForm() const
-{
-    return isSuccessfulSubmitButton() && form() && form()->defaultButton() == this;
-}
-
 #if ENABLE(IOS_AUTOCORRECT_AND_AUTOCAPITALIZE)
 
 // FIXME: We should look to share this code with class HTMLFormElement instead of duplicating the logic.

Modified: trunk/Source/WebCore/html/HTMLFormControlElement.h (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLFormControlElement.h	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLFormControlElement.h	2016-06-20 21:30:36 UTC (rev 202245)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (kn...@kde.org)
  *           (C) 1999 Antti Koivisto (koivi...@kde.org)
  *           (C) 2000 Dirk Mueller (muel...@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2016 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
@@ -72,7 +72,6 @@
     void dispatchFormControlInputEvent();
 
     bool isDisabledFormControl() const override;
-    bool isDefaultButtonForForm() const override;
 
     bool isFocusable() const override;
     bool isEnumeratable() const override { return false; }

Modified: trunk/Source/WebCore/html/HTMLFormElement.cpp (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLFormElement.cpp	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLFormElement.cpp	2016-06-20 21:30:36 UTC (rev 202245)
@@ -88,6 +88,7 @@
     if (!shouldAutocomplete())
         document().unregisterForDocumentSuspensionCallbacks(this);
 
+    m_defaultButton = nullptr;
     for (auto& associatedElement : m_associatedElements)
         associatedElement->formWillBeDestroyed();
     for (auto& imageElement : m_imageElements)
@@ -593,6 +594,16 @@
 void HTMLFormElement::registerFormElement(FormAssociatedElement* e)
 {
     m_associatedElements.insert(formElementIndex(e), e);
+
+    if (is<HTMLFormControlElement>(e)) {
+        HTMLFormControlElement& control = downcast<HTMLFormControlElement>(*e);
+        if (control.isSuccessfulSubmitButton()) {
+            if (!m_defaultButton)
+                control.setNeedsStyleRecalc();
+            else
+                resetDefaultButton();
+        }
+    }
 }
 
 void HTMLFormElement::removeFormElement(FormAssociatedElement* e)
@@ -605,6 +616,9 @@
         --m_associatedElementsAfterIndex;
     removeFromPastNamesMap(e);
     m_associatedElements.remove(index);
+
+    if (e == m_defaultButton)
+        resetDefaultButton();
 }
 
 void HTMLFormElement::registerInvalidAssociatedFormControl(const HTMLFormControlElement& formControlElement)
@@ -703,15 +717,38 @@
 
 HTMLFormControlElement* HTMLFormElement::defaultButton() const
 {
-    for (auto& associatedElement : m_associatedElements) {
-        if (!is<HTMLFormControlElement>(*associatedElement))
-            continue;
-        HTMLFormControlElement& control = downcast<HTMLFormControlElement>(*associatedElement);
-        if (control.isSuccessfulSubmitButton())
-            return &control;
+    if (!m_defaultButton) {
+        for (auto& associatedElement : m_associatedElements) {
+            if (!is<HTMLFormControlElement>(*associatedElement))
+                continue;
+            HTMLFormControlElement& control = downcast<HTMLFormControlElement>(*associatedElement);
+            if (control.isSuccessfulSubmitButton()) {
+                m_defaultButton = &control;
+                break;
+            }
+        }
     }
+    return m_defaultButton;
+}
 
-    return nullptr;
+void HTMLFormElement::resetDefaultButton()
+{
+    if (!m_defaultButton) {
+        // Computing the default button is not cheap, we don't want to do it unless needed.
+        // If there was no default button set, the only style to invalidate is the element
+        // being added to the form. This is done explicitely in registerFormElement().
+        return;
+    }
+
+    HTMLFormControlElement* oldDefault = m_defaultButton;
+    m_defaultButton = nullptr;
+    defaultButton();
+    if (m_defaultButton != oldDefault) {
+        if (oldDefault)
+            oldDefault->setNeedsStyleRecalc();
+        if (m_defaultButton)
+            m_defaultButton->setNeedsStyleRecalc();
+    }
 }
 
 bool HTMLFormElement::checkValidity()

Modified: trunk/Source/WebCore/html/HTMLFormElement.h (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLFormElement.h	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLFormElement.h	2016-06-20 21:30:36 UTC (rev 202245)
@@ -116,6 +116,7 @@
     bool wasUserSubmitted() const;
 
     HTMLFormControlElement* defaultButton() const;
+    void resetDefaultButton();
 
     bool checkValidity();
 
@@ -186,6 +187,7 @@
     std::unique_ptr<PastNamesMap> m_pastNamesMap;
 
     RadioButtonGroups m_radioButtonGroups;
+    mutable HTMLFormControlElement* m_defaultButton { nullptr };
 
     unsigned m_associatedElementsBeforeIndex;
     unsigned m_associatedElementsAfterIndex;

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2016-06-20 21:30:36 UTC (rev 202245)
@@ -465,6 +465,7 @@
     bool didStoreValue = m_inputType->storesValueSeparateFromAttribute();
     bool neededSuspensionCallback = needsSuspensionCallback();
     bool didRespectHeightAndWidth = m_inputType->shouldRespectHeightAndWidthAttributes();
+    bool wasSuccessfulSubmitButtonCandidate = m_inputType->canBeSuccessfulSubmitButton();
 
     m_inputType->destroyShadowSubtree();
 
@@ -507,6 +508,9 @@
             attributeChanged(alignAttr, nullAtom, align->value());
     }
 
+    if (form() && wasSuccessfulSubmitButtonCandidate != m_inputType->canBeSuccessfulSubmitButton())
+        form()->resetDefaultButton();
+
     runPostTypeUpdateTasks();
 }
 
@@ -677,6 +681,9 @@
         updateValidity();
         m_valueAttributeWasUpdatedAfterParsing = !m_parsingInProgress;
     } else if (name == checkedAttr) {
+        if (m_inputType->isCheckable())
+            setNeedsStyleRecalc();
+
         // Another radio button in the same group might be checked by state
         // restore. We shouldn't call setChecked() even if this has the checked
         // attribute. So, delay the setChecked() call until
@@ -816,6 +823,14 @@
     return !isDisabledFormControl() && m_inputType->canBeSuccessfulSubmitButton();
 }
 
+bool HTMLInputElement::matchesDefaultPseudoClass() const
+{
+    ASSERT(m_inputType);
+    if (m_inputType->canBeSuccessfulSubmitButton())
+        return !isDisabledFormControl() && form() && form()->defaultButton() == this;
+    return m_inputType->isCheckable() && fastHasAttribute(checkedAttr);
+}
+
 bool HTMLInputElement::isActivatedSubmit() const
 {
     return m_isActivatedSubmit;

Modified: trunk/Source/WebCore/html/HTMLInputElement.h (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLInputElement.h	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLInputElement.h	2016-06-20 21:30:36 UTC (rev 202245)
@@ -380,6 +380,7 @@
     bool appendFormData(FormDataList&, bool) final;
 
     bool isSuccessfulSubmitButton() const final;
+    bool matchesDefaultPseudoClass() const final;
 
     void reset() final;
 

Modified: trunk/Source/WebCore/html/HTMLOptionElement.cpp (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLOptionElement.cpp	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLOptionElement.cpp	2016-06-20 21:30:36 UTC (rev 202245)
@@ -3,7 +3,7 @@
  *           (C) 1999 Antti Koivisto (koivi...@kde.org)
  *           (C) 2001 Dirk Mueller (muel...@kde.org)
  *           (C) 2006 Alexey Proskuryakov (a...@nypop.com)
- * Copyright (C) 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2010, 2016 Apple Inc. All rights reserved.
  * Copyright (C) 2010 Google Inc. All rights reserved.
  * Copyright (C) 2011 Motorola Mobility, Inc.  All rights reserved.
  *
@@ -96,6 +96,11 @@
     return style && style->display() != NONE;
 }
 
+bool HTMLOptionElement::matchesDefaultPseudoClass() const
+{
+    return fastHasAttribute(selectedAttr);
+}
+
 String HTMLOptionElement::text() const
 {
     String text = collectOptionInnerText();
@@ -174,6 +179,8 @@
                 renderer()->theme().stateChanged(*renderer(), ControlStates::EnabledState);
         }
     } else if (name == selectedAttr) {
+        setNeedsStyleRecalc();
+
         // FIXME: This doesn't match what the HTML specification says.
         // The specification implies that removing the selected attribute or
         // changing the value of a selected attribute that is already present

Modified: trunk/Source/WebCore/html/HTMLOptionElement.h (202244 => 202245)


--- trunk/Source/WebCore/html/HTMLOptionElement.h	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/html/HTMLOptionElement.h	2016-06-20 21:30:36 UTC (rev 202245)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (kn...@kde.org)
  *           (C) 1999 Antti Koivisto (koivi...@kde.org)
  *           (C) 2000 Dirk Mueller (muel...@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2010, 2011, 2016 Apple Inc. All rights reserved.
  * Copyright (C) 2010 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -71,6 +71,7 @@
 
     bool isFocusable() const override;
     bool rendererIsNeeded(const RenderStyle&) override { return false; }
+    bool matchesDefaultPseudoClass() const override;
 
     void parseAttribute(const QualifiedName&, const AtomicString&) override;
 

Modified: trunk/Source/WebCore/style/StyleSharingResolver.cpp (202244 => 202245)


--- trunk/Source/WebCore/style/StyleSharingResolver.cpp	2016-06-20 21:25:33 UTC (rev 202244)
+++ trunk/Source/WebCore/style/StyleSharingResolver.cpp	2016-06-20 21:30:36 UTC (rev 202245)
@@ -185,9 +185,6 @@
     if (formElement.isDisabledFormControl() != element.isDisabledFormControl())
         return false;
 
-    if (formElement.isDefaultButtonForForm() != element.isDefaultButtonForForm())
-        return false;
-
     if (formElement.isInRange() != element.isInRange())
         return false;
 
@@ -284,6 +281,9 @@
     if (candidateElement.matchesIndeterminatePseudoClass() != element.matchesIndeterminatePseudoClass())
         return false;
 
+    if (candidateElement.matchesDefaultPseudoClass() != element.matchesDefaultPseudoClass())
+        return false;
+
     if (element.shadowRoot() && !element.shadowRoot()->styleResolver().ruleSets().authorStyle()->hostPseudoClassRules().isEmpty())
         return false;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to