Bug 803129. Convert DOMStringMap to WebIDL. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 05 Nov 2012 11:58:03 -0500
changeset 120262 e7e0e49c7ee48d41a4e4422bf72adfda2368433f
parent 120261 b356ecf4086ca17ad4ed6bbc515eac91b43aaacb
child 120263 da96e260d2dd3565e871966b6c23ae9378eba58d
push idunknown
push userunknown
push dateunknown
reviewerspeterv
bugs803129
milestone19.0a1
Bug 803129. Convert DOMStringMap to WebIDL. r=peterv
content/base/src/nsGenericElement.h
content/html/content/src/nsDOMStringMap.cpp
content/html/content/src/nsDOMStringMap.h
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/interfaces/html/Makefile.in
dom/interfaces/html/nsIDOMDOMStringMap.idl
dom/interfaces/html/nsIDOMHTMLElement.idl
dom/webidl/DOMStringMap.webidl
dom/webidl/WebIDL.mk
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -24,17 +24,16 @@
 #include "mozFlushType.h"
 #include "nsDOMAttributeMap.h"
 #include "nsIWeakReference.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDocument.h"
 #include "nsIDOMNodeSelector.h"
 #include "nsIDOMXPathNSResolver.h"
 #include "nsPresContext.h"
-#include "nsIDOMDOMStringMap.h"
 #include "nsDOMClassInfoID.h" // DOMCI_DATA
 #include "nsIDOMTouchEvent.h"
 #include "nsIInlineEventHandlers.h"
 #include "mozilla/CORSMode.h"
 #include "mozilla/Attributes.h"
 #include "nsContentUtils.h"
 #include "nsINodeList.h"
 #include "nsISMILAttr.h"
--- a/content/html/content/src/nsDOMStringMap.cpp
+++ b/content/html/content/src/nsDOMStringMap.cpp
@@ -2,21 +2,22 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsError.h"
 #include "nsDOMStringMap.h"
 
-#include "nsDOMClassInfoID.h"
 #include "nsGenericHTMLElement.h"
 #include "nsContentUtils.h"
+#include "mozilla/dom/DOMStringMapBinding.h"
 
-DOMCI_DATA(DOMStringMap, nsDOMStringMap)
+using namespace mozilla;
+using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMStringMap)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMStringMap)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mElement)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMStringMap)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
@@ -29,202 +30,137 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMStringMap)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMStringMap)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsIDOMDOMStringMap)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMStringMap)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMStringMap)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMStringMap)
 
 nsDOMStringMap::nsDOMStringMap(nsGenericHTMLElement* aElement)
   : mElement(aElement),
     mRemovingProp(false)
 {
+  SetIsDOMBinding();
 }
 
 nsDOMStringMap::~nsDOMStringMap()
 {
   // Check if element still exists, may have been unlinked by cycle collector.
   if (mElement) {
     // Call back to element to null out weak reference to this object.
     mElement->ClearDataset();
   }
 }
 
-class nsDOMStringMapRemoveProp : public nsRunnable {
-public:
-  nsDOMStringMapRemoveProp(nsDOMStringMap* aDataset, nsIAtom* aProperty)
-  : mDataset(aDataset),
-    mProperty(aProperty)
-  {
-  }
-
-  NS_IMETHOD Run()
-  {
-    return mDataset->RemovePropInternal(mProperty);
-  }
-
-  virtual ~nsDOMStringMapRemoveProp()
-  {
-  }
-
-protected:
-  nsRefPtr<nsDOMStringMap> mDataset;
-  nsCOMPtr<nsIAtom> mProperty;
-};
-
-/* [notxpcom] boolean hasDataAttr (in DOMString prop); */
-NS_IMETHODIMP_(bool) nsDOMStringMap::HasDataAttr(const nsAString& aProp)
+/* virtual */
+JSObject*
+nsDOMStringMap::WrapObject(JSContext *cx, JSObject *scope,
+                           bool *triedToWrap)
 {
-  nsAutoString attr;
-  if (!DataPropToAttr(aProp, attr)) {
-    return false;
-  }
-
-  nsCOMPtr<nsIAtom> attrAtom = do_GetAtom(attr);
-  if (!attrAtom) {
-    return false;
-  }
-
-  return mElement->HasAttr(kNameSpaceID_None, attrAtom);
+  return DOMStringMapBinding::Wrap(cx, scope, this, triedToWrap);
 }
 
-/* [noscript] DOMString getDataAttr (in DOMString prop); */
-NS_IMETHODIMP nsDOMStringMap::GetDataAttr(const nsAString& aProp,
-                                          nsAString& aResult)
+void
+nsDOMStringMap::NamedGetter(const nsAString& aProp, bool& found,
+                            nsString& aResult) const
 {
   nsAutoString attr;
 
   if (!DataPropToAttr(aProp, attr)) {
-    aResult.SetIsVoid(true);
-    return NS_OK;
+    found = false;
+    return;
   }
 
   nsCOMPtr<nsIAtom> attrAtom = do_GetAtom(attr);
-  NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
+  MOZ_ASSERT(attrAtom, "Should be infallible");
 
-  if (!mElement->GetAttr(kNameSpaceID_None, attrAtom, aResult)) {
-    aResult.SetIsVoid(true);
-    return NS_OK;
-  }
-
-  return NS_OK;
+  found = mElement->GetAttr(kNameSpaceID_None, attrAtom, aResult);
 }
 
