Bug 1088228 part 6. Simplify the DOM GetParentObject setup, now that we no longer rely on it for scope chains. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 30 Oct 2014 17:43:42 -0400
changeset 213333 411d5252365bc2a564e7edfb2991fe538ae41146
parent 213332 f5e241cd0b82c709e8b399b0c11bc0375e799d5a
child 213334 2887e7c320feed62cb66ff49327d37d13ad81276
push id27748
push userryanvm@gmail.com
push dateFri, 31 Oct 2014 20:14:33 +0000
treeherdermozilla-central@12ac66e2c016 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1088228
milestone36.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 1088228 part 6. Simplify the DOM GetParentObject setup, now that we no longer rely on it for scope chains. r=peterv
dom/base/nsIDocument.h
dom/base/nsINode.h
dom/bindings/BindingUtils.h
dom/bindings/Codegen.py
dom/html/HTMLLegendElement.h
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
dom/xul/nsXULElement.h
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2872,12 +2872,16 @@ inline nsINode*
 nsINode::OwnerDocAsNode() const
 {
   return OwnerDoc();
 }
 
 inline mozilla::dom::ParentObject
 nsINode::GetParentObject() const
 {
-  return GetParentObjectInternal(OwnerDoc());
+  mozilla::dom::ParentObject p(OwnerDoc());
+    // Note that mUseXBLScope is a no-op for chrome, and other places where we
+    // don't use XBL scopes.
+  p.mUseXBLScope = IsInAnonymousSubtree() && !IsAnonymousContentInSVGUseSubtree();
+  return p;
 }
 
 #endif /* nsIDocument_h___ */
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -377,27 +377,16 @@ public:
 protected:
   /**
    * WrapNode is called from WrapObject to actually wrap this node, WrapObject
    * does some additional checks and fix-up that's common to all nodes. WrapNode
    * should just call the DOM binding's Wrap function.
    */
   virtual JSObject* WrapNode(JSContext *aCx) = 0;
 
