☠☠ backed out by a40e6f483853 ☠ ☠ | |
author | Tom Puttemans <mozilla@tomputtemans.com> |
Mon, 03 Oct 2016 20:26:53 +0200 | |
changeset 316395 | 2a5aeed15578d6b3f951de5db7bf95245451fb44 |
parent 316394 | b05037b39080357f4e0d6d31fbddb9623d222a8e |
child 316396 | 6397682fabeae612c1434016bb51355335f1989e |
push id | 82435 |
push user | ryanvm@gmail.com |
push date | Tue, 04 Oct 2016 18:59:12 +0000 |
treeherder | mozilla-inbound@cf23f8fe42fb [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bz |
bugs | 1052045 |
milestone | 52.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/html/HTMLSelectElement.cpp +++ b/dom/html/HTMLSelectElement.cpp @@ -1768,29 +1768,34 @@ HTMLSelectElement::IsValueMissing() if (!Required()) { return false; } uint32_t length = Length(); for (uint32_t i = 0; i < length; ++i) { RefPtr<HTMLOptionElement> option = Item(i); + // Check for a placeholder label option, don't count it as a valid value + if (i == 0 && !Multiple() && Size() <= 1 && option->GetParent() == this) { + nsAutoString value; + MOZ_ALWAYS_SUCCEEDS(option->GetValue(value)); + if (value.IsEmpty()) { + continue; + } + } + if (!option->Selected()) { continue; } if (IsOptionDisabled(option)) { continue; } - nsAutoString value; - MOZ_ALWAYS_SUCCEEDS(option->GetValue(value)); - if (!value.IsEmpty()) { - return false; - } + return false; } return true; } void HTMLSelectElement::UpdateValueMissingValidityState() {
--- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -37425,16 +37425,22 @@ } ], "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html": [ { "path": "html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html", "url": "/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html" } ], + "html/semantics/forms/the-select-element/select-validity.html": [ + { + "path": "html/semantics/forms/the-select-element/select-validity.html", + "url": "/html/semantics/forms/the-select-element/select-validity.html" + } + ], "html/semantics/forms/the-textarea-element/cloning-steps.html": [ { "path": "html/semantics/forms/the-textarea-element/cloning-steps.html", "url": "/html/semantics/forms/the-textarea-element/cloning-steps.html" } ], "html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html": [ {
new file mode 100644 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-validity.html @@ -0,0 +1,99 @@ +<!doctype html> +<meta charset=utf-8> +<title>HTMLSelectElement.checkValidity</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#the-select-element:attr-select-required-4"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> + +test(function() { + var select = document.createElement('select'); + assert_true(select.willValidate, "A select element is a submittable element that is a candidate for constraint validation."); + var placeholder = document.createElement('option'); + select.appendChild(placeholder); + placeholder.value = ""; + assert_true(select.checkValidity(), "Always valid when the select isn't a required value."); + select.required = true; + assert_true(placeholder.selected, "If display size is 1, multiple is absent and no options have selectedness true, the first option is selected."); + assert_equals(select.value, "", "The placeholder's value should be the select's value right now"); + assert_false(select.checkValidity(), "A selected placeholder option should invalidate the select."); + var emptyOption = document.createElement('option'); + select.appendChild(emptyOption); + emptyOption.selected = true; + assert_equals(select.value, "", "The empty value should be set."); + assert_true(select.checkValidity(), "An empty non-placeholder option should be a valid choice."); + var filledOption = document.createElement('option'); + filledOption.value = "test"; + select.appendChild(filledOption); + filledOption.selected = true; + assert_equals(select.value, "test", "The non-empty value should be set."); + assert_true(select.checkValidity(), "A non-empty non-placeholder option should be a valid choice."); + select.removeChild(placeholder); + select.appendChild(emptyOption); // move emptyOption to second place + emptyOption.selected = true; + assert_equals(select.value, "", "The empty value should be set."); + assert_true(select.checkValidity(), "Only the first option can be seen as a placeholder."); + placeholder.disabled = true; + select.insertBefore(placeholder, filledOption); + placeholder.selected = true; + assert_equals(select.value, "", "A disabled first placeholder option should result in an empty value."); + assert_false(select.checkValidity(), "A disabled first placeholder option should invalidate the select."); +}, "Placeholder label options within a select"); + +test(function() { + var select = document.createElement('select'); + select.required = true; + var optgroup = document.createElement('optgroup'); + var emptyOption = document.createElement('option'); + emptyOption.value = ""; + optgroup.appendChild(emptyOption); + select.appendChild(optgroup); + emptyOption.selected = true; + assert_equals(select.value, "", "The empty value should be set."); + assert_true(select.checkValidity(), "The first option is not considered a placeholder if it is located within an optgroup."); + var otherEmptyOption = document.createElement('option'); + otherEmptyOption.value = ""; + select.appendChild(otherEmptyOption); + otherEmptyOption.selected = true; + assert_equals(select.value, "", "The empty value should be set."); + assert_true(select.checkValidity(), "The empty option should be accepted as it is not the first option in the tree ordered list."); +}, "Placeholder label-like options within optgroup"); + +test(function() { + var select = document.createElement('select'); + select.required = true; + select.size = 2; + var emptyOption = document.createElement('option'); + emptyOption.value = ""; + select.appendChild(emptyOption); + assert_false(emptyOption.selected, "Display size is not 1, so the first option should not be selected."); + assert_false(select.checkValidity(), "If no options are selected the select must be seen as invalid."); + emptyOption.selected = true; + assert_true(select.checkValidity(), "If one option is selected, the select should be considered valid."); + var otherEmptyOption = document.createElement('option'); + otherEmptyOption.value = ""; + select.appendChild(otherEmptyOption); + otherEmptyOption.selected = true; + assert_false(emptyOption.selected, "Whenever an option has its selectiveness set to true, the other options must be set to false."); + otherEmptyOption.selected = false; + assert_false(otherEmptyOption.selected, "It should be possible to set the selectiveness to false with a display size more than one."); + assert_false(select.checkValidity(), "If no options are selected the select must be seen as invalid."); +}, "Validation on selects with display size set as more than one"); + +test(function() { + var select = document.createElement('select'); + select.required = true; + select.multiple = true; + var emptyOption = document.createElement('option'); + emptyOption.value = ""; + select.appendChild(emptyOption); + assert_false(select.checkValidity(), "If no options are selected the select must be seen as invalid."); + emptyOption.selected = true; + assert_true(select.checkValidity(), "If one option is selected, the select should be considered valid."); + var optgroup = document.createElement('optgroup'); + optgroup.appendChild(emptyOption); // Move option to optgroup + select.appendChild(optgroup); + assert_true(select.checkValidity(), "If one option within an optgroup or not is selected, the select should be considered valid."); +}, "Validation on selects with multiple set"); +</script>