-/* [noscript] void setDataAttr (in DOMString prop, in DOMString value); */
-NS_IMETHODIMP nsDOMStringMap::SetDataAttr(const nsAString& aProp,
-                                          const nsAString& aValue)
+void
+nsDOMStringMap::NamedSetter(const nsAString& aProp,
+                            const nsAString& aValue,
+                            ErrorResult& rv)
 {
   nsAutoString attr;
-  NS_ENSURE_TRUE(DataPropToAttr(aProp, attr), NS_ERROR_DOM_SYNTAX_ERR);
+  if (!DataPropToAttr(aProp, attr)) {
+    rv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
+    return;
+  }
 
-  nsresult rv = nsContentUtils::CheckQName(attr, false);
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsresult res = nsContentUtils::CheckQName(attr, false);
+  if (NS_FAILED(res)) {
+    rv.Throw(res);
+    return;
+  }
 
   nsCOMPtr<nsIAtom> attrAtom = do_GetAtom(attr);
-  NS_ENSURE_TRUE(attrAtom, NS_ERROR_OUT_OF_MEMORY);
+  MOZ_ASSERT(attrAtom, "Should be infallible");
 
-  return mElement->SetAttr(kNameSpaceID_None, attrAtom, aValue, true);
+  res = mElement->SetAttr(kNameSpaceID_None, attrAtom, aValue, true);
+  if (NS_FAILED(res)) {
+    rv.Throw(res);
+  }
 }
 
-/* [notxpcom] void removeDataAttr (in DOMString prop); */
-NS_IMETHODIMP_(void) nsDOMStringMap::RemoveDataAttr(const nsAString& aProp)
+void
+nsDOMStringMap::NamedDeleter(const nsAString& aProp, bool& found)
 {
   // Currently removing property, attribute is already removed.
   if (mRemovingProp) {
     return;
   }
   
   nsAutoString attr;
   if (!DataPropToAttr(aProp, attr)) {
     return;
   }
 
   nsCOMPtr<nsIAtom> attrAtom = do_GetAtom(attr);
-  if (!attrAtom) {
-    return;
-  }
+  MOZ_ASSERT(attrAtom, "Should be infallible");
 
-  mElement->UnsetAttr(kNameSpaceID_None, attrAtom, true);
-}
+  found = mElement->HasAttr(kNameSpaceID_None, attrAtom);
 
-nsGenericHTMLElement* nsDOMStringMap::GetElement()
-{
-  return mElement;
-}
-
-/* [notxpcom] void removeProp (in nsIAtom attr); */
-NS_IMETHODIMP_(void) nsDOMStringMap::RemoveProp(nsIAtom* aAttr)
-{
-  nsContentUtils::AddScriptRunner(new nsDOMStringMapRemoveProp(this, aAttr));
+  if (found) {
+    mRemovingProp = true;
+    mElement->UnsetAttr(kNameSpaceID_None, attrAtom, true);
+    mRemovingProp = false;
+  }
 }
 
-nsresult nsDOMStringMap::RemovePropInternal(nsIAtom* aAttr)
-{
-  nsAutoString attr;
-  aAttr->ToString(attr);
-  nsAutoString prop;
-  NS_ENSURE_TRUE(AttrToDataProp(attr, prop), NS_OK);
-
-  jsval val;
-  JSContext* cx = nsContentUtils::GetCurrentJSContext();
-  nsresult rv = nsContentUtils::WrapNative(cx, JS_GetGlobalForScopeChain(cx),
-                                           this, &val);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  JSAutoCompartment ac(cx, JSVAL_TO_OBJECT(val));
-
-  // Guard against infinite recursion. Prevents the stack from looking like
-  // ...
-  // RemoveProp
-  // ...
-  // RemoveDataAttr
-  // ...
-  // RemoveProp
-  mRemovingProp = true;
-  jsval dummy;
-  JS_DeleteUCProperty2(cx, JSVAL_TO_OBJECT(val), prop.get(), prop.Length(),
-                       &dummy);
-  mRemovingProp = false;
-
-  return NS_OK;
-}
-
-/**
- * Returns a list of dataset properties corresponding to the data
- * attributes on the element.
- */
-nsresult nsDOMStringMap::GetDataPropList(nsTArray<nsString>& aResult)
+void
+nsDOMStringMap::GetSupportedNames(nsTArray<nsString>& aNames)
 {
   uint32_t attrCount = mElement->GetAttrCount();
 
   // Iterate through all the attributes and add property
   // names corresponding to data attributes to return array.
   for (uint32_t i = 0; i < attrCount; ++i) {
     nsAutoString attrString;
     const nsAttrName* attrName = mElement->GetAttrNameAt(i);
+    // Skip the ones that are not in the null namespace
+    if (attrName->NamespaceID() != kNameSpaceID_None) {
+      continue;
+    }
     attrName->LocalName()->ToString(attrString);
 
     nsAutoString prop;
     if (!AttrToDataProp(attrString, prop)) {
       continue;
     }
 
-    aResult.AppendElement(prop);
+    aNames.AppendElement(prop);
   }
-
-  return NS_OK;
 }
 
 /**
  * Converts a dataset property name to the corresponding data attribute name.
  * (ex. aBigFish to data-a-big-fish).
  */
 bool nsDOMStringMap::DataPropToAttr(const nsAString& aProp,
                                       nsAString& aResult)
