Bug 1888774 - make InvokeAction an enum, "auto" now implicit r=dom-core,sefeng

Only "custom" invoke actions (those with a dash) or well-defined built-in
actions can be defined. Auto action is now implicit from empty/null atom.

Differential Revision: https://phabricator.services.mozilla.com/D206182
This commit is contained in:
keithamus 2024-05-15 21:38:06 +00:00
parent d06779086a
commit 12abaca03f
10 changed files with 88 additions and 35 deletions

View file

@ -253,6 +253,21 @@ class Grid;
ExplicitlySetAttrElement(nsGkAtoms::attr, aElement); \ ExplicitlySetAttrElement(nsGkAtoms::attr, aElement); \
} }
// TODO(keithamus): Reference the spec link once merged.
// https://github.com/whatwg/html/pull/9841/files#diff-41cf6794ba4200b839c53531555f0f3998df4cbb01a4d5cb0b94e3ca5e23947dR86024
enum class InvokeAction : uint8_t {
Invalid,
Custom,
Auto,
TogglePopover,
ShowPopover,
HidePopover,
ShowModal,
Toggle,
Close,
Open,
};
class Element : public FragmentOrElement { class Element : public FragmentOrElement {
public: public:
#ifdef MOZILLA_INTERNAL_API #ifdef MOZILLA_INTERNAL_API
@ -1113,7 +1128,7 @@ class Element : public FragmentOrElement {
return FindAttributeDependence(aAttribute, aMaps, N); return FindAttributeDependence(aAttribute, aMaps, N);
} }
MOZ_CAN_RUN_SCRIPT virtual void HandleInvokeInternal(nsAtom* aAction, MOZ_CAN_RUN_SCRIPT virtual void HandleInvokeInternal(InvokeAction aAction,
ErrorResult& aRv) {} ErrorResult& aRv) {}
private: private:

View file

@ -3658,6 +3658,23 @@ nsresult nsContentUtils::NewURIWithDocumentCharset(nsIURI** aResult,
return NS_NewURI(aResult, aSpec, nullptr, aBaseURI); return NS_NewURI(aResult, aSpec, nullptr, aBaseURI);
} }
// static
bool nsContentUtils::ContainsChar(nsAtom* aAtom, char aChar) {
const uint32_t len = aAtom->GetLength();
if (!len) {
return false;
}
const char16_t* name = aAtom->GetUTF16String();
uint32_t i = 0;
while (i < len) {
if (name[i] == aChar) {
return true;
}
i++;
}
return false;
}
// static // static
bool nsContentUtils::IsNameWithDash(nsAtom* aName) { bool nsContentUtils::IsNameWithDash(nsAtom* aName) {
// A valid custom element name is a sequence of characters name which // A valid custom element name is a sequence of characters name which

View file

@ -975,6 +975,11 @@ class nsContentUtils {
Document* aDocument, Document* aDocument,
nsIURI* aBaseURI); nsIURI* aBaseURI);
/**
* Returns true if |aAtom| contains at least one |aChar|.
*/
static bool ContainsChar(nsAtom* aAtom, char aChar);
/** /**
* Returns true if |aName| is a name with dashes. * Returns true if |aName| is a name with dashes.
*/ */

View file

@ -144,16 +144,15 @@ JSObject* HTMLDetailsElement::WrapNode(JSContext* aCx,
return HTMLDetailsElement_Binding::Wrap(aCx, this, aGivenProto); return HTMLDetailsElement_Binding::Wrap(aCx, this, aGivenProto);
} }
void HTMLDetailsElement::HandleInvokeInternal(nsAtom* aAction, void HTMLDetailsElement::HandleInvokeInternal(InvokeAction aAction,
ErrorResult& aRv) { ErrorResult& aRv) {
if (nsContentUtils::EqualsIgnoreASCIICase(aAction, nsGkAtoms::_auto) || if (aAction == InvokeAction::Auto || aAction == InvokeAction::Toggle) {
nsContentUtils::EqualsIgnoreASCIICase(aAction, nsGkAtoms::toggle)) {
ToggleOpen(); ToggleOpen();
} else if (nsContentUtils::EqualsIgnoreASCIICase(aAction, nsGkAtoms::close)) { } else if (aAction == InvokeAction::Close) {
if (Open()) { if (Open()) {
SetOpen(false, IgnoreErrors()); SetOpen(false, IgnoreErrors());
} }
} else if (nsContentUtils::EqualsIgnoreASCIICase(aAction, nsGkAtoms::open)) { } else if (aAction == InvokeAction::Open) {
if (!Open()) { if (!Open()) {
SetOpen(true, IgnoreErrors()); SetOpen(true, IgnoreErrors());
} }

View file

@ -50,7 +50,7 @@ class HTMLDetailsElement final : public nsGenericHTMLElement {
void AsyncEventRunning(AsyncEventDispatcher* aEvent) override; void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
void HandleInvokeInternal(nsAtom* aAction, ErrorResult& aRv) override; void HandleInvokeInternal(InvokeAction aAction, ErrorResult& aRv) override;
protected: protected:
virtual ~HTMLDetailsElement(); virtual ~HTMLDetailsElement();

View file

@ -2897,15 +2897,42 @@ void nsGenericHTMLFormControlElementWithState::HandlePopoverTargetAction() {
void nsGenericHTMLFormControlElementWithState::GetInvokeAction( void nsGenericHTMLFormControlElementWithState::GetInvokeAction(
nsAString& aValue) const { nsAString& aValue) const {
GetInvokeAction()->ToString(aValue); const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::invokeaction);
if (attr) {
attr->GetAtomValue()->ToString(aValue);
}
} }
nsAtom* nsGenericHTMLFormControlElementWithState::GetInvokeAction() const { InvokeAction nsGenericHTMLFormControlElementWithState::GetInvokeAction(
const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::invokeaction); nsAtom* aAtom) const {
if (attr && attr->GetAtomValue() != nsGkAtoms::_empty) { if (aAtom == nsGkAtoms::_empty) {
return attr->GetAtomValue(); return InvokeAction::Auto;
} }
return nsGkAtoms::_auto; if (nsContentUtils::EqualsIgnoreASCIICase(aAtom, nsGkAtoms::showpopover)) {
return InvokeAction::ShowPopover;
}
if (nsContentUtils::EqualsIgnoreASCIICase(aAtom, nsGkAtoms::hidepopover)) {
return InvokeAction::HidePopover;
}
if (nsContentUtils::EqualsIgnoreASCIICase(aAtom, nsGkAtoms::togglepopover)) {
return InvokeAction::TogglePopover;
}
if (nsContentUtils::EqualsIgnoreASCIICase(aAtom, nsGkAtoms::showmodal)) {
return InvokeAction::ShowModal;
}
if (nsContentUtils::EqualsIgnoreASCIICase(aAtom, nsGkAtoms::toggle)) {
return InvokeAction::Toggle;
}
if (nsContentUtils::EqualsIgnoreASCIICase(aAtom, nsGkAtoms::close)) {
return InvokeAction::Close;
}
if (nsContentUtils::EqualsIgnoreASCIICase(aAtom, nsGkAtoms::open)) {
return InvokeAction::Open;
}
if (nsContentUtils::ContainsChar(aAtom, '-')) {
return InvokeAction::Custom;
}
return InvokeAction::Invalid;
} }
mozilla::dom::Element* mozilla::dom::Element*
@ -2930,16 +2957,15 @@ void nsGenericHTMLFormControlElementWithState::HandleInvokeTargetAction() {
return; return;
} }
// 3. Let action be node's invokeaction attribute const nsAttrValue* attr = GetParsedAttr(nsGkAtoms::invokeaction);
// 4. If action is null or empty, then let action be the string "auto". nsAtom* actionRaw = attr ? attr->GetAtomValue() : nsGkAtoms::_empty;
RefPtr<nsAtom> aAction = GetInvokeAction(); InvokeAction action = GetInvokeAction(actionRaw);
MOZ_ASSERT(!aAction->IsEmpty(), "Action should not be empty");
// 5. Let notCancelled be the result of firing an event named invoke at // 5. Let notCancelled be the result of firing an event named invoke at
// invokee with its action set to action, its invoker set to node, // invokee with its action set to action, its invoker set to node,
// and its cancelable attribute initialized to true. // and its cancelable attribute initialized to true.
InvokeEventInit init; InvokeEventInit init;
aAction->ToString(init.mAction); actionRaw->ToString(init.mAction);
init.mInvoker = this; init.mInvoker = this;
init.mCancelable = true; init.mCancelable = true;
init.mComposed = true; init.mComposed = true;
@ -2955,7 +2981,7 @@ void nsGenericHTMLFormControlElementWithState::HandleInvokeTargetAction() {
return; return;
} }
invokee->HandleInvokeInternal(aAction, IgnoreErrors()); invokee->HandleInvokeInternal(action, IgnoreErrors());
} }
void nsGenericHTMLFormControlElementWithState::GenerateStateKey() { void nsGenericHTMLFormControlElementWithState::GenerateStateKey() {

View file

@ -55,6 +55,8 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
public: public:
using Element::Focus; using Element::Focus;
using Element::SetTabIndex; using Element::SetTabIndex;
using InvokeAction = mozilla::dom::InvokeAction;
explicit nsGenericHTMLElement( explicit nsGenericHTMLElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo) already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: nsGenericHTMLElementBase(std::move(aNodeInfo)) { : nsGenericHTMLElementBase(std::move(aNodeInfo)) {
@ -1260,7 +1262,7 @@ class nsGenericHTMLFormControlElementWithState
mozilla::dom::Element* GetInvokeTargetElement() const; mozilla::dom::Element* GetInvokeTargetElement() const;
void SetInvokeTargetElement(mozilla::dom::Element*); void SetInvokeTargetElement(mozilla::dom::Element*);
void GetInvokeAction(nsAString& aValue) const; void GetInvokeAction(nsAString& aValue) const;
nsAtom* GetInvokeAction() const; InvokeAction GetInvokeAction(nsAtom* aAtom) const;
void SetInvokeAction(const nsAString& aValue) { void SetInvokeAction(const nsAString& aValue) {
SetHTMLAttr(nsGkAtoms::invokeaction, aValue); SetHTMLAttr(nsGkAtoms::invokeaction, aValue);
} }

View file

@ -1,12 +0,0 @@
[invokeelement-interface.tentative.html]
[invokeAction reflects '' when attribute not present]
expected: FAIL
[invokeAction reflects '' when attribute empty, setAttribute version]
expected: FAIL
[invokeAction reflects '' when attribute empty, IDL version]
expected: FAIL
[invokeAction reflects '' when attribute set to [\]]
expected: FAIL

View file

@ -1,7 +1,4 @@
[invoketarget-button-event-dispatch.tentative.html] [invoketarget-button-event-dispatch.tentative.html]
[event dispatches on click]
expected: FAIL
[setting custom invokeAction property to foo (no dash) did not dispatch an event] [setting custom invokeAction property to foo (no dash) did not dispatch an event]
expected: FAIL expected: FAIL

View file

@ -520,6 +520,7 @@ STATIC_ATOMS = [
Atom("hidden", "hidden"), Atom("hidden", "hidden"),
Atom("hidechrome", "hidechrome"), Atom("hidechrome", "hidechrome"),
Atom("hidecolumnpicker", "hidecolumnpicker"), Atom("hidecolumnpicker", "hidecolumnpicker"),
Atom("hidepopover", "hidepopover"),
Atom("high", "high"), Atom("high", "high"),
Atom("highest", "highest"), Atom("highest", "highest"),
Atom("horizontal", "horizontal"), Atom("horizontal", "horizontal"),
@ -1155,6 +1156,8 @@ STATIC_ATOMS = [
Atom("shape", "shape"), Atom("shape", "shape"),
Atom("show", "show"), Atom("show", "show"),
Atom("showcaret", "showcaret"), Atom("showcaret", "showcaret"),
Atom("showmodal", "showmodal"),
Atom("showpopover", "showpopover"),
Atom("showservicesmenu", "showservicesmenu"), Atom("showservicesmenu", "showservicesmenu"),
Atom("sibling", "sibling"), Atom("sibling", "sibling"),
Atom("simple", "simple"), Atom("simple", "simple"),
@ -1248,6 +1251,7 @@ STATIC_ATOMS = [
Atom("title", "title"), Atom("title", "title"),
Atom("titletip", "titletip"), Atom("titletip", "titletip"),
Atom("toggle", "toggle"), Atom("toggle", "toggle"),
Atom("togglepopover", "togglepopover"),
Atom("token", "token"), Atom("token", "token"),
Atom("tokenize", "tokenize"), Atom("tokenize", "tokenize"),
Atom("toolbar", "toolbar"), Atom("toolbar", "toolbar"),