forked from mirrors/gecko-dev
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:
parent
d06779086a
commit
12abaca03f
10 changed files with 88 additions and 35 deletions
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue