Bug 877277 - Move the document.all getter into WebIDL; r=smaug
authorMs2ger <ms2ger@gmail.com>
Wed, 12 Jun 2013 08:55:00 +0200
changeset 134739 135a277d13194b78612fb30be8ee744ce749614a
parent 134738 c1ed5d80b9d0ccd5b50b5a224401e22d5951f1fe
child 134740 e20539356853f52a09c54a02a7a5e8a40564feb8
push id29360
push useremorley@mozilla.com
push dateWed, 12 Jun 2013 07:41:20 +0000
treeherdermozilla-inbound@c5875145f618 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs877277
milestone24.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 877277 - Move the document.all getter into WebIDL; r=smaug
content/html/document/src/nsHTMLDocument.cpp
content/html/document/src/nsHTMLDocument.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfo.h
dom/webidl/HTMLDocument.webidl
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -196,28 +196,54 @@ nsHTMLDocument::nsHTMLDocument()
 
   mIsRegularHTML = true;
   mDefaultElementType = kNameSpaceID_XHTML;
   mCompatMode = eCompatibility_NavQuirks;
 
   SetIsDOMBinding();
 }
 
-
-NS_IMPL_CYCLE_COLLECTION_INHERITED_10(nsHTMLDocument, nsDocument,
-                                      mImages,
-                                      mApplets,
-                                      mEmbeds,
-                                      mLinks,
-                                      mAnchors,
-                                      mScripts,
-                                      mForms,
-                                      mFormControls,
-                                      mWyciwygChannel,
-                                      mMidasCommandManager)
+nsHTMLDocument::~nsHTMLDocument()
+{
+  mAll = nullptr;
+  NS_DROP_JS_OBJECTS(this, nsHTMLDocument);
+}
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
+  NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
+               "Shouldn't traverse nsHTMLDocument!");
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImages)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mApplets)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEmbeds)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLinks)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnchors)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScripts)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mForms)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFormControls)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWyciwygChannel)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMidasCommandManager)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
+  tmp->mAll = nullptr;
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mImages)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mApplets)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mEmbeds)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLinks)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnchors)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mScripts)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mForms)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFormControls)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mWyciwygChannel)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mMidasCommandManager)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mAll)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_ADDREF_INHERITED(nsHTMLDocument, nsDocument)
 NS_IMPL_RELEASE_INHERITED(nsHTMLDocument, nsDocument)
 
 // QueryInterface implementation for nsHTMLDocument
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsHTMLDocument)
   NS_INTERFACE_TABLE_INHERITED2(nsHTMLDocument, nsIHTMLDocument,
                                 nsIDOMHTMLDocument)
