Bug 1088228 part 1. Introduce an nsINode API for getting the scope chain parent for a given node. r=peterv
☠☠ backed out by a37fedd51b7d ☠ ☠
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 30 Oct 2014 17:38:48 -0400
changeset 213246 55f4818378e45014be126d54b1c236a4cdb844c0
parent 213245 aec14e7888f0281086438f28e50a44ad1159b67e
child 213247 920d50e84a17f9198e05b559314751da78b1bcf5
push id27745
push usercbook@mozilla.com
push dateFri, 31 Oct 2014 13:09:12 +0000
treeherdermozilla-central@6bd2071b373f [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 1. Introduce an nsINode API for getting the scope chain parent for a given node. r=peterv
dom/base/Element.cpp
dom/base/Element.h
dom/base/nsIDocument.h
dom/base/nsINode.cpp
dom/base/nsINode.h
dom/html/HTMLLegendElement.cpp
dom/html/HTMLLegendElement.h
dom/html/nsGenericHTMLElement.cpp
dom/html/nsGenericHTMLElement.h
dom/xul/nsXULElement.h
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -495,16 +495,23 @@ Element::WrapObject(JSContext *aCx)
           NS_NewRunnableMethod(binding, &nsXBLBinding::ExecuteAttachedHandler));
       }
     }
   }
 
   return obj;
 }
 
+/* virtual */
+nsINode*
+Element::GetScopeChainParent() const
+{
+  return OwnerDoc();
+}
+
 nsDOMTokenList*
 Element::ClassList()
 {
   Element::nsDOMSlots* slots = DOMSlots();
 
   if (!slots->mClassList) {
     slots->mClassList = new nsDOMTokenList(this, nsGkAtoms::_class);
   }
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -134,18 +134,18 @@ class AnimationPlayer;
 class Link;
 class UndoManager;
 class DOMRect;
 class DOMRectList;
 class DestinationInsertionPointList;
 
 // IID for the dom::Element interface
 #define NS_ELEMENT_IID \
-{ 0xaa79cb98, 0xc785, 0x44c5, \
-  { 0x80, 0x80, 0x2e, 0x5f, 0x0c, 0xa5, 0xbd, 0x63 } }
+{ 0x31d3f3fb, 0xcdf8, 0x4e40, \
+ { 0xb7, 0x09, 0x1a, 0x11, 0x43, 0x93, 0x61, 0x71 } }
 
 class Element : public FragmentOrElement
 {
 public:
 #ifdef MOZILLA_INTERNAL_API
   explicit Element(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) :
     FragmentOrElement(aNodeInfo),
     mState(NS_EVENT_STATE_MOZ_READONLY)
@@ -956,16 +956,18 @@ public:
                            nsIDOMHTMLCollection** aResult);
   nsresult
     GetElementsByClassName(const nsAString& aClassNames,
                            nsIDOMHTMLCollection** aResult);
   void GetClassList(nsISupports** aClassList);
 
   virtual JSObject* WrapObject(JSContext *aCx) MOZ_FINAL MOZ_OVERRIDE;
 
+  nsINode* GetScopeChainParent() const MOZ_OVERRIDE;
+
   /**
    * Locate an nsIEditor rooted at this content node, if there is one.
    */
   nsIEditor* GetEditorInternal();
 
   /**
    * Helper method for NS_IMPL_BOOL_ATTR macro.
    * Gets value of boolean attribute. Only works for attributes in null
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -131,18 +131,18 @@ template<typename> class OwningNonNull;
 template<typename> class Sequence;
 
 template<typename, typename> class CallbackObjectHolder;
 typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID \
-{ 0xbab5b447, 0x7e23, 0x4cdd, \
-  { 0xac, 0xe5, 0xaa, 0x04, 0x26, 0x87, 0x2b, 0x97 } }
+{ 0x6bbf1955, 0xd9c4, 0x4d61, \
+ { 0xbf, 0x75, 0x1b, 0xba, 0x55, 0xf7, 0x99, 0xc2 } }
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
   DocumentFlavorSVG, // SVGDocument
   DocumentFlavorPlain, // Just a Document
 };
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -2747,8 +2747,13 @@ nsINode::GetParentElementCrossingShadowR
 
 bool
 nsINode::HasBoxQuadsSupport(JSContext* aCx, JSObject* /* unused */)
 {
   return xpc::AccessCheck::isChrome(js::GetContextCompartment(aCx)) ||
          Preferences::GetBool("layout.css.getBoxQuads.enabled");
 }
 
