Bug 1469592 - Add support for Element.toggleAttribute. r=bzbarsky,smaug!
authorJonathan Kingston <jkt@mozilla.com>
Tue, 03 Jul 2018 19:12:49 +0000
changeset 424956 72cacb766a6f9f5401392384e7c681e35e318cd3
parent 424955 9c75cab2e32295ee037f0a8f1af2f61ac86f8b8c
child 424957 6e281abe4d39f6d1d3c40fdaca47c009db6720de
push id104946
push userrgurzau@mozilla.com
push dateWed, 04 Jul 2018 10:03:16 +0000
treeherdermozilla-inbound@796893f4d2f5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky, smaug
bugs1469592
milestone63.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
Bug 1469592 - Add support for Element.toggleAttribute. r=bzbarsky,smaug! MozReview-Commit-ID: KkDLMlQgESs Differential Revision: https://phabricator.services.mozilla.com/D1710
dom/base/Element.cpp
dom/base/Element.h
dom/webidl/Element.webidl
testing/web-platform/tests/interfaces/dom.idl
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1316,16 +1316,53 @@ Element::GetAttribute(const nsAString& a
       // See bug 232598
       // aReturn is already empty
     } else {
       aReturn.SetNull();
     }
   }
 }
 
+bool
+Element::ToggleAttribute(const nsAString& aName,
+                         const Optional<bool>& aForce,
+                         nsIPrincipal* aTriggeringPrincipal,
+                         ErrorResult& aError)
+{
+  aError = nsContentUtils::CheckQName(aName, false);
+  if (aError.Failed()) {
+    return false;
+  }
+
+  nsAutoString nameToUse;
+  const nsAttrName* name = InternalGetAttrNameFromQName(aName, &nameToUse);
+  if (!name) {
+    if (aForce.WasPassed() && !aForce.Value()) {
+      return false;
+    }
+    RefPtr<nsAtom> nameAtom = NS_AtomizeMainThread(nameToUse);
+    if (!nameAtom) {
+      aError.Throw(NS_ERROR_OUT_OF_MEMORY);
+      return false;
+    }
+    aError = SetAttr(kNameSpaceID_None, nameAtom, EmptyString(), aTriggeringPrincipal, true);
+    return true;
+  }
+  if (aForce.WasPassed() && aForce.Value()) {
+    return true;
+  }
+  // Hold a strong reference here so that the atom or nodeinfo doesn't go
+  // away during UnsetAttr. If it did UnsetAttr would be left with a
+  // dangling pointer as argument without knowing it.
+  nsAttrName tmp(*name);
+
+  aError = UnsetAttr(name->NamespaceID(), name->LocalName(), true);
+  return false;
+}
+
 void
 Element::SetAttribute(const nsAString& aName,
                       const nsAString& aValue,
                       nsIPrincipal* aTriggeringPrincipal,
                       ErrorResult& aError)
 {
   aError = nsContentUtils::CheckQName(aName, false);
   if (aError.Failed()) {
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -1096,16 +1096,18 @@ public:
     GetAttribute(aName, str);
     str.ToString(aReturn);
   }
 
   void GetAttribute(const nsAString& aName, DOMString& aReturn);
   void GetAttributeNS(const nsAString& aNamespaceURI,
                       const nsAString& aLocalName,
                       nsAString& aReturn);
+  bool ToggleAttribute(const nsAString& aName, const Optional<bool>& aForce,
+                       nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
   void SetAttribute(const nsAString& aName, const nsAString& aValue,
                     nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
   void SetAttributeNS(const nsAString& aNamespaceURI,
                       const nsAString& aLocalName,
                       const nsAString& aValue,
                       nsIPrincipal* aTriggeringPrincipal,
                       ErrorResult& aError);
   void SetAttribute(const nsAString& aName, const nsAString& aValue,
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -36,16 +36,18 @@ interface Element : Node {
   readonly attribute NamedNodeMap attributes;
   [Pure]
   sequence<DOMString> getAttributeNames();
   [Pure]
   DOMString? getAttribute(DOMString name);
   [Pure]
   DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
   [CEReactions, NeedsSubjectPrincipal=NonSystem, Throws]
+  boolean toggleAttribute(DOMString name, optional boolean force);
+  [CEReactions, NeedsSubjectPrincipal=NonSystem, Throws]
   void setAttribute(DOMString name, DOMString value);
   [CEReactions, NeedsSubjectPrincipal=NonSystem, Throws]
   void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
   [CEReactions, Throws]
   void removeAttribute(DOMString name);
   [CEReactions, Throws]
   void removeAttributeNS(DOMString? namespace, DOMString localName);
   [Pure]
--- a/testing/web-platform/tests/interfaces/dom.idl
+++ b/testing/web-platform/tests/interfaces/dom.idl
@@ -355,16 +355,17 @@ interface Element : Node {
   [SameObject] readonly attribute NamedNodeMap attributes;
   sequence<DOMString> getAttributeNames();
   DOMString? getAttribute(DOMString qualifiedName);
   DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
   void setAttribute(DOMString qualifiedName, DOMString value);
   void setAttributeNS(DOMString? namespace, DOMString qualifiedName, DOMString value);
   void removeAttribute(DOMString qualifiedName);
   void removeAttributeNS(DOMString? namespace, DOMString localName);
+  boolean toggleAttribute(DOMString qualifiedName, optional boolean force);
   boolean hasAttribute(DOMString qualifiedName);
   boolean hasAttributeNS(DOMString? namespace, DOMString localName);
 
   Attr? getAttributeNode(DOMString qualifiedName);
   Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName);
   Attr? setAttributeNode(Attr attr);
   Attr? setAttributeNodeNS(Attr attr);
   Attr removeAttributeNode(Attr attr);