Skip to content

Commit d24bbb9

Browse files
AtkinsSJF3n67u
authored andcommitted
LibWeb/HTML: Update HTMLButtonElement.type to match spec changes
Corresponds to part of whatwg/html#9841 and then whatwg/html#11047 Adding `Auto` as a type state feels a little odd, as it's not an actual type allowed in HTML. However, it's the default state when the value is missing or invalid, which works out the same, as long as we never serialize "auto", which we don't.
1 parent 02adeeb commit d24bbb9

File tree

6 files changed

+149
-9
lines changed

6 files changed

+149
-9
lines changed

Libraries/LibWeb/HTML/AttributeNames.h

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ namespace AttributeNames {
5151
__ENUMERATE_HTML_ATTRIBUTE(color, "color") \
5252
__ENUMERATE_HTML_ATTRIBUTE(cols, "cols") \
5353
__ENUMERATE_HTML_ATTRIBUTE(colspan, "colspan") \
54+
__ENUMERATE_HTML_ATTRIBUTE(command, "command") \
55+
__ENUMERATE_HTML_ATTRIBUTE(commandfor, "commandfor") \
5456
__ENUMERATE_HTML_ATTRIBUTE(compact, "compact") \
5557
__ENUMERATE_HTML_ATTRIBUTE(content, "content") \
5658
__ENUMERATE_HTML_ATTRIBUTE(contenteditable, "contenteditable") \

Libraries/LibWeb/HTML/HTMLButtonElement.cpp

+51-6
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,44 @@ HTMLButtonElement::TypeAttributeState HTMLButtonElement::type_state() const
3737
ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTES
3838
#undef __ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE
3939

40-
// The missing value default and invalid value default are the Submit Button state.
41-
return HTMLButtonElement::TypeAttributeState::Submit;
40+
// The attribute's missing value default and invalid value default are both the Auto state.
41+
// https://html.spec.whatwg.org/multipage/form-elements.html#attr-button-type-auto-state
42+
return HTMLButtonElement::TypeAttributeState::Auto;
4243
}
4344

44-
WebIDL::ExceptionOr<void> HTMLButtonElement::set_type(String const& type)
45+
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-button-type
46+
String HTMLButtonElement::type_for_bindings() const
4547
{
48+
// The type getter steps are:
49+
// 1. If this is a submit button, then return "submit".
50+
if (is_submit_button())
51+
return "submit"_string;
52+
53+
// 2. Let state be this's type attribute.
54+
auto state = type_state();
55+
56+
// 3. Assert: state is not in the Submit Button state.
57+
VERIFY(state != TypeAttributeState::Submit);
58+
59+
// 4. If state is in the Auto state, then return "button".
60+
if (state == TypeAttributeState::Auto)
61+
return "button"_string;
62+
63+
// 5. Return the keyword value corresponding to state.
64+
switch (state) {
65+
#define __ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(keyword, state) \
66+
case TypeAttributeState::state: \
67+
return #keyword##_string;
68+
ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTES
69+
#undef __ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE
70+
}
71+
VERIFY_NOT_REACHED();
72+
}
73+
74+
// https://html.spec.whatwg.org/multipage/form-elements.html#dom-button-type
75+
WebIDL::ExceptionOr<void> HTMLButtonElement::set_type_for_bindings(String const& type)
76+
{
77+
// The type setter steps are to set the type content attribute to the given value.
4678
return set_attribute(HTML::AttributeNames::type, type);
4779
}
4880

@@ -68,8 +100,17 @@ i32 HTMLButtonElement::default_tab_index_value() const
68100
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:concept-submit-button
69101
bool HTMLButtonElement::is_submit_button() const
70102
{
71-
// A button element is said to be a submit button if the type attribute is in the Submit Button state.
72-
return type_state() == TypeAttributeState::Submit;
103+
// A button element is said to be a submit button if any of the following are true:
104+
switch (type_state()) {
105+
// - the type attribute is in the Auto state and both the command and commandfor content attributes are not present; or
106+
case TypeAttributeState::Auto:
107+
return !has_attribute(AttributeNames::command) && !has_attribute(AttributeNames::commandfor);
108+
// - the type attribute is in the Submit Button state.
109+
case TypeAttributeState::Submit:
110+
return true;
111+
default:
112+
return false;
113+
}
73114
}
74115