@@ -2305,20 +2331,16 @@ nsHTMLDocument::ResolveName(const nsAStr
 JSObject*
 nsHTMLDocument::NamedGetter(JSContext* cx, const nsAString& aName, bool& aFound,
                             ErrorResult& rv)
 {
   nsWrapperCache* cache;
   nsISupports* supp = ResolveName(aName, &cache);
   if (!supp) {
     aFound = false;
-    if (aName.EqualsLiteral("all")) {
-      JS::Rooted<JSObject*> obj(cx, GetWrapper());
-      rv = nsHTMLDocumentSH::TryResolveAll(cx, this, obj);
-    }
     return nullptr;
   }
 
   JS::Rooted<JS::Value> val(cx);
   { // Scope for auto-compartment
     JS::Rooted<JSObject*> wrapper(cx, GetWrapper());
     JSAutoCompartment ac(cx, wrapper);
     // XXXbz Should we call the (slightly misnamed, really) WrapNativeParent
@@ -2693,16 +2715,37 @@ nsHTMLDocument::GetDocumentAllResult(con
   }
 
   // There's only 0 or 1 items. Return the first one or null.
   *aCache = cont = docAllList->Item(0, true);
 
   return cont;
 }
 
+JSObject*
+nsHTMLDocument::GetAll(JSContext* aCx, ErrorResult& aRv)
+{
+  if (!mAll) {
+    mAll = JS_NewObject(aCx, &sHTMLDocumentAllClass, nullptr,
+                        JS_GetGlobalForObject(aCx, GetWrapper()));
+    if (!mAll) {
+      aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
+      return nullptr;
+    }
+
+    // Make the JSObject hold a reference to this.
+    JS_SetPrivate(mAll, static_cast<nsINode*>(this));
+    NS_ADDREF_THIS();
+
+    NS_HOLD_JS_OBJECTS(this, nsHTMLDocument);
+  }
+
+  return mAll;
+}
+
 static void
 NotifyEditableStateChange(nsINode *aNode, nsIDocument *aDocument)
 {
   for (nsIContent* child = aNode->GetFirstChild();
        child;
        child = child->GetNextSibling()) {
     if (child->IsElement()) {
       child->AsElement()->UpdateState(true);
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -39,23 +39,24 @@ class nsHTMLDocument : public nsDocument
                        public nsIHTMLDocument,
                        public nsIDOMHTMLDocument
 {
 public:
   using nsDocument::SetDocumentURI;
   using nsDocument::GetPlugins;
 
   nsHTMLDocument();
+  ~nsHTMLDocument();
   virtual nsresult Init() MOZ_OVERRIDE;
 
-  NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) MOZ_OVERRIDE;
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(nsHTMLDocument,
+                                                         nsDocument)
 
-  NS_IMETHOD_(nsrefcnt) AddRef(void) MOZ_OVERRIDE;
-  NS_IMETHOD_(nsrefcnt) Release(void) MOZ_OVERRIDE;
-
+  // nsIDocument
   virtual void Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup) MOZ_OVERRIDE;
   virtual void ResetToURI(nsIURI* aURI, nsILoadGroup* aLoadGroup,
                           nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
 
   virtual already_AddRefed<nsIPresShell> CreateShell(nsPresContext* aContext,
                                                      nsViewManager* aViewManager,
                                                      nsStyleSet* aStyleSet) MOZ_OVERRIDE;
 
@@ -64,19 +65,25 @@ public:
                                      nsILoadGroup* aLoadGroup,
                                      nsISupports* aContainer,
                                      nsIStreamListener **aDocListener,
                                      bool aReset = true,
                                      nsIContentSink* aSink = nullptr) MOZ_OVERRIDE;
   virtual void StopDocumentLoad() MOZ_OVERRIDE;
 
   virtual void BeginLoad() MOZ_OVERRIDE;
-
   virtual void EndLoad() MOZ_OVERRIDE;
 
+  virtual NS_HIDDEN_(void) Destroy() MOZ_OVERRIDE
+  {
+    mAll = nullptr;
+    nsDocument::Destroy();
+  }
+
+  // nsIHTMLDocument
   virtual void SetCompatibilityMode(nsCompatibility aMode) MOZ_OVERRIDE;
 
   virtual bool IsWriting() MOZ_OVERRIDE
   {
     return mWriteLevel != uint32_t(0);
   }
 
   virtual NS_HIDDEN_(nsContentList*) GetForms();
@@ -103,16 +110,17 @@ public:
   /**
    * Returns the result of document.all[aID] which can either be a node
    * or a nodelist depending on if there are multiple nodes with the same
    * id.
    */
   nsISupports *GetDocumentAllResult(const nsAString& aID,
                                     nsWrapperCache **aCache,
                                     nsresult *aResult);
+  JSObject* GetAll(JSContext* aCx, mozilla::ErrorResult& aRv);
 
   nsISupports* ResolveName(const nsAString& aName, nsWrapperCache **aCache);
   virtual already_AddRefed<nsISupports> ResolveName(const nsAString& aName,
                                                     nsIContent *aForm,
                                                     nsWrapperCache **aCache) MOZ_OVERRIDE;
 
   virtual void AddedForm() MOZ_OVERRIDE;
   virtual void RemovedForm() MOZ_OVERRIDE;
@@ -150,18 +158,16 @@ public:
   private:
     nsHTMLDocument* mDoc;
     EditingState    mSavedState;
   };
   friend class nsAutoEditingState;
 
   void EndUpdate(nsUpdateType aUpdateType) MOZ_OVERRIDE;
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLDocument, nsDocument)
-
   virtual nsresult SetEditingState(EditingState aState) MOZ_OVERRIDE;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual NS_HIDDEN_(void) RemovedFromDocShell() MOZ_OVERRIDE;
 
   virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId)
   {
@@ -289,16 +295,18 @@ protected:
   nsRefPtr<nsContentList> mApplets;
   nsRefPtr<nsContentList> mEmbeds;
   nsRefPtr<nsContentList> mLinks;
   nsRefPtr<nsContentList> mAnchors;
   nsRefPtr<nsContentList> mScripts;
   nsRefPtr<nsContentList> mForms;
   nsRefPtr<nsContentList> mFormControls;
 
+  JSObject* mAll;
+
   /** # of forms in the document, synchronously set */
   int32_t mNumForms;
 
   static uint32_t gWyciwygSessionCnt;
 
   static void TryHintCharset(nsIMarkupDocumentViewer* aMarkupDV,
                              int32_t& aCharsetSource,
                              nsACString& aCharset);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -887,17 +887,16 @@ jsid nsDOMClassInfo::sScrollMaxY_id     
 jsid nsDOMClassInfo::sItem_id            = JSID_VOID;
 jsid nsDOMClassInfo::sNamedItem_id       = JSID_VOID;
 jsid nsDOMClassInfo::sEnumerate_id       = JSID_VOID;
 jsid nsDOMClassInfo::sNavigator_id       = JSID_VOID;
 jsid nsDOMClassInfo::sTop_id             = JSID_VOID;
 jsid nsDOMClassInfo::sDocument_id        = JSID_VOID;
 jsid nsDOMClassInfo::sFrames_id          = JSID_VOID;
 jsid nsDOMClassInfo::sSelf_id            = JSID_VOID;
-jsid nsDOMClassInfo::sAll_id             = JSID_VOID;
 jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
 jsid nsDOMClassInfo::sURL_id             = JSID_VOID;
 jsid nsDOMClassInfo::sOnload_id          = JSID_VOID;
 jsid nsDOMClassInfo::sOnerror_id         = JSID_VOID;
 
 static const JSClass *sObjectClass = nullptr;
 
 /**
@@ -1083,17 +1082,16 @@ nsDOMClassInfo::DefineStaticJSVals(JSCon
   SET_JSID_TO_STRING(sItem_id,            cx, "item");
   SET_JSID_TO_STRING(sNamedItem_id,       cx, "namedItem");
   SET_JSID_TO_STRING(sEnumerate_id,       cx, "enumerateProperties");
   SET_JSID_TO_STRING(sNavigator_id,       cx, "navigator");
   SET_JSID_TO_STRING(sTop_id,             cx, "top");
   SET_JSID_TO_STRING(sDocument_id,        cx, "document");
   SET_JSID_TO_STRING(sFrames_id,          cx, "frames");
   SET_JSID_TO_STRING(sSelf_id,            cx, "self");
-  SET_JSID_TO_STRING(sAll_id,             cx, "all");
   SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
   SET_JSID_TO_STRING(sURL_id,             cx, "URL");
   SET_JSID_TO_STRING(sOnload_id,          cx, "onload");
   SET_JSID_TO_STRING(sOnerror_id,         cx, "onerror");
 
   return NS_OK;
 }
 
@@ -2606,17 +2604,16 @@ nsDOMClassInfo::ShutDown()
   sScrollMaxY_id      = JSID_VOID;
   sItem_id            = JSID_VOID;
   sEnumerate_id       = JSID_VOID;
   sNavigator_id       = JSID_VOID;
   sTop_id             = JSID_VOID;
   sDocument_id        = JSID_VOID;
   sFrames_id          = JSID_VOID;
   sSelf_id            = JSID_VOID;
-  sAll_id             = JSID_VOID;
   sWrappedJSObject_id = JSID_VOID;
   sOnload_id          = JSID_VOID;
   sOnerror_id         = JSID_VOID;
 
   NS_IF_RELEASE(sXPConnect);
   NS_IF_RELEASE(sSecMan);
   sIsInitialized = false;
 }
@@ -2720,18 +2717,19 @@ ChildWindowGetter(JSContext *cx, JSHandl
   NS_ENSURE_SUCCESS(rv, false);
   vp.set(v);
   return true;
 }
 
 static nsHTMLDocument*
 GetDocument(JSObject *obj)
 {
+  MOZ_ASSERT(js::GetObjectJSClass(obj) == &sHTMLDocumentAllClass);
   return static_cast<nsHTMLDocument*>(
-    static_cast<nsIHTMLDocument*>(::JS_GetPrivate(obj)));
+    static_cast<nsINode*>(JS_GetPrivate(obj)));
 }
 
 // static
 JSBool
 nsWindowSH::GlobalScopePolluterNewResolve(JSContext *cx, JSHandleObject obj,
                                           JSHandleId id, unsigned flags,
                                           JS::MutableHandle<JSObject*> objp)
 {
@@ -5620,48 +5618,35 @@ nsNamedArraySH::GetProperty(nsIXPConnect
     // Don't fall through to nsArraySH::GetProperty() here
     return rv;
   }
 
   return nsArraySH::GetProperty(wrapper, cx, obj, id, vp, _retval);
 }
 
 
-// HTMLDocument helper
-
-static JSClass sHTMLDocumentAllClass = {
+// HTMLAllCollection
+
+JSClass sHTMLDocumentAllClass = {
   "HTML document.all class",
   JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_NEW_RESOLVE |
   JSCLASS_EMULATES_UNDEFINED | JSCLASS_HAS_RESERVED_SLOTS(1),
   JS_PropertyStub,                                         /* addProperty */
   JS_DeletePropertyStub,                                   /* delProperty */
   nsHTMLDocumentSH::DocumentAllGetProperty,                /* getProperty */
   JS_StrictPropertyStub,                                   /* setProperty */
   JS_EnumerateStub,
   (JSResolveOp)nsHTMLDocumentSH::DocumentAllNewResolve,
   JS_ConvertStub,
   nsHTMLDocumentSH::ReleaseDocument,
   nullptr,                                                  /* checkAccess */
   nsHTMLDocumentSH::CallToGetPropMapper
 };
 
 
-static JSClass sHTMLDocumentAllHelperClass = {
-  "HTML document.all helper class",
-  JSCLASS_NEW_RESOLVE,
-  JS_PropertyStub,                                         /* addProperty */
-  JS_DeletePropertyStub,                                   /* delProperty */
-  nsHTMLDocumentSH::DocumentAllHelperGetProperty,          /* getProperty */
-  JS_StrictPropertyStub,                                   /* setProperty */
-  JS_EnumerateStub,
-  (JSResolveOp)nsHTMLDocumentSH::DocumentAllHelperNewResolve,
-  JS_ConvertStub
-};
-
-
 // static
 JSBool
 nsHTMLDocumentSH::GetDocumentAllNodeList(JSContext *cx,
                                          JS::Handle<JSObject*> obj,
                                          nsDocument *domdoc,
                                          nsContentList **nodeList)
 {
   // The document.all object is a mix of the node list returned by
@@ -5855,23 +5840,20 @@ nsHTMLDocumentSH::DocumentAllNewResolve(
   if (v.get() != JSVAL_VOID) {
     ok = ::JS_DefinePropertyById(cx, obj, id, v, nullptr, nullptr, 0);
     objp.set(obj);
   }
 
   return ok;
 }
 
-// Finalize hook used by document related JS objects, but also by
-// sGlobalScopePolluterClass!
-
 void
 nsHTMLDocumentSH::ReleaseDocument(JSFreeOp *fop, JSObject *obj)
 {
-  nsIHTMLDocument *doc = static_cast<nsIHTMLDocument *>(JS_GetPrivate(obj));
+  nsIHTMLDocument* doc = GetDocument(obj);
   if (doc) {
     xpc::DeferredRelease(doc);
   }
 }
 
 JSBool
 nsHTMLDocumentSH::CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp)
 {
@@ -5911,165 +5893,16 @@ nsHTMLDocumentSH::CallToGetPropMapper(JS
   if (!chars) {
     return JS_FALSE;
   }
 
   return ::JS_GetUCProperty(cx, self, chars, length, vp);
 }
 
 
-static inline bool
-GetDocumentAllHelper(JSContext *cx, JS::Handle<JSObject*> aObj, JSObject **result)
-{
-  JS::Rooted<JSObject*> obj(cx, aObj);
-  while (obj && JS_GetClass(obj) != &sHTMLDocumentAllHelperClass) {
-    if (!::JS_GetPrototype(cx, obj, obj.address())) {
-      return false;
-    }
-  }
-
-  *result = obj;
-  return true;
-}
-
-JSBool
-nsHTMLDocumentSH::DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
-                                               JSHandleId id, JSMutableHandleValue vp)
-{
-  if (nsDOMClassInfo::sAll_id != id) {
-    return JS_TRUE;
-  }
-
-  if (!vp.isObjectOrNull()) {
-    // First time through, create the collection, and set the
-    // document as its private nsISupports data.
-    nsresult rv;
-    nsCOMPtr<nsIHTMLDocument> doc = do_QueryWrapper(cx, obj, &rv);
-    if (NS_FAILED(rv)) {
-      xpc::Throw(cx, rv);
-      return JS_FALSE;
-    }
-
-    JS::Rooted<JSObject*> all(cx);
-    all = ::JS_NewObject(cx, &sHTMLDocumentAllClass, nullptr,
-                         ::JS_GetGlobalForObject(cx, obj));
-    if (!all) {
-      return JS_FALSE;
-    }
-
-    // Let the JSObject take over ownership of doc.
-    ::JS_SetPrivate(all, doc.forget().get());
-
-    vp.setObject(*all);
-  }
-
-  return JS_TRUE;
-}
-
-JSBool
-nsHTMLDocumentSH::DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
-                                              JSHandleId id, unsigned flags,
-                                              JS::MutableHandle<JSObject*> objp)
-{
-  if (nsDOMClassInfo::sAll_id == id) {
-    // document.all is resolved for the first time. Define it.
-    JS::Rooted<JSObject*> helper(cx);
-    if (!GetDocumentAllHelper(cx, obj, helper.address())) {
-      return JS_FALSE;
-    }
-
-    if (helper) {
-      if (!::JS_DefineProperty(cx, helper, "all", JSVAL_VOID, nullptr, nullptr,
-                               JSPROP_ENUMERATE)) {
-        return JS_FALSE;
-      }
-
-      objp.set(helper);
-    }
-  }
-
-  return JS_TRUE;
-}
-
-
-static nsresult
-ResolveAll(JSContext* cx, nsIDocument* doc, JS::Handle<JSObject*> obj)
-{
-  JS::Rooted<JSObject*> proto(cx);
-  if (!::JS_GetPrototype(cx, obj, proto.address())) {
-    return NS_ERROR_FAILURE;
-  }
-
-  JS::Rooted<JSObject*> helper(cx);
-  if (!GetDocumentAllHelper(cx, proto, helper.address())) {
-    return NS_ERROR_FAILURE;
-  }
-
-  if (!::JS_GetPrototype(cx, helper ? helper : obj, proto.address())) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // Check if the property all is defined on obj's (or helper's
-  // if obj doesn't exist) prototype, if it is, don't expose our
-  // document.all helper.
-
-  JSBool hasAll = JS_FALSE;
-  if (proto && !JS_HasProperty(cx, proto, "all", &hasAll)) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  if (hasAll && helper) {
-    // Our helper's prototype now has an "all" property, remove
-    // the helper out of the prototype chain to prevent
-    // shadowing of the now defined "all" property.
-    JS::Rooted<JSObject*> tmp(cx, obj), tmpProto(cx, tmp);
-
-    do {
-      tmp = tmpProto;
-      if (!::JS_GetPrototype(cx, tmp, tmpProto.address())) {
-        return NS_ERROR_UNEXPECTED;
-      }
-    } while (tmpProto != helper);
-
-    ::JS_SetPrototype(cx, tmp, proto);
-  }
-
-  // If we don't already have a helper and "all" isn't already defined on
-  // our prototype, create a helper.
-  if (!helper && !hasAll) {
-    if (!::JS_GetPrototype(cx, obj, proto.address())) {
-      return NS_ERROR_UNEXPECTED;
-    }
-    helper = ::JS_NewObject(cx, &sHTMLDocumentAllHelperClass,
-                            proto,
-                            ::JS_GetGlobalForObject(cx, obj));
-
-    if (!helper) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    // Insert the helper into our prototype chain. helper's prototype
-    // is already obj's current prototype.
-    if (!::JS_SetPrototype(cx, obj, helper)) {
-      xpc::Throw(cx, NS_ERROR_UNEXPECTED);
-      return NS_ERROR_UNEXPECTED;
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsHTMLDocumentSH::TryResolveAll(JSContext* cx, nsHTMLDocument* doc,
-                                JS::Handle<JSObject*> obj)
-{
-  JSAutoCompartment ac(cx, obj);
-  return ResolveAll(cx, doc, obj);
-}
-
 // HTMLFormElement helper
 
 NS_IMETHODIMP
 nsHTMLFormElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,
                                 JSContext *cx, JSObject *aObj, jsid aId,
                                 uint32_t flags, JSObject **objp,
                                 bool *_retval)
 {
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -212,17 +212,16 @@ public:
   static jsid sItem_id;
   static jsid sNamedItem_id;
   static jsid sEnumerate_id;
   static jsid sNavigator_id;
   static jsid sTop_id;
   static jsid sDocument_id;
   static jsid sFrames_id;
   static jsid sSelf_id;
-  static jsid sAll_id;
   static jsid sJava_id;
   static jsid sPackages_id;
   static jsid sWrappedJSObject_id;
   static jsid sURL_id;
   static jsid sOnload_id;
   static jsid sOnerror_id;
 
 protected:
@@ -586,39 +585,33 @@ public:
                          JSObject *obj, jsid id, jsval *vp, bool *_retval) MOZ_OVERRIDE;
 
 private:
   // Not implemented, nothing should create an instance of this class.
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData);
 };
 
 