-  // Subclasses that wish to override the parent behavior should return the
-  // result of GetParentObjectIntenral, which handles the XBL scope stuff.
-  //
-  mozilla::dom::ParentObject GetParentObjectInternal(nsINode* aNativeParent) const {
-    mozilla::dom::ParentObject p(aNativeParent);
-    // Note that mUseXBLScope is a no-op for chrome, and other places where we
-    // don't use XBL scopes.
-    p.mUseXBLScope = IsInAnonymousSubtree() && !IsAnonymousContentInSVGUseSubtree();
-    return p;
-  }
-
 public:
   mozilla::dom::ParentObject GetParentObject() const; // Implemented in nsIDocument.h
 
   /**
    * Return the scope chain parent for this node, for use in things
    * like event handler compilation.  Returning null means to use the
    * global object as the scope chain parent.
    */
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1499,44 +1499,27 @@ WrapNativeParent(JSContext* cx, T* p, ns
 // things like the nsWrapperCache for it.
 template<typename T>
 static inline JSObject*
 WrapNativeParent(JSContext* cx, const T& p)
 {
   return WrapNativeParent(cx, GetParentPointer(p), GetWrapperCache(p), GetUseXBLScope(p));
 }
 
-// A way to differentiate between nodes, which use the parent object
-// returned by native->GetParentObject(), and all other objects, which
-// just use the parent's global.
-static inline JSObject*
-GetRealParentObject(void* aParent, JSObject* aParentObject)
-{
-  return aParentObject ?
-    js::GetGlobalForObjectCrossCompartment(aParentObject) : nullptr;
-}
-
-static inline JSObject*
-GetRealParentObject(Element* aParent, JSObject* aParentObject)
-{
-  return aParentObject;
-}
-
 HAS_MEMBER(GetParentObject)
 
 template<typename T, bool WrapperCached=HasGetParentObjectMember<T>::Value>
 struct GetParentObject
 {
   static JSObject* Get(JSContext* cx, JS::Handle<JSObject*> obj)
   {
     MOZ_ASSERT(js::IsObjectInContextCompartment(obj, cx));
     T* native = UnwrapDOMObject<T>(obj);
-    return
-      GetRealParentObject(native,
-                          WrapNativeParent(cx, native->GetParentObject()));
+    JSObject* wrappedParent = WrapNativeParent(cx, native->GetParentObject());
+    return wrappedParent ? js::GetGlobalForObjectCrossCompartment(wrappedParent) : nullptr;
   }
 };
 
 template<typename T>
 struct GetParentObject<T, false>
 {
   static JSObject* Get(JSContext* cx, JS::Handle<JSObject*> obj)
   {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3064,51 +3064,49 @@ class CGConstructorEnabled(CGAbstractMet
                                         pre="return ", post=";\n", reindent=True)
         else:
           conditionsWrapper = CGGeneric("return true;\n")
 
         body.append(conditionsWrapper)
         return body.define()
 
 
-def CreateBindingJSObject(descriptor, properties, parent):
+def CreateBindingJSObject(descriptor, properties):
     # We don't always need to root obj, but there are a variety
     # of cases where we do, so for simplicity, just always root it.
     objDecl = "JS::Rooted<JSObject*> obj(aCx);\n"
     if descriptor.proxy:
-        create = fill(
+        create = dedent(
             """
             JS::Rooted<JS::Value> proxyPrivateVal(aCx, JS::PrivateValue(aObject));
             js::ProxyOptions options;
             options.setClass(&Class.mBase);
             obj = NewProxyObject(aCx, DOMProxyHandler::getInstance(),
-                                 proxyPrivateVal, proto, ${parent}, options);
+                                 proxyPrivateVal, proto, global, options);
             if (!obj) {
               return nullptr;
             }
 
-            """,
-            parent=parent)
+            """)
         if descriptor.interface.getExtendedAttribute('OverrideBuiltins'):
             create += dedent("""
                 js::SetProxyExtra(obj, JSPROXYSLOT_EXPANDO,
                                   JS::PrivateValue(&aObject->mExpandoAndGeneration));
 
                 """)
     else:
-        create = fill(
-            """
-            obj = JS_NewObject(aCx, Class.ToJSClass(), proto, ${parent});
+        create = dedent(
+            """
+            obj = JS_NewObject(aCx, Class.ToJSClass(), proto, global);
             if (!obj) {
               return nullptr;
             }
 
             js::SetReservedSlot(obj, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
-            """,
-            parent=parent)
+            """)
     create = objDecl + create
 
     if descriptor.nativeOwnership == 'refcounted':
         create += "NS_ADDREF(aObject);\n"
     else:
         create += dedent("""
             // Make sure the native objects inherit from NonRefcountedDOMObject so that we
             // log their ctor and dtor.
@@ -3249,51 +3247,48 @@ class CGWrapWithCacheMethod(CGAbstractMe
     def definition_body(self):
         return fill(
             """
             $*{assertion}
 
             MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
                        "nsISupports must be on our primary inheritance chain");
 
-            JS::Rooted<JSObject*> parent(aCx,
-              GetRealParentObject(aObject,
-                                  WrapNativeParent(aCx, aObject->GetParentObject())));
+            JS::Rooted<JSObject*> parent(aCx, WrapNativeParent(aCx, aObject->GetParentObject()));
             if (!parent) {
               return nullptr;
             }
 
             // That might have ended up wrapping us already, due to the wonders
             // of XBL.  Check for that, and bail out as needed.  Scope so we don't
             // collide with the "obj" we declare in CreateBindingJSObject.
             {
               JSObject* obj = aCache->GetWrapper();
               if (obj) {
                 return obj;
               }
             }
 
             JSAutoCompartment ac(aCx, parent);
-            JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, parent));
+            JS::Rooted<JSObject*> global(aCx, js::GetGlobalForObjectCrossCompartment(parent));
             JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx, global);
             if (!proto) {
               return nullptr;
             }
 
-            $*{parent}
+            $*{createObject}
 
             $*{unforgeable}
 
             aCache->SetWrapper(obj);
             $*{slots}
             return obj;
             """,
             assertion=AssertInheritanceChain(self.descriptor),
-            parent=CreateBindingJSObject(self.descriptor, self.properties,
-                                         "parent"),
+            createObject=CreateBindingJSObject(self.descriptor, self.properties),
             unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
             slots=InitMemberSlots(self.descriptor, True))
 
 
 class CGWrapMethod(CGAbstractMethod):
     def __init__(self, descriptor):
         # XXX can we wrap if we don't have an interface prototype object?
         assert descriptor.interface.hasInterfacePrototypeObject()
@@ -3329,26 +3324,25 @@ class CGWrapNonWrapperCacheMethod(CGAbst
             $*{assertions}
 
             JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
             JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx, global);
             if (!proto) {
               return nullptr;
             }
 
-            $*{global_}
+            $*{createObject}
 
             $*{unforgeable}
 
             $*{slots}
             return obj;
             """,
             assertions=AssertInheritanceChain(self.descriptor),
-            global_=CreateBindingJSObject(self.descriptor, self.properties,
-                                          "global"),
+            createObject=CreateBindingJSObject(self.descriptor, self.properties),
             unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
             slots=InitMemberSlots(self.descriptor, False))
 
 
 class CGWrapGlobalMethod(CGAbstractMethod):
     """
     Create a wrapper JSObject for a global.  The global must implement
     nsWrapperCache.
--- a/dom/html/HTMLLegendElement.h
+++ b/dom/html/HTMLLegendElement.h
@@ -72,22 +72,16 @@ public:
     GetHTMLAttr(nsGkAtoms::align, aAlign);
   }
 
   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
   }
 
-  ParentObject GetParentObject() {
-    Element* form = GetFormElement();
-    return form ? GetParentObjectInternal(form)
-                : nsGenericHTMLElement::GetParentObject();
-  }
-
   nsINode* GetScopeChainParent() const MOZ_OVERRIDE
   {
     Element* form = GetFormElement();
     return form ? form : nsGenericHTMLElement::GetScopeChainParent();
   }
 
 protected:
   virtual ~HTMLLegendElement();
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1891,26 +1891,16 @@ nsGenericHTMLFormElement::~nsGenericHTML
   // Check that this element doesn't know anything about its form at this point.
   NS_ASSERTION(!mForm, "mForm should be null at this point!");
 }
 
 NS_IMPL_ISUPPORTS_INHERITED(nsGenericHTMLFormElement,
                             nsGenericHTMLElement,
                             nsIFormControl)
 
-mozilla::dom::ParentObject
-nsGenericHTMLFormElement::GetParentObject() const
-{
-  // We use the parent chain to implement the scope for event handlers.
-  if (mForm) {
-    return GetParentObjectInternal(mForm);
-  }
-  return nsGenericHTMLElement::GetParentObject();
-}
-
 nsINode*
 nsGenericHTMLFormElement::GetScopeChainParent() const
 {
   return mForm ? mForm : nsGenericHTMLElement::GetScopeChainParent();
 }
 
 bool
 nsGenericHTMLFormElement::IsNodeOfType(uint32_t aFlags) const
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -1240,18 +1240,16 @@ ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPE
 class nsGenericHTMLFormElement : public nsGenericHTMLElement,
                                  public nsIFormControl
 {
 public:
   explicit nsGenericHTMLFormElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   NS_DECL_ISUPPORTS_INHERITED
 
-  mozilla::dom::ParentObject GetParentObject() const;
-
   nsINode* GetScopeChainParent() const MOZ_OVERRIDE;
 
   virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
   virtual void SaveSubtreeState() MOZ_OVERRIDE;
 
   // nsIFormControl
   virtual mozilla::dom::HTMLFieldSetElement* GetFieldSet();
   virtual mozilla::dom::Element* GetFormElement() MOZ_OVERRIDE;
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -601,28 +601,19 @@ public:
       GetElementsByAttributeNS(const nsAString& aNamespaceURI,
                                const nsAString& aAttribute,
                                const nsAString& aValue,
                                mozilla::ErrorResult& rv);
     // Style() inherited from nsStyledElement
     already_AddRefed<nsFrameLoader> GetFrameLoader();
     void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& rv);
 
-    // For XUL, the parent is the parent element, if any
-    mozilla::dom::ParentObject GetParentObject() const
-    {
-        Element* parent = GetParentElement();
-        if (parent) {
-          return GetParentObjectInternal(parent);
-        }
-        return nsStyledElement::GetParentObject();
-    }
-
     nsINode* GetScopeChainParent() const MOZ_OVERRIDE
     {
+        // For XUL, the parent is the parent element, if any
         Element* parent = GetParentElement();
         return parent ? parent : nsStyledElement::GetScopeChainParent();
     }
 
 protected:
     ~nsXULElement();
 
     // This can be removed if EnsureContentsGenerated dies.