75116
// https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element:concept-fe-value
@@ -106,7 +147,11 @@ void HTMLButtonElement::activation_behavior(DOM::Event const& event)
106147
}
107148
}
108149

109-
// 4. Run the popover target attribute activation behavior given element and event's target.
150+
// FIXME: 4. Let target be the result of running element's get the commandfor associated element.
151+
// FIXME: 5. If target is not null:
152+
// ...
153+
154+
// 6. Otherwise, run the popover target attribute activation behavior given element and event's target.
110155
if (event.target() && event.target()->is_dom_node())
111156
PopoverInvokerElement::popover_target_activation_behaviour(*this, as<DOM::Node>(*event.target()));
112157
}

Libraries/LibWeb/HTML/HTMLButtonElement.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ namespace Web::HTML {
1616
#define ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTES \
1717
__ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(submit, Submit) \
1818
__ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(reset, Reset) \
19-
__ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(button, Button)
19+
__ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(button, Button) \
20+
__ENUMERATE_HTML_BUTTON_TYPE_ATTRIBUTE(auto, Auto)
2021

2122
class HTMLButtonElement final
2223
: public HTMLElement
@@ -38,7 +39,8 @@ class HTMLButtonElement final
3839
};
3940

4041
TypeAttributeState type_state() const;
41-
WebIDL::ExceptionOr<void> set_type(String const&);
42+
String type_for_bindings() const;
43+
WebIDL::ExceptionOr<void> set_type_for_bindings(String const&);
4244

4345
virtual void form_associated_element_attribute_changed(FlyString const& name, Optional<String> const& value, Optional<FlyString> const& namespace_) override;
4446