-// HTMLDocument helper
+// HTMLAllCollection
+
+extern JSClass sHTMLDocumentAllClass;
 
 class nsHTMLDocumentSH
 {
 protected:
   static JSBool GetDocumentAllNodeList(JSContext *cx, JS::Handle<JSObject*> obj,
                                        nsDocument *doc,
                                        nsContentList **nodeList);
 public:
   static JSBool DocumentAllGetProperty(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                        JSMutableHandleValue vp);
   static JSBool DocumentAllNewResolve(JSContext *cx, JSHandleObject obj, JSHandleId id,
                                       unsigned flags, JS::MutableHandle<JSObject*> objp);
   static void ReleaseDocument(JSFreeOp *fop, JSObject *obj);
   static JSBool CallToGetPropMapper(JSContext *cx, unsigned argc, jsval *vp);
-  static JSBool DocumentAllHelperGetProperty(JSContext *cx, JSHandleObject obj,
-                                             JSHandleId id, JSMutableHandleValue vp);
-  static JSBool DocumentAllHelperNewResolve(JSContext *cx, JSHandleObject obj,
-                                            JSHandleId id, unsigned flags,
-                                            JS::MutableHandle<JSObject*> objp);
-
-  static nsresult TryResolveAll(JSContext* cx, nsHTMLDocument* doc,
-                                JS::Handle<JSObject*> obj);
 };
 
 
 // HTMLFormElement helper
 
 class nsHTMLFormElementSH : public nsElementSH
 {
 protected:
--- a/dom/webidl/HTMLDocument.webidl
+++ b/dom/webidl/HTMLDocument.webidl
@@ -60,12 +60,15 @@ interface HTMLDocument : Document {
   [TreatNullAs=EmptyString] attribute DOMString alinkColor;
   [TreatNullAs=EmptyString] attribute DOMString bgColor;
 
   readonly attribute HTMLCollection anchors;
   readonly attribute HTMLCollection applets;
 
   void clear();
 
+  [Throws]
+  readonly attribute object all;
+
   // https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#selections
   [Throws]
   Selection getSelection();
 };