+nsINode*
+nsINode::GetScopeChainParent() const
+{
+  return nullptr;
+}
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -243,18 +243,18 @@ private:
 
 // Categories of node properties
 // 0 is global.
 #define DOM_USER_DATA         1
 #define SMIL_MAPPED_ATTR_ANIMVAL 2
 
 // IID for the nsINode interface
 #define NS_INODE_IID \
-{ 0x8deda3f4, 0x0f45, 0x497a, \
-  { 0x89, 0x7c, 0xe6, 0x09, 0x12, 0x8a, 0xad, 0xd8 } }
+{ 0x66972940, 0x1d1b, 0x4d15, \
+ { 0x93, 0x11, 0x96, 0x72, 0x84, 0x2e, 0xc7, 0x27 } }
 
 /**
  * An internal interface that abstracts some DOMNode-related parts that both
  * nsIContent and nsIDocument share.  An instance of this interface has a list
  * of nsIContent children and provides access to them.
  */
 class nsINode : public mozilla::dom::EventTarget
 {
@@ -392,16 +392,23 @@ protected:
     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.
+   */
+  virtual nsINode* GetScopeChainParent() const;
+
+  /**
    * Return whether the node is an Element node
    */
   bool IsElement() const {
     return GetBoolFlag(NodeIsElement);
   }
 
   /**
    * Return this node as an Element.  Should only be used for nodes
--- a/dom/html/HTMLLegendElement.cpp
+++ b/dom/html/HTMLLegendElement.cpp
@@ -17,17 +17,17 @@ namespace dom {
 
 HTMLLegendElement::~HTMLLegendElement()
 {
 }
 
 NS_IMPL_ELEMENT_CLONE(HTMLLegendElement)
 
 nsIContent*
-HTMLLegendElement::GetFieldSet()
+HTMLLegendElement::GetFieldSet() const
 {
   nsIContent* parent = GetParent();
 
   if (parent && parent->IsHTML(nsGkAtoms::fieldset)) {
     return parent;
   }
 
   return nullptr;
--- a/dom/html/HTMLLegendElement.h
+++ b/dom/html/HTMLLegendElement.h
@@ -49,17 +49,17 @@ public:
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
                            bool aNotify) MOZ_OVERRIDE;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
                              bool aNotify) MOZ_OVERRIDE;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
 
-  Element* GetFormElement()
+  Element* GetFormElement() const
   {
     nsCOMPtr<nsIFormControl> fieldsetControl = do_QueryInterface(GetFieldSet());
 
     return fieldsetControl ? fieldsetControl->GetFormElement() : nullptr;
   }
 
   /**
    * WebIDL Interface
@@ -78,24 +78,30 @@ public:
   }
 
   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();
 
   virtual JSObject* WrapNode(JSContext* aCx) MOZ_OVERRIDE;
 
   /**
    * Get the fieldset content element that contains this legend.
    * Returns null if there is no fieldset containing this legend.
    */
-  nsIContent* GetFieldSet();
+  nsIContent* GetFieldSet() const;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif /* mozilla_dom_HTMLLegendElement_h */
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -1901,16 +1901,22 @@ nsGenericHTMLFormElement::GetParentObjec
 {
   // 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
 {
   return !(aFlags & ~(eCONTENT | eHTML_FORM_CONTROL));
 }
 
 void
 nsGenericHTMLFormElement::SaveSubtreeState()
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -1242,16 +1242,18 @@ class nsGenericHTMLFormElement : public 
 {
 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;
   mozilla::dom::HTMLFormElement* GetForm() const
   {
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -611,16 +611,22 @@ public:
     {
         Element* parent = GetParentElement();
         if (parent) {
           return GetParentObjectInternal(parent);
         }
         return nsStyledElement::GetParentObject();
     }
 
+    nsINode* GetScopeChainParent() const MOZ_OVERRIDE
+    {
+        Element* parent = GetParentElement();
+        return parent ? parent : nsStyledElement::GetScopeChainParent();
+    }
+
 protected:
     ~nsXULElement();
 
     // This can be removed if EnsureContentsGenerated dies.
     friend class nsNSElementTearoff;
 
     // Implementation methods
     nsresult EnsureContentsGenerated(void) const;