Libraries/LibWeb/HTML/HTMLButtonElement.idl

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface HTMLButtonElement : HTMLElement {
2323
[CEReactions, Reflect=formnovalidate] attribute boolean formNoValidate;
2424
[CEReactions, Reflect=formtarget] attribute DOMString formTarget;
2525
[CEReactions, Reflect] attribute DOMString name;
26-
[CEReactions, Reflect, Enumerated=ButtonTypeState] attribute DOMString type;
26+
[CEReactions, ImplementedAs=type_for_bindings, Enumerated=ButtonTypeState] attribute DOMString type;
2727
[CEReactions, Reflect] attribute DOMString value;
2828

2929
[FIXME] readonly attribute boolean willValidate;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Harness status: OK
2+
3+
Found 21 tests
4+
5+
18 Pass
6+
3 Fail
7+
Pass Button with id reset-in-form should reflect type correctly
8+
Pass Button with id submit-in-form should reflect type correctly
9+
Pass Button with id button-in-form should reflect type correctly
10+
Fail Button with id invalid-in-form should reflect type correctly
11+
Pass Button with id missing-in-form should reflect type correctly
12+
Pass Button with id missing-in-form-command-only should reflect type correctly
13+
Pass Button with id missing-in-form-commandfor-only should reflect type correctly
14+
Pass Button with id reset-attr-form should reflect type correctly
15+
Pass Button with id submit-attr-form should reflect type correctly
16+
Pass Button with id button-attr-form should reflect type correctly
17+
Fail Button with id invalid-attr-form should reflect type correctly
18+
Pass Button with id missing-attr-form should reflect type correctly
19+
Pass Button with id missing-attr-form-command-only should reflect type correctly
20+
Pass Button with id missing-attr-form-commandfor-only should reflect type correctly
21+
Pass Button with id reset-outside-form should reflect type correctly
22+
Pass Button with id submit-outside-form should reflect type correctly
23+
Pass Button with id button-outside-form should reflect type correctly
24+
Fail Button with id invalid-outside-form should reflect type correctly
25+
Pass Button with id missing-outside-form should reflect type correctly
26+
Pass Button with id missing-outside-form-command-only should reflect type correctly
27+
Pass Button with id missing-outside-form-commandfor-only should reflect type correctly
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<!DOCTYPE html>
2+
<link rel=author href="mailto:lwarlow@igalia.com">
3+
<script src="../../../../resources/testharness.js"></script>
4+
<script src="../../../../resources/testharnessreport.js"></script>
5+
6+
<iframe name=foo></iframe>
7+
<form id="form" target=foo action="about:blank">
8+
<button id=reset-in-form type=reset commandfor=mypopover command=toggle-popover>reset</button>
9+
<button id=submit-in-form type=submit commandfor=mypopover command=toggle-popover>submit</button>
10+
<button id=button-in-form type=button commandfor=mypopover command=toggle-popover>type=button</button>
11+
<button id=invalid-in-form type=invalid commandfor=mypopover command=toggle-popover>invalid</button>
12+
<button id=missing-in-form commandfor=mypopover command=toggle-popover>missing</button>
13+
<button id=missing-in-form-command-only command=toggle-popover>missing with command only</button>
14+
<button id=missing-in-form-commandfor-only commandfor=mypopover >missing with commandfor only</button>
15+
</form>
16+
17+
<button id=reset-attr-form type=reset commandfor=mypopover command=toggle-popover form=form>reset</button>
18+
<button id=submit-attr-form type=submit commandfor=mypopover command=toggle-popover form=form>submit</button>
19+
<button id=button-attr-form type=button commandfor=mypopover command=toggle-popover form=form>type=button</button>
20+
<button id=invalid-attr-form type=invalid commandfor=mypopover command=toggle-popover form=form>invalid</button>
21+
<button id=missing-attr-form commandfor=mypopover command=toggle-popover form=form>missing</button>
22+
<button id=missing-attr-form-command-only command=toggle-popover form=form>missing with command only</button>
23+
<button id=missing-attr-form-commandfor-only commandfor=mypopover form=form>missing with commandfor only</button>
24+
25+
<button id=reset-outside-form type=reset commandfor=mypopover command=toggle-popover>reset</button>
26+
<button id=submit-outside-form type=submit commandfor=mypopover command=toggle-popover>submit</button>
27+
<button id=button-outside-form type=button commandfor=mypopover command=toggle-popover>type=button</button>
28+
<button id=invalid-outside-form type=invalid commandfor=mypopover command=toggle-popover>invalid</button>
29+
<button id=missing-outside-form commandfor=mypopover command=toggle-popover>missing</button>
30+
<button id=missing-outside-form-command-only command=toggle-popover>missing with command only</button>
31+
<button id=missing-outside-form-commandfor-only commandfor=mypopover>missing with commandfor only</button>
32+
33+
<script>
34+
const data = {
35+
'reset-in-form': 'reset',
36+
'submit-in-form': 'submit',
37+
'button-in-form': 'button',
38+
'invalid-in-form': 'submit',
39+
'missing-in-form': 'button',
40+
'missing-in-form-command-only': 'button',
41+
'missing-in-form-commandfor-only': 'button',
42+
'reset-attr-form': 'reset',
43+
'submit-attr-form': 'submit',
44+
'button-attr-form': 'button',
45+
'invalid-attr-form': 'submit',
46+
'missing-attr-form': 'button',
47+
'missing-attr-form-command-only': 'button',
48+
'missing-attr-form-commandfor-only': 'button',
49+
'reset-outside-form': 'reset',
50+
'submit-outside-form': 'submit',
51+
'button-outside-form': 'button',
52+
'invalid-outside-form': 'submit',
53+
'missing-outside-form': 'button',
54+
'missing-outside-form-command-only': 'button',
55+
'missing-outside-form-commandfor-only': 'button',
56+
};
57+
58+
Object.entries(data).map(([id, expectedType]) => {
59+
test(() => {
60+
const button = document.getElementById(id);
61+
assert_equals(button.type, expectedType, `type of ${id} should be ${expectedType}`);
62+
}, `Button with id ${id} should reflect type correctly`);
63+
});
64+
</script>

0 commit comments

Comments
 (0)