--- a/content/html/content/src/nsDOMStringMap.h
+++ b/content/html/content/src/nsDOMStringMap.h
@@ -2,72 +2,54 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsDOMStringMap_h
 #define nsDOMStringMap_h
 
-#include "nsIDOMDOMStringMap.h"
-
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
 #include "nsTArray.h"
 #include "nsString.h"
 #include "nsWrapperCache.h"
 #include "nsGenericHTMLElement.h"
 
-class nsDOMStringMap : public nsIDOMDOMStringMap,
+namespace mozilla {
+class ErrorResult;
+}
+
+class nsDOMStringMap : public nsISupports,
                        public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_NSIDOMDOMSTRINGMAP
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMStringMap)
 
   nsINode* GetParentObject()
   {
     return mElement;
   }
 
-  static nsDOMStringMap* FromSupports(nsISupports* aSupports)
-  {
-    nsIDOMDOMStringMap* map =
-      static_cast<nsDOMStringMap*>(aSupports);
-#ifdef DEBUG
-    {
-      nsCOMPtr<nsIDOMDOMStringMap> map_qi =
-        do_QueryInterface(aSupports);
-
-      // If this assertion fires the QI implementation for the object in
-      // question doesn't use the nsIDOMDOMStringMap pointer as the
-      // nsISupports pointer. That must be fixed, or we'll crash...
-      NS_ASSERTION(map_qi == map, "Uh, fix QI!");
-    }
-#endif
-
-    return static_cast<nsDOMStringMap*>(map);
-  }
-
-  
   nsDOMStringMap(nsGenericHTMLElement* aElement);
 
-  // GetDataPropList is not defined in IDL due to difficulty
-  // of returning arrays in IDL. Instead, we cast to this
-  // class if this method needs to be called.
-  nsresult GetDataPropList(nsTArray<nsString>& aResult);
-
-  nsresult RemovePropInternal(nsIAtom* aAttr);
-  nsGenericHTMLElement* GetElement();
+  // WebIDL API
+  virtual JSObject* WrapObject(JSContext *cx, JSObject *scope,
+                               bool *triedToWrap);
+  void NamedGetter(const nsAString& aProp, bool& found, nsString& aResult) const;
+  void NamedSetter(const nsAString& aProp, const nsAString& aValue,
+                   mozilla::ErrorResult& rv);
+  void NamedDeleter(const nsAString& aProp, bool &found);
+  void GetSupportedNames(nsTArray<nsString>& aNames);
 
 private:
   virtual ~nsDOMStringMap();
 
 protected:
   nsRefPtr<nsGenericHTMLElement> mElement;
   // Flag to guard against infinite recursion.
   bool mRemovingProp;
-  bool DataPropToAttr(const nsAString& aProp, nsAString& aResult);
-  bool AttrToDataProp(const nsAString& aAttr, nsAString& aResult);
+  static bool DataPropToAttr(const nsAString& aProp, nsAString& aResult);
+  static bool AttrToDataProp(const nsAString& aAttr, nsAString& aResult);
 };
 
 #endif
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -356,17 +356,17 @@ nsGenericHTMLElement::Dataset()
     slots->mDataset = new nsDOMStringMap(this);
   }
 
   NS_ADDREF(slots->mDataset);
   return slots->mDataset;
 }
 
 nsresult
