mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 23:05:42 +00:00
Bug 1737364 - Part 2: Elements should be barred from constraint validation if it has a datalist element ancestor; r=smaug
Add a new flag, ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR, to indicate that the element is a HTML datalist element or has a HTML datalist element ancestor. Per https://html.spec.whatwg.org/multipage/form-elements.html#the-datalist-element:barred-from-constraint-validation Differential Revision: https://phabricator.services.mozilla.com/D129717
This commit is contained in:
parent
6f8feb87ed
commit
ad06ef9d0a
@ -1675,6 +1675,9 @@ nsresult Element::BindToTree(BindContext& aContext, nsINode& aParent) {
|
||||
if (IsRootOfNativeAnonymousSubtree()) {
|
||||
aParent.SetMayHaveAnonymousChildren();
|
||||
}
|
||||
if (aParent.HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR)) {
|
||||
SetFlags(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR);
|
||||
}
|
||||
|
||||
// Now set the parent.
|
||||
mParent = &aParent;
|
||||
@ -1819,6 +1822,19 @@ bool WillDetachFromShadowOnUnbind(const Element& aElement, bool aNullParent) {
|
||||
void Element::UnbindFromTree(bool aNullParent) {
|
||||
HandleShadowDOMRelatedRemovalSteps(aNullParent);
|
||||
|
||||
if (HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR) &&
|
||||
!IsHTMLElement(nsGkAtoms::datalist)) {
|
||||
if (aNullParent) {
|
||||
UnsetFlags(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR);
|
||||
} else {
|
||||
nsIContent* parent = GetParent();
|
||||
MOZ_ASSERT(parent);
|
||||
if (!parent->HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR)) {
|
||||
UnsetFlags(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bool detachingFromShadow =
|
||||
WillDetachFromShadowOnUnbind(*this, aNullParent);
|
||||
// Make sure to only remove from the ID table if our subtree root is actually
|
||||
|
@ -168,8 +168,12 @@ enum {
|
||||
// style of an element is up-to-date, even during the same restyle process.
|
||||
ELEMENT_HANDLED_SNAPSHOT = ELEMENT_FLAG_BIT(3),
|
||||
|
||||
// If this flag is set on an element, that means that it is a HTML datalist
|
||||
// element or has a HTML datalist element ancestor.
|
||||
ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR = ELEMENT_FLAG_BIT(4),
|
||||
|
||||
// Remaining bits are for subclasses
|
||||
ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 4
|
||||
ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 5
|
||||
};
|
||||
|
||||
#undef ELEMENT_FLAG_BIT
|
||||
|
@ -82,9 +82,10 @@ void HTMLButtonElement::SetCustomValidity(const nsAString& aError) {
|
||||
}
|
||||
|
||||
void HTMLButtonElement::UpdateBarredFromConstraintValidation() {
|
||||
SetBarredFromConstraintValidation(mType == FormControlType::ButtonButton ||
|
||||
mType == FormControlType::ButtonReset ||
|
||||
IsDisabled());
|
||||
SetBarredFromConstraintValidation(
|
||||
mType == FormControlType::ButtonButton ||
|
||||
mType == FormControlType::ButtonReset ||
|
||||
HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR) || IsDisabled());
|
||||
}
|
||||
|
||||
void HTMLButtonElement::FieldSetDisabledChanged(bool aNotify) {
|
||||
@ -273,6 +274,8 @@ nsresult HTMLButtonElement::BindToTree(BindContext& aContext,
|
||||
nsGenericHTMLFormControlElementWithState::BindToTree(aContext, aParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
// Update our state; we may now be the default submit element
|
||||
UpdateState(false);
|
||||
|
||||
@ -282,6 +285,8 @@ nsresult HTMLButtonElement::BindToTree(BindContext& aContext,
|
||||
void HTMLButtonElement::UnbindFromTree(bool aNullParent) {
|
||||
nsGenericHTMLFormControlElementWithState::UnbindFromTree(aNullParent);
|
||||
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
// Update our state; we may no longer be the default submit element
|
||||
UpdateState(false);
|
||||
}
|
||||
|
@ -11,7 +11,9 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(DataList)
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
HTMLDataListElement::~HTMLDataListElement() = default;
|
||||
HTMLDataListElement::~HTMLDataListElement() {
|
||||
MOZ_ASSERT(HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR));
|
||||
}
|
||||
|
||||
JSObject* HTMLDataListElement::WrapNode(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) {
|
||||
|
@ -17,7 +17,9 @@ class HTMLDataListElement final : public nsGenericHTMLElement {
|
||||
public:
|
||||
explicit HTMLDataListElement(
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
|
||||
: nsGenericHTMLElement(std::move(aNodeInfo)) {}
|
||||
: nsGenericHTMLElement(std::move(aNodeInfo)) {
|
||||
SetFlags(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR);
|
||||
}
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -6583,7 +6583,8 @@ void HTMLInputElement::UpdateBarredFromConstraintValidation() {
|
||||
mType == FormControlType::InputHidden ||
|
||||
mType == FormControlType::InputButton ||
|
||||
mType == FormControlType::InputReset ||
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) || IsDisabled());
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) ||
|
||||
HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR) || IsDisabled());
|
||||
}
|
||||
|
||||
nsresult HTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
||||
|
@ -1539,7 +1539,8 @@ void HTMLSelectElement::VerifyOptionsArray() {
|
||||
#endif
|
||||
|
||||
void HTMLSelectElement::UpdateBarredFromConstraintValidation() {
|
||||
SetBarredFromConstraintValidation(IsDisabled());
|
||||
SetBarredFromConstraintValidation(
|
||||
HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR) || IsDisabled());
|
||||
}
|
||||
|
||||
void HTMLSelectElement::FieldSetDisabledChanged(bool aNotify) {
|
||||
|
@ -991,7 +991,8 @@ void HTMLTextAreaElement::UpdateValueMissingValidityState() {
|
||||
|
||||
void HTMLTextAreaElement::UpdateBarredFromConstraintValidation() {
|
||||
SetBarredFromConstraintValidation(
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) || IsDisabled());
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::readonly) ||
|
||||
HasFlag(ELEMENT_IS_DATALIST_OR_HAS_DATALIST_ANCESTOR) || IsDisabled());
|
||||
}
|
||||
|
||||
nsresult HTMLTextAreaElement::GetValidationMessage(
|
||||
|
@ -1,13 +1,4 @@
|
||||
[form-validation-willValidate.html]
|
||||
[[BUTTON in SUBMIT status\] The willValidate attribute must be false if it has a datalist ancestor]
|
||||
expected: FAIL
|
||||
|
||||
[[select\] The willValidate attribute must be false if it has a datalist ancestor]
|
||||
expected: FAIL
|
||||
|
||||
[[textarea\] The willValidate attribute must be false if it has a datalist ancestor]
|
||||
expected: FAIL
|
||||
|
||||
[[INPUT in COLOR status\] Must be not barred from the constraint validation even if it is readonly]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -1,7 +1,3 @@
|
||||
[datalistoptions.html]
|
||||
[options label/value]
|
||||
expected: FAIL
|
||||
|
||||
[If an element has a datalist element ancestor, it is barred from constraint validation]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>The constraint validation API Test: element.willValidate</title>
|
||||
<link rel="author" title="Intel" href="http://www.intel.com/">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-cva-willvalidate">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-constraint-validation-api">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<datalist></datalist>
|
||||
<script>
|
||||
var dl = document.querySelector("datalist");
|
||||
function runTest(element, name) {
|
||||
test(function () {
|
||||
assert_true(element.willValidate, "The willValidate attribute should be true initially.");
|
||||
|
||||
dl.appendChild(element);
|
||||
assert_false(element.willValidate, "The willValidate attribute should be false if element has datalist parent.");
|
||||
|
||||
element.remove();
|
||||
assert_true(element.willValidate, "The willValidate attribute should be true if element has no parent.");
|
||||
|
||||
let div = document.createElement("div");
|
||||
div.appendChild(element);
|
||||
let foo = document.createElementNS('some-random-namespace', 'foo');
|
||||
foo.appendChild(div);
|
||||
dl.appendChild(foo);
|
||||
assert_false(element.willValidate, "The willValidate attribute should be false if element has datalist ancestor.");
|
||||
|
||||
foo.remove();
|
||||
assert_true(element.willValidate, "The willValidate attribute should be true if element has no datalist ancestor.");
|
||||
}, name);
|
||||
}
|
||||
|
||||
var testElements = [
|
||||
{
|
||||
tag: "input",
|
||||
types: ["text", "search", "tel", "url", "email", "password", "datetime-local", "date", "month", "week", "time", "color", "file", "submit"]
|
||||
},
|
||||
{
|
||||
tag: "button",
|
||||
types: ["submit"],
|
||||
},
|
||||
{
|
||||
tag: "select",
|
||||
types: [],
|
||||
},
|
||||
{
|
||||
tag: "textarea",
|
||||
types: [],
|
||||
}
|
||||
].forEach(function(testData) {
|
||||
if (testData.types.length > 0) {
|
||||
testData.types.forEach(function(type) {
|
||||
let ele = document.createElement(testData.tag);
|
||||
try {
|
||||
ele.type = type;
|
||||
} catch (e) {
|
||||
//Do nothing, avoid the runtime error breaking the test
|
||||
}
|
||||
runTest(ele, `Test ${testData.tag} element with ${type} type`);
|
||||
});
|
||||
} else {
|
||||
runTest(document.createElement(testData.tag), `Test ${testData.tag} element`);
|
||||
}
|
||||
});
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user