-nsGenericHTMLElement::GetDataset(nsIDOMDOMStringMap** aDataset)
+nsGenericHTMLElement::GetDataset(nsISupports** aDataset)
 {
   *aDataset = Dataset().get();
   return NS_OK;
 }
 
 nsresult
 nsGenericHTMLElement::ClearDataset()
 {
@@ -2045,22 +2045,16 @@ nsGenericHTMLElement::UnsetAttr(int32_t 
     }
     else if (nsContentUtils::IsEventAttributeName(aAttribute,
                                                   EventNameType_HTML)) {
       nsEventListenerManager* manager = GetListenerManager(false);
       if (manager) {
         manager->RemoveEventHandler(aAttribute);
       }
     }
-
-    // Remove dataset property if necessary.
-    nsDOMSlots *slots = GetExistingDOMSlots();
-    if (slots && slots->mDataset) {
-      slots->mDataset->RemoveProp(aAttribute);
-    }
   }
 
   nsresult rv = nsGenericHTMLElementBase::UnsetAttr(aNameSpaceID, aAttribute,
                                                     aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (contentEditable) {
     ChangeEditableState(contentEditableChange);
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -26,17 +26,16 @@ class nsIURI;
 class nsIFormControlFrame;
 class nsIForm;
 class nsPresState;
 class nsILayoutHistoryState;
 class nsIEditor;
 struct nsRect;
 struct nsSize;
 class nsHTMLFormElement;
-class nsIDOMDOMStringMap;
 class nsIDOMHTMLMenuElement;
 class nsIDOMHTMLCollection;
 class nsDOMSettableTokenList;
 class nsIDOMHTMLPropertiesCollection;
 
 typedef nsMappedAttributeElement nsGenericHTMLElementBase;
 
 /**
@@ -213,17 +212,17 @@ public:
   NS_IMETHOD SetItemProp(nsIVariant* aValue);
   NS_IMETHOD GetProperties(nsIDOMHTMLPropertiesCollection** aReturn);
   NS_IMETHOD GetAccessKey(nsAString &aAccessKey);
   NS_IMETHOD SetAccessKey(const nsAString& aAccessKey);
   NS_IMETHOD GetAccessKeyLabel(nsAString& aLabel);
   nsresult GetContentEditable(nsAString& aContentEditable);
   nsresult GetIsContentEditable(bool* aContentEditable);
   nsresult SetContentEditable(const nsAString &aContentEditable);
-  nsresult GetDataset(nsIDOMDOMStringMap** aDataset);
+  nsresult GetDataset(nsISupports** aDataset);
   already_AddRefed<nsDOMStringMap> Dataset();
   // Callback for destructor of of dataset to ensure to null out weak pointer.
   nsresult ClearDataset();
   nsresult GetContextMenu(nsIDOMHTMLMenuElement** aContextMenu);
 
   /**
    * Get width and height, using given image request if attributes are unset.
    */
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -106,18 +106,16 @@
 #include "nsError.h"
 #include "nsIDOMDOMException.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNamedNodeMap.h"
 #include "nsIDOMDOMStringList.h"
 #include "nsIDOMDOMTokenList.h"
 #include "nsIDOMDOMSettableTokenList.h"
 
-#include "nsDOMStringMap.h"
-
 // HTMLFormElement helper includes
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsHTMLDocument.h"
 
 // Constraint Validation API helper includes
 #include "nsIDOMValidityState.h"
@@ -433,18 +431,16 @@
 #include "mozilla/dom/workers/Workers.h"
 
 #include "nsDOMFile.h"
 #include "nsDOMFileReader.h"
 #include "nsIDOMFormData.h"
 #include "ArchiveReader.h"
 #include "ArchiveRequest.h"
 
-#include "nsIDOMDOMStringMap.h"
-
 #include "nsIDOMDesktopNotification.h"
 #include "nsIDOMNavigatorDesktopNotification.h"
 #include "nsIDOMNavigatorDeviceStorage.h"
 #include "nsIDOMNavigatorGeolocation.h"
 #include "Navigator.h"
 
 #include "nsPluginArray.h"
 #include "nsMimeTypeArray.h"
@@ -611,24 +607,16 @@ static const char kDOMStringBundleURL[] 
    nsIXPCScriptable::WANT_POSTCREATE |                                        \
    nsIXPCScriptable::WANT_ENUMERATE)
 
 #define ARRAY_SCRIPTABLE_FLAGS                                                \
   (DOM_DEFAULT_SCRIPTABLE_FLAGS       |                                       \
    nsIXPCScriptable::WANT_GETPROPERTY |                                       \
    nsIXPCScriptable::WANT_ENUMERATE)
 
-#define DOMSTRINGMAP_SCRIPTABLE_FLAGS                                         \
-  (DOM_DEFAULT_SCRIPTABLE_FLAGS       |                                       \
-   nsIXPCScriptable::WANT_ENUMERATE   |                                       \
-   nsIXPCScriptable::WANT_PRECREATE   |                                       \
-   nsIXPCScriptable::WANT_DELPROPERTY |                                       \
-   nsIXPCScriptable::WANT_SETPROPERTY |                                       \
-   nsIXPCScriptable::WANT_GETPROPERTY)
-
 #define EVENTTARGET_SCRIPTABLE_FLAGS                                          \
   (DOM_DEFAULT_SCRIPTABLE_FLAGS       |                                       \
    nsIXPCScriptable::WANT_ADDPROPERTY)
 
 #define IDBEVENTTARGET_SCRIPTABLE_FLAGS                                       \
   (EVENTTARGET_SCRIPTABLE_FLAGS)
 
 #define DOMCLASSINFO_STANDARD_FLAGS                                           \
@@ -1444,19 +1432,16 @@ static nsDOMClassInfoData sClassInfoData
                            EVENTTARGET_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(ArchiveReader, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(ArchiveRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozURLProperty, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(DOMStringMap, nsDOMStringMapSH,
-                           DOMSTRINGMAP_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH,
                            DEFAULT_SCRIPTABLE_FLAGS |
                            WINDOW_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(DataContainerEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MessageEvent, nsDOMGenericSH,
@@ -4006,20 +3991,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMArchiveRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMRequest)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozURLProperty, nsIDOMMozURLProperty)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozURLProperty)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(DOMStringMap, nsIDOMDOMStringMap)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMStringMap)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
     DOM_CLASSINFO_WINDOW_MAP_ENTRIES(nsGlobalWindow::HasIndexedDBSupport())
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DataContainerEvent, nsIDOMDataContainerEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataContainerEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
@@ -8511,152 +8492,16 @@ nsNamedNodeMapSH::GetNamedItem(nsISuppor
 {
   nsDOMAttributeMap* map = nsDOMAttributeMap::FromSupports(aNative);
 
   nsINode *attr;
   *aCache = attr = map->GetNamedItem(aName, aResult);
   return attr;
 }
 
-
-NS_IMETHODIMP
-nsDOMStringMapSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                             JSObject *obj, jsid id, uint32_t flags,
-                             JSObject **objp, bool *_retval)
-{
-  nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
-  NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
-
-  nsAutoString prop;
-  NS_ENSURE_TRUE(JSIDToProp(id, prop), NS_ERROR_UNEXPECTED);
-
-  if (dataset->HasDataAttr(prop)) {
-    *_retval = JS_DefinePropertyById(cx, obj, id, JSVAL_VOID,
-                                     nullptr, nullptr,
-                                     JSPROP_ENUMERATE | JSPROP_SHARED); 
-    *objp = obj;
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMStringMapSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                            JSObject *obj, bool *_retval)
-{
-  nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
-  NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
-
-  nsDOMStringMap* stringMap = static_cast<nsDOMStringMap*>(dataset.get());
-  nsTArray<nsString> properties;
-  nsresult rv = stringMap->GetDataPropList(properties);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  for (uint32_t i = 0; i < properties.Length(); ++i) {
-    nsString& prop(properties[i]);
-    *_retval = JS_DefineUCProperty(cx, obj, prop.get(), prop.Length(),
-                                   JSVAL_VOID, nullptr, nullptr,
-                                   JSPROP_ENUMERATE | JSPROP_SHARED);
-    NS_ENSURE_TRUE(*_retval, NS_ERROR_FAILURE);
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMStringMapSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
-                            JSObject *globalObj, JSObject **parentObj)
-{
-  nsDOMStringMap* map = nsDOMStringMap::FromSupports(nativeObj);
-  nsINode* native_parent = map->GetParentObject();
-  if (!native_parent) {
-    return nsDOMClassInfo::PreCreate(nativeObj, cx, globalObj, parentObj);
-  }
-
-  return WrapNativeParent(cx, globalObj, native_parent, parentObj);
-}
-
-NS_IMETHODIMP
-nsDOMStringMapSH::DelProperty(nsIXPConnectWrappedNative *wrapper,
-                              JSContext *cx, JSObject *obj, jsid id,
-                              jsval *vp, bool *_retval)
-{
-  nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
-  NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
-
-  nsAutoString prop;
-  NS_ENSURE_TRUE(JSIDToProp(id, prop), NS_ERROR_UNEXPECTED);
-
-  dataset->RemoveDataAttr(prop);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMStringMapSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                              JSObject *obj, jsid id, jsval *vp,
-                              bool *_retval)
-{
-  nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
-  NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
-
-  nsAutoString propName;
-  NS_ENSURE_TRUE(JSIDToProp(id, propName), NS_ERROR_UNEXPECTED);
-
-  nsAutoString propVal;
-  nsresult rv = dataset->GetDataAttr(propName, propVal);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (propVal.IsVoid()) {
-    *vp = JSVAL_VOID;
-    return NS_SUCCESS_I_DID_SOMETHING;
-  }
-
-  NS_ENSURE_TRUE(xpc::NonVoidStringToJsval(cx, propVal, vp),
-                 NS_ERROR_OUT_OF_MEMORY);
-  return NS_SUCCESS_I_DID_SOMETHING;
-}
-
-NS_IMETHODIMP
-nsDOMStringMapSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                              JSObject *obj, jsid id, jsval *vp,
-                              bool *_retval)
-{
-  nsCOMPtr<nsIDOMDOMStringMap> dataset(do_QueryWrappedNative(wrapper, obj));
-  NS_ENSURE_TRUE(dataset, NS_ERROR_UNEXPECTED);
-
-  nsAutoString propName;
-  NS_ENSURE_TRUE(JSIDToProp(id, propName), NS_ERROR_UNEXPECTED);
-
-  JSString *val = JS_ValueToString(cx, *vp);
-  NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
-
-  nsDependentJSString propVal;
-  NS_ENSURE_TRUE(propVal.init(cx, val), NS_ERROR_UNEXPECTED);
-
-  nsresult rv = dataset->SetDataAttr(propName, propVal);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_SUCCESS_I_DID_SOMETHING;
-}
-
-bool
-nsDOMStringMapSH::JSIDToProp(const jsid& aId, nsAString& aResult)
-{
-  if (JSID_IS_INT(aId)) {
-    aResult.AppendInt(JSID_TO_INT(aId));
-  } else if (JSID_IS_STRING(aId)) {
-    aResult = nsDependentJSString(aId);
-  } else {
-    return false;
-  }
-
-  return true;
-}
-
 // Can't be static so GetterShim will compile
 nsresult
 DocumentURIObjectGetter(JSContext *cx, JSObject *obj, jsval *vp)
 {
   // This function duplicates some of the logic in XPC_WN_HelperGetProperty
   XPCWrappedNative *wrapper =
     XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
 
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -683,55 +683,16 @@ protected:
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsNamedNodeMapSH(aData);
   }
 };
 
-
-// DOMStringMap helper for .dataset property on elements.
-
-class nsDOMStringMapSH : public nsDOMGenericSH
-{
-public:
-  nsDOMStringMapSH(nsDOMClassInfoData* aData) : nsDOMGenericSH(aData)
-  {
-  }
-
-  virtual ~nsDOMStringMapSH()
-  {
-  }
-
-public:
-  NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                        JSObject *obj, jsid id, uint32_t flags,
-                        JSObject **objp, bool *_retval);
-  NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                       JSObject *obj, bool *_retval);
-  NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
-                       JSObject *globalObj, JSObject **parentObj);
-  NS_IMETHOD DelProperty(nsIXPConnectWrappedNative *wrapper,
-                         JSContext *cx, JSObject *obj, jsid id,
-                         jsval *vp, bool *_retval);
-  NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
-  NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                         JSObject *obj, jsid id, jsval *vp, bool *_retval);
-
-  bool JSIDToProp(const jsid& aId, nsAString& aResult);
-
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsDOMStringMapSH(aData);
-  }
-};
-
-
 // Document helper, for document.location and document.on*
 
 class nsDocumentSH : public nsNodeSH
 {
 public:
   nsDocumentSH(nsDOMClassInfoData* aData) : nsNodeSH(aData)
   {
   }
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -363,18 +363,16 @@ DOMCI_CLASS(OfflineResourceList)
 DOMCI_CLASS(FileList)
 DOMCI_CLASS(Blob)
 DOMCI_CLASS(File)
 DOMCI_CLASS(FileReader)
 DOMCI_CLASS(ArchiveReader)
 DOMCI_CLASS(ArchiveRequest)
 DOMCI_CLASS(MozURLProperty)
 
-DOMCI_CLASS(DOMStringMap)
-
 // DOM modal content window class, almost identical to Window
 DOMCI_CLASS(ModalContentWindow)
 
 // Data Events
 DOMCI_CLASS(DataContainerEvent)
 
 // event used for cross-domain message-passing and for server-sent events in
 // HTML5
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -107,35 +107,33 @@ DOMInterfaces = {
 'Blob': [
 {
     'headerFile': 'nsIDOMFile.h',
 },
 {
     'workers': True,
 }],
 
-'CanvasRenderingContext2D': [
-{
+'CanvasRenderingContext2D': {
     'implicitJSContext': [
         'createImageData', 'getImageData', 'putImageData', 'strokeStyle',
         'fillStyle', 'mozDash'
     ],
     'resultNotAddRefed': [ 'canvas' ],
     'binaryNames': {
         'mozImageSmoothingEnabled': 'imageSmoothingEnabled',
         'mozFillRule': 'fillRule'
     }
-}],
+},
 
-'ClientRectList': [
-{
+'ClientRectList': {
     'nativeType': 'nsClientRectList',
     'headerFile': 'nsClientRect.h',
     'resultNotAddRefed': [ 'item' ]
-}],
+},
 
 'CSS2Properties': {
   'nativeType': 'nsDOMCSSDeclaration'
 },
 
 'CSSStyleDeclaration': {
   'nativeType': 'nsICSSDeclaration'
 },
@@ -148,31 +146,33 @@ DOMInterfaces = {
 'Document': [
 {
     'nativeType': 'nsIDocument',
 },
 {
     'workers': True,
 }],
 
-'DOMSettableTokenList': [
-{
+'DOMSettableTokenList': {
     'nativeType': 'nsDOMSettableTokenList',
     'binaryNames': {
         '__stringifier': 'Stringify'
     }
-}],
+},
 
-'DOMTokenList': [
-{
+'DOMStringMap': {
+    'nativeType': 'nsDOMStringMap'
+},
+
+'DOMTokenList': {
     'nativeType': 'nsDOMTokenList',
     'binaryNames': {
         '__stringifier': 'Stringify'
     }
-}],
+},
 
 'Event': [
 {
     'workers': True,
 }],
 
 'EventListener': [
 {
@@ -186,58 +186,54 @@ DOMInterfaces = {
     'concrete': False,
     'prefable': True,
 },
 {
     'workers': True,
     'concrete': False
 }],
 
-'FileList': [
-{
+'FileList': {
     'nativeType': 'nsDOMFileList',
     'headerFile': 'nsDOMFile.h',
     'resultNotAddRefed': [ 'item' ]
-}],
+},
 
 'FileReaderSync': {
     'workers': True,
 },
 
 'FormData': [
 {
     'workers': True,
 }],
 
 'GainNode': [
 {
     'resultNotAddRefed': [ 'gain' ],
 }],
 
-'HTMLCollection': [
-{
+'HTMLCollection': {
     'nativeType': 'nsIHTMLCollection',
     'resultNotAddRefed': [ 'item' ]
-}],
+},
 
-'HTMLOptionsCollection': [
-{
+'HTMLOptionsCollection': {
     'nativeType': 'nsHTMLOptionCollection',
     'headerFile': 'nsHTMLSelectElement.h',
     'resultNotAddRefed': [ 'item' ],
     'binaryNames': {
         '__indexedsettercreator': 'SetOption'
     }
-}],
+},
 
-'HTMLPropertiesCollection': [
-{
+'HTMLPropertiesCollection': {
     'headerFile': 'HTMLPropertiesCollection.h',
     'resultNotAddRefed': [ 'item', 'namedItem', 'names' ]
-}],
+},
 
 'IID': [
 {
     'nativeType': 'nsIJSID',
     'headerFile': 'xpcjsid.h',
 },
 {
     'workers': True,
@@ -268,89 +264,81 @@ DOMInterfaces = {
 {
     'nativeType': 'nsIChannel',
     'notflattened': True
 },
 {
     'workers': True,
 }],
 
-'NodeList': [
-{
+'NodeList': {
     'nativeType': 'nsINodeList',
     'resultNotAddRefed': [ 'item' ]
-}],
+},
 
-'PaintRequestList': [
-{
+'PaintRequestList': {
     'nativeType': 'nsPaintRequestList',
     'headerFile': 'nsPaintRequest.h',
     'resultNotAddRefed': [ 'item' ]
-}],
+},
 
 'Performance': {
     'nativeType': 'nsPerformance',
     'resultNotAddRefed': [ 'timing', 'navigation' ]
 },
 
 'PerformanceTiming': {
     'nativeType': 'nsPerformanceTiming',
     'headerFile': 'nsPerformance.h'
 },
 
 'PerformanceNavigation': {
     'nativeType': 'nsPerformanceNavigation',
     'headerFile': 'nsPerformance.h'
 },
 
-'PropertyNodeList': [
-{
+'PropertyNodeList': {
     'headerFile': 'HTMLPropertiesCollection.h',
     'resultNotAddRefed': [ 'item' ]
-}],
+},
 
 'Screen': {
     'nativeType': 'nsScreen',
     'prefable': True,
 },
 
-'SVGLengthList': [
-{
+'SVGLengthList': {
     'nativeType': 'mozilla::DOMSVGLengthList',
     'headerFile': 'DOMSVGLengthList.h',
     'resultNotAddRefed': [ 'getItem' ]
-}],
+},
 
-'SVGNumberList': [
-{
+'SVGNumberList': {
     'nativeType': 'mozilla::DOMSVGNumberList',
     'headerFile': 'DOMSVGNumberList.h',
     'resultNotAddRefed': [ 'getItem' ]
-}],
+},
 
-'SVGPathSegList': [
-{
+'SVGPathSegList': {
     'nativeType': 'mozilla::DOMSVGPathSegList',
     'headerFile': 'DOMSVGPathSegList.h',
     'resultNotAddRefed': [ 'getItem' ]
-}],
+},
 
-'SVGPointList': [
-{
+'SVGPointList': {
     'nativeType': 'mozilla::DOMSVGPointList',
     'headerFile': 'DOMSVGPointList.h',
     'resultNotAddRefed': [ 'getItem' ]
-}],
+},
 
-'SVGTransformList': [
-{
+'SVGTransformList': {
     'nativeType': 'mozilla::DOMSVGTransformList',
     'headerFile': 'DOMSVGTransformList.h',
     'resultNotAddRefed': [ 'getItem' ]
-}],
+},
 
 'TextEncoder': {
     'headerFile': 'mozilla/dom/TextEncoder.h',
     'implicitJSContext': [ 'encode' ],
 },
 
 'TextDecoder': {
     'headerFile': 'mozilla/dom/TextDecoder.h',
@@ -452,21 +440,20 @@ DOMInterfaces = {
 },
 
 'WebGLUniformLocation': {
    'nativeType': 'mozilla::WebGLUniformLocation',
    'headerFile': 'WebGLContext.h',
    'wrapperCache': False
 },
 
-'WebSocket': [
-{
+'WebSocket': {
     'headerFile': 'WebSocket.h',
     'implicitJSContext': [ 'constructor' ]
-}],
+},
 
 'XMLHttpRequest': [
 {
     'nativeType': 'nsXMLHttpRequest',
     'implicitJSContext': [ 'constructor', ],
     'resultNotAddRefed': [ 'upload', 'responseXML' ]
 },
 {
--- a/dom/interfaces/html/Makefile.in
+++ b/dom/interfaces/html/Makefile.in
@@ -81,17 +81,16 @@ SDK_XPIDLSRCS =					\
 	nsIDOMMediaError.idl		\
 	nsIDOMTimeRanges.idl		\
 	nsIDOMHTMLByteRanges.idl		\
 	nsIDOMHTMLMediaElement.idl		\
 	nsIDOMHTMLSourceElement.idl		\
 	nsIDOMHTMLVideoElement.idl		\
 	nsIDOMHTMLAudioElement.idl		\
 	nsIDOMValidityState.idl		\
-	nsIDOMDOMStringMap.idl		\
 	nsIDOMMozBrowserFrame.idl		\
 	$(NULL)
 
 XPIDLSRCS = 					\
 	nsIDOMHTMLCanvasElement.idl		\
 	nsIDOMHTMLUnknownElement.idl \
 	nsIMozBrowserFrame.idl \
 	$(NULL)
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMDOMStringMap.idl
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "domstubs.idl"
-
-interface nsIAtom;
-
-[scriptable, uuid(47c9ab4f-1ca3-4551-95d1-c02a93a0e74f)]
-interface nsIDOMDOMStringMap : nsISupports
-{
-  [notxpcom] boolean hasDataAttr(in DOMString prop);
-  [noscript] DOMString getDataAttr(in DOMString prop);
-  [noscript] void setDataAttr(in DOMString prop, in DOMString value);
-  [notxpcom] void removeDataAttr(in DOMString prop);
-  
-  /**
-   * Removes the property from the dataset object. Used to update the
-   * dataset object when data-* attribute has been removed from the
-   * element.
-   */
-  [notxpcom] void removeProp(in nsIAtom attr);
-};
--- a/dom/interfaces/html/nsIDOMHTMLElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLElement.idl
@@ -1,17 +1,16 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMElement.idl"
 #include "nsIVariant.idl"
 
-interface nsIDOMDOMStringMap;
 interface nsIDOMHTMLMenuElement;
 interface nsIDOMHTMLPropertiesCollection;
 
 /**
  * The nsIDOMHTMLElement interface is the primary [X]HTML element
  * interface. It represents a single [X]HTML element in the document
  * tree.
  *
@@ -25,17 +24,17 @@ interface nsIDOMHTMLPropertiesCollection
 interface nsIDOMHTMLElement : nsIDOMElement
 {
   // metadata attributes
            attribute DOMString        id;
            attribute DOMString        title;
            attribute DOMString        lang;
            attribute DOMString        dir;
            attribute DOMString        className;
-  readonly attribute nsIDOMDOMStringMap dataset;
+  readonly attribute nsISupports      dataset;
 
            attribute boolean                        itemScope;
            attribute nsIVariant                     itemType;
            attribute DOMString                      itemId;
   readonly attribute nsIDOMHTMLPropertiesCollection properties; 
   // The following attributes are really nsDOMSettableTokenList, which has
   // PutForwards, so we express them as nsIVariants to deal with this.
            attribute nsIVariant                     itemValue;
new file mode 100644
--- /dev/null
+++ b/dom/webidl/DOMStringMap.webidl
@@ -0,0 +1,19 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#domstringmap-0
+ *
+ *  Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
+ * Opera Software ASA. You are granted a license to use, reproduce
+ * and create derivative works of this document.
+ */
+
+interface DOMStringMap {
+  getter DOMString (DOMString name);
+  [Throws]
+  setter creator void (DOMString name, DOMString value);
+  deleter void (DOMString name);
+};
--- a/dom/webidl/WebIDL.mk
+++ b/dom/webidl/WebIDL.mk
@@ -19,16 +19,17 @@ webidl_files = \
   Blob.webidl \
   CanvasRenderingContext2D.webidl \
   ClientRectList.webidl \
   CSSStyleDeclaration.webidl \
   DelayNode.webidl \
   DOMImplementation.webidl \
   DOMTokenList.webidl \
   DOMSettableTokenList.webidl \
+  DOMStringMap.webidl \
   Function.webidl \
   EventHandler.webidl \
   EventListener.webidl \
   EventTarget.webidl \
   FileList.webidl \
   FileReaderSync.webidl \
   GainNode.webidl \
   HTMLCollection.webidl \