Backing out bug 372769 due to leaks.
authorbzbarsky@mit.edu
Wed, 26 Sep 2007 07:39:31 -0700
changeset 6330 e4ddc08d0887d3194dfdb99759a1023c3b23f27d
parent 6329 a65cbc7b8a591c5c2a88ef0846976f7ed020e100
child 6331 1f2e9546c21c190ccfbd29719d3211f4cdaf2a37
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs372769
milestone1.9a9pre
Backing out bug 372769 due to leaks.
content/xbl/src/Makefile.in
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLBinding.h
content/xbl/src/nsXBLContentSink.cpp
content/xbl/src/nsXBLContentSink.h
content/xbl/src/nsXBLProtoImpl.cpp
content/xbl/src/nsXBLProtoImpl.h
content/xbl/src/nsXBLProtoImplField.cpp
content/xbl/src/nsXBLProtoImplField.h
content/xbl/src/nsXBLPrototypeBinding.cpp
content/xbl/src/nsXBLPrototypeBinding.h
content/xbl/test/Makefile.in
dom/src/base/nsDOMClassInfo.cpp
dom/src/base/nsDOMClassInfo.h
--- a/content/xbl/src/Makefile.in
+++ b/content/xbl/src/Makefile.in
@@ -106,12 +106,11 @@ LOCAL_INCLUDES	= \
 		-I$(srcdir)/../../base/src \
 		-I$(srcdir)/../../html/base/src \
 		-I$(srcdir)/../../html/document/src \
 		-I$(srcdir)/../../xml/document/src \
 		-I$(srcdir)/../../xul/content/src \
 		-I$(srcdir)/../../xul/document/src \
 		-I$(srcdir)/../../events/src \
 		-I$(srcdir)/../../../layout/style \
-		-I$(srcdir)/../../../dom/src/base \
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -97,137 +97,37 @@
 #include "nsIPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIEventListenerManager.h"
 #include "nsGUIEvent.h"
 
 #include "prprf.h"
 #include "nsNodeUtils.h"
 
-// Nasty hack.  Maybe we could move some of the classinfo utility methods
-// (e.g. WrapNative and ThrowJSException) over to nsContentUtils?
-#include "nsDOMClassInfo.h"
-#include "nsJSUtils.h"
-
 // Helper classes
 
 /***********************************************************************/
 //
 // The JS class for XBLBinding
 //
-JS_STATIC_DLL_CALLBACK(void)
+PR_STATIC_CALLBACK(void)
 XBLFinalize(JSContext *cx, JSObject *obj)
 {
-  nsXBLPrototypeBinding* protoBinding =
-    static_cast<nsXBLPrototypeBinding*>(::JS_GetPrivate(cx, obj));
-  protoBinding->XBLDocumentInfo()->Release();
-  
   nsXBLJSClass* c = static_cast<nsXBLJSClass*>(::JS_GetClass(cx, obj));
   c->Drop();
 }
 
-JS_STATIC_DLL_CALLBACK(JSBool)
-XBLResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
-           JSObject **objp)
-{
-  // Note: if we get here, that means that the implementation for some binding
-  // was installed, which means that AllowScripts() tested true.  Hence no need
-  // to do checks like that here.
-  
-  // Default to not resolving things.
-  NS_ASSERTION(*objp, "Must have starting object");
-
-  JSObject* origObj = *objp;
-  *objp = NULL;
-
-  if (!JSVAL_IS_STRING(id)) {
-    return JS_TRUE;
-  }
-
-  nsDependentJSString fieldName(id);
-                     
-  nsXBLPrototypeBinding* protoBinding =
-    static_cast<nsXBLPrototypeBinding*>(::JS_GetPrivate(cx, obj));
-  NS_ASSERTION(protoBinding, "Must have prototype binding!");
-
-  nsXBLProtoImplField* field = protoBinding->FindField(fieldName);
-  if (!field) {
-    return JS_TRUE;
-  }
-
-  // We have this field.  Time to install it.  Get our node.
-  JSClass* nodeClass = ::JS_GetClass(cx, origObj);
-  if (!nodeClass) {
-    return JS_FALSE;
-  }
-  
-  if (~nodeClass->flags &
-      (JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS)) {
-    // Looks like whatever |origObj| is it's not our nsIContent.  It might well
-    // be the proto our binding installed, however, so just baul out quietly.
-    // Do NOT throw an exception here.
-    // We could make this stricter by checking the class maybe, but whatever
-    return JS_TRUE;
-  }
-
-  nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
-    do_QueryInterface(static_cast<nsISupports*>(::JS_GetPrivate(cx, origObj)));
-  if (!xpcWrapper) {
-    nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
-    return JS_FALSE;
-  }
-
-  nsCOMPtr<nsIContent> content = do_QueryWrappedNative(xpcWrapper);
-  if (!content) {
-    nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_UNEXPECTED);
-    return JS_FALSE;
-  }
-
-  // This mirrors code in nsXBLProtoImpl::InstallImplementation
-  nsIDocument* doc = content->GetOwnerDoc();
-  if (!doc) {
-    return JS_TRUE;
-  }
-
-  nsIScriptGlobalObject* global = doc->GetScriptGlobalObject();
-  if (!global) {
-    return JS_TRUE;
-  }
-
-  nsCOMPtr<nsIScriptContext> context = global->GetContext();
-  if (!context) {
-    return JS_TRUE;
-  }
-
-
-  // Now we either resolve or fail
-  *objp = origObj;
-  nsresult rv = field->InstallField(context, origObj,
-                                    protoBinding->DocURI());
-  if (NS_FAILED(rv)) {
-    if (!::JS_IsExceptionPending(cx)) {
-      nsDOMClassInfo::ThrowJSException(cx, rv);
-    }
-
-    return JS_FALSE;
-  }
-
-  return JS_TRUE;
-}
-
 nsXBLJSClass::nsXBLJSClass(const nsAFlatCString& aClassName)
 {
   memset(this, 0, sizeof(nsXBLJSClass));
   next = prev = static_cast<JSCList*>(this);
   name = ToNewCString(aClassName);
-  flags =
-    JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_RESOLVE_GETS_START;
   addProperty = delProperty = setProperty = getProperty = ::JS_PropertyStub;
   enumerate = ::JS_EnumerateStub;
-  resolve = (JSResolveOp)XBLResolve;
+  resolve = ::JS_ResolveStub;
   convert = ::JS_ConvertStub;
   finalize = XBLFinalize;
 }
 
 nsrefcnt
 nsXBLJSClass::Destroy()
 {
   NS_ASSERTION(next == prev && prev == static_cast<JSCList*>(this),
@@ -1129,17 +1029,16 @@ nsXBLBinding::WalkRules(nsIStyleRuleProc
 }
 
 // Internal helper methods ////////////////////////////////////////////////////////////////
 
 // static
 nsresult
 nsXBLBinding::DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
                             const nsAFlatCString& aClassName,
-                            nsXBLPrototypeBinding* aProtoBinding,
                             void **aClassObject)
 {
   // First ensure our JS class is initialized.
   jsval val;
   JSObject* proto;
 
   nsCAutoString className(aClassName);
   JSObject* parent_proto = nsnull;  // If we have an "obj" we can set this
@@ -1235,37 +1134,89 @@ nsXBLBinding::DoInitJSClass(JSContext *c
 
       (nsXBLService::gClassTable)->Remove(&key);
 
       c->Drop();
 
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    ::JS_SetPrivate(cx, proto, aProtoBinding);
-
-    // Keep this proto binding alive while we're alive
-    aProtoBinding->XBLDocumentInfo()->AddRef();
-
     *aClassObject = (void*)proto;
   }
   else {
     proto = JSVAL_TO_OBJECT(val);
   }
 
   if (obj) {
     // Set the prototype of our object to be the new class.
     if (!::JS_SetPrototype(cx, obj, proto)) {
       return NS_ERROR_FAILURE;
     }
   }
 
   return NS_OK;
 }
 
+
+nsresult
+nsXBLBinding::InitClass(const nsCString& aClassName,
+                        nsIScriptContext* aContext, 
+                        nsIDocument* aDocument, void** aScriptObject,
+                        void** aClassObject)
+{
+  *aClassObject = nsnull;
+  *aScriptObject = nsnull;
+
+  nsresult rv;
+
+  // Obtain the bound element's current script object.
+  JSContext* cx = (JSContext*)aContext->GetNativeContext();
+
+  nsIDocument *ownerDoc = mBoundElement->GetOwnerDoc();
+  nsIScriptGlobalObject *sgo;
+
+  if (!ownerDoc || !(sgo = ownerDoc->GetScriptGlobalObject())) {
+    NS_ERROR("Can't find global object for bound content!");
+
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
+  rv = nsContentUtils::XPConnect()->WrapNative(cx, sgo->GetGlobalJSObject(),
+                                               mBoundElement,
+                                               NS_GET_IID(nsISupports),
+                                               getter_AddRefs(wrapper));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  JSObject* object = nsnull;
+  rv = wrapper->GetJSObject(&object);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *aScriptObject = object;
+
+  // First ensure our JS class is initialized.
+
+  rv = DoInitJSClass(cx, sgo->GetGlobalJSObject(), object, aClassName,
+                     aClassObject);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Root mBoundElement so that it doesn't lose it's binding
+  nsIDocument* doc = mBoundElement->GetOwnerDoc();
+
+  if (doc) {
+    nsCOMPtr<nsIXPConnectWrappedNative> native_wrapper =
+      do_QueryInterface(wrapper);
+    if (native_wrapper) {
+      doc->AddReference(mBoundElement, native_wrapper);
+    }
+  }
+
+  return NS_OK;
+}
+
 PRBool
 nsXBLBinding::AllowScripts()
 {
   PRBool result;
   mPrototypeBinding->GetAllowScripts(&result);
   if (!result) {
     return result;
   }
@@ -1388,30 +1339,16 @@ nsXBLBinding*
 nsXBLBinding::GetFirstStyleBinding()
 {
   if (mIsStyleBinding)
     return this;
 
   return mNextBinding ? mNextBinding->GetFirstStyleBinding() : nsnull;
 }
 
-PRBool
-nsXBLBinding::ResolveAllFields(JSContext *cx, JSObject *obj) const
-{
-  if (!mPrototypeBinding->ResolveAllFields(cx, obj)) {
-    return PR_FALSE;
-  }
-
-  if (mNextBinding) {
-    return mNextBinding->ResolveAllFields(cx, obj);
-  }
-
-  return PR_TRUE;
-}
-
 void
 nsXBLBinding::MarkForDeath()
 {
   mMarkedForDeath = PR_TRUE;
   ExecuteDetachedHandler();
 }
 
 PRBool
--- a/content/xbl/src/nsXBLBinding.h
+++ b/content/xbl/src/nsXBLBinding.h
@@ -127,20 +127,16 @@ public:
   void ExecuteDetachedHandler();
   void UnhookEventHandlers();
 
   nsIAtom* GetBaseTag(PRInt32* aNameSpaceID);
   nsXBLBinding* GetFirstBindingWithConstructor();
   nsXBLBinding* RootBinding();
   nsXBLBinding* GetFirstStyleBinding();
 
-  // Resolve all the fields for this binding and all ancestor bindings on the
-  // object |obj|.  False return means a JS exception was set.
-  PRBool ResolveAllFields(JSContext *cx, JSObject *obj) const;
-
   // Get the list of insertion points for aParent. The nsInsertionPointList
   // is owned by the binding, you should not delete it.
   nsresult GetInsertionPointsFor(nsIContent* aParent,
                                  nsInsertionPointList** aResult);
 
   nsInsertionPointList* GetExistingInsertionPointsFor(nsIContent* aParent);
 
   nsIContent* GetInsertionPoint(nsIContent* aChild, PRUint32* aIndex);
@@ -154,21 +150,26 @@ public:
   void ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument);
 
   void WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, void* aData);
 
   already_AddRefed<nsIDOMNodeList> GetAnonymousNodes();
 
   static nsresult DoInitJSClass(JSContext *cx, JSObject *global, JSObject *obj,
                                 const nsAFlatCString& aClassName,
-                                nsXBLPrototypeBinding* aProtoBinding,
                                 void **aClassObject);
 
   PRBool AllowScripts();  // XXX make const
 
+// Internal member functions
+protected:
+  nsresult InitClass(const nsCString& aClassName, nsIScriptContext* aContext,
+                     nsIDocument* aDocument, void** aScriptObject,
+                     void** aClassObject);
+
 // MEMBER VARIABLES
 protected:
   nsAutoRefCnt mRefCnt;
   nsXBLPrototypeBinding* mPrototypeBinding; // Weak, but we're holding a ref to the docinfo
   nsCOMPtr<nsIContent> mContent; // Strong. Our anonymous content stays around with us.
   nsRefPtr<nsXBLBinding> mNextBinding; // Strong. The derived binding owns the base class bindings.
   
   nsIContent* mBoundElement; // [WEAK] We have a reference, but we don't own it.
--- a/content/xbl/src/nsXBLContentSink.cpp
+++ b/content/xbl/src/nsXBLContentSink.cpp
@@ -78,23 +78,22 @@ NS_NewXBLContentSink(nsIXMLContentSink**
 
   return CallQueryInterface(it, aResult);
 }
 
 nsXBLContentSink::nsXBLContentSink()
   : mState(eXBL_InDocument),
     mSecondaryState(eXBL_None),
     mDocInfo(nsnull),
+    mFoundFirstBinding(PR_FALSE),    
     mIsChromeOrResource(PR_FALSE),
-    mFoundFirstBinding(PR_FALSE),    
     mBinding(nsnull),
     mHandler(nsnull),
     mImplementation(nsnull),
     mImplMember(nsnull),
-    mImplField(nsnull),
     mProperty(nsnull),
     mMethod(nsnull),
     mField(nsnull)
 {
   mPrettyPrintXML = PR_FALSE;
 }
 
 nsXBLContentSink::~nsXBLContentSink()
@@ -259,28 +258,16 @@ nsXBLContentSink::AddMember(nsXBLProtoIm
   if (mImplMember)
     mImplMember->SetNext(aMember); // Already have a chain. Just append to the end.
   else
     mImplementation->SetMemberList(aMember); // We're the first member in the chain.
 
   mImplMember = aMember; // Adjust our pointer to point to the new last member in the chain.
 }
 
-void
-nsXBLContentSink::AddField(nsXBLProtoImplField* aField)
-{
-  // Add this field to our chain.
-  if (mImplField)
-    mImplField->SetNext(aField); // Already have a chain. Just append to the end.
-  else
-    mImplementation->SetFieldList(aField); // We're the first member in the chain.
-
-  mImplField = aField; // Adjust our pointer to point to the new last field in the chain.
-}
-
 NS_IMETHODIMP 
 nsXBLContentSink::HandleStartElement(const PRUnichar *aName, 
                                      const PRUnichar **aAtts, 
                                      PRUint32 aAttsCount, 
                                      PRInt32 aIndex, 
                                      PRUint32 aLineNumber)
 {
   nsresult rv = nsXMLContentSink::HandleStartElement(aName,aAtts,aAttsCount,aIndex,aLineNumber);
@@ -711,18 +698,17 @@ nsXBLContentSink::ConstructResource(cons
   }
 }
 
 void
 nsXBLContentSink::ConstructImplementation(const PRUnichar **aAtts)
 {
   mImplementation = nsnull;
   mImplMember = nsnull;
-  mImplField = nsnull;
-  
+      
   if (!mBinding)
     return;
 
   const PRUnichar* name = nsnull;
 
   nsCOMPtr<nsIAtom> prefix, localName;
   for (; *aAtts; aAtts += 2) {
     PRInt32 nameSpaceID;
@@ -786,17 +772,17 @@ nsXBLContentSink::ConstructField(const P
   }
 
   if (name) {
     // All of our pointers are now filled in. Construct our field with all of
     // these parameters.
     mField = new nsXBLProtoImplField(name, readonly);
     if (mField) {
       mField->SetLineNumber(aLineNumber);
-      AddField(mField);
+      AddMember(mField);
     }
   }
 }
 
 void
 nsXBLContentSink::ConstructProperty(const PRUnichar **aAtts)
 {
   const PRUnichar* name     = nsnull;
--- a/content/xbl/src/nsXBLContentSink.h
+++ b/content/xbl/src/nsXBLContentSink.h
@@ -152,29 +152,27 @@ protected:
                          const PRUnichar* aSourceText,
                          nsIScriptError *aError,
                          PRBool *_retval);
 
 protected:
   nsresult ReportUnexpectedElement(nsIAtom* aElementName, PRUint32 aLineNumber);
 
   void AddMember(nsXBLProtoImplMember* aMember);
-  void AddField(nsXBLProtoImplField* aField);
   
   XBLPrimaryState mState;
   XBLSecondaryState mSecondaryState;
   nsIXBLDocumentInfo* mDocInfo;
   PRPackedBool mIsChromeOrResource; // For bug #45989
   PRPackedBool mFoundFirstBinding;
 
   nsXBLPrototypeBinding* mBinding;
   nsXBLPrototypeHandler* mHandler; // current handler, owned by its PrototypeBinding
   nsXBLProtoImpl* mImplementation;
   nsXBLProtoImplMember* mImplMember;
-  nsXBLProtoImplField* mImplField;
   nsXBLProtoImplProperty* mProperty;
   nsXBLProtoImplMethod* mMethod;
   nsXBLProtoImplField* mField;
 };
 
 nsresult
 NS_NewXBLContentSink(nsIXMLContentSink** aResult,
                      nsIDocument* aDoc,
--- a/content/xbl/src/nsXBLProtoImpl.cpp
+++ b/content/xbl/src/nsXBLProtoImpl.cpp
@@ -42,26 +42,25 @@
 #include "nsContentUtils.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptGlobalObjectOwner.h"
 #include "nsIScriptContext.h"
 #include "nsIXPConnect.h"
 #include "nsIServiceManager.h"
 #include "nsIXBLDocumentInfo.h"
 #include "nsIDOMNode.h"
-#include "nsXBLPrototypeBinding.h"
 
 nsresult
 nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding* aBinding, nsIContent* aBoundElement)
 {
   // This function is called to install a concrete implementation on a bound element using
   // this prototype implementation as a guide.  The prototype implementation is compiled lazily,
   // so for the first bound element that needs a concrete implementation, we also build the
   // prototype implementation.
-  if (!mMembers && !mFields)  // Constructor and destructor also live in mMembers
+  if (!mMembers)  // Constructor and destructor also live in mMembers
     return NS_OK; // Nothing to do, so let's not waste time.
 
   // If the way this gets the script context changes, fix
   // nsXBLProtoImplAnonymousMethod::Execute
   nsIDocument* document = aBoundElement->GetOwnerDoc();
   if (!document) return NS_OK;
 
   nsIScriptGlobalObject *global = document->GetScriptGlobalObject();
@@ -210,47 +209,16 @@ nsXBLProtoImpl::Traverse(nsCycleCollecti
   }
 
   nsXBLProtoImplMember *member;
   for (member = mMembers; member; member = member->GetNext()) {
     member->Traverse(cb);
   }
 }
 
-nsXBLProtoImplField*
-nsXBLProtoImpl::FindField(const nsString& aFieldName) const
-{
-  for (nsXBLProtoImplField* f = mFields; f; f = f->GetNext()) {
-    if (aFieldName.Equals(f->GetName())) {
-      return f;
-    }
-  }
-
-  return nsnull;
-}
-
-PRBool
-nsXBLProtoImpl::ResolveAllFields(JSContext *cx, JSObject *obj) const
-{
-  for (nsXBLProtoImplField* f = mFields; f; f = f->GetNext()) {
-    // Using OBJ_LOOKUP_PROPERTY is a pain, since what we have is a
-    // PRUnichar* for the property name.  Let's just use the public API and
-    // all.
-    nsDependentString name(f->GetName());
-    jsval dummy;
-    if (!::JS_LookupUCProperty(cx, obj,
-                               reinterpret_cast<const jschar*>(name.get()),
-                               name.Length(), &dummy)) {
-      return PR_FALSE;
-    }
-  }
-
-  return PR_TRUE;
-}
-
 void
 nsXBLProtoImpl::DestroyMembers(nsXBLProtoImplMember* aBrokenMember)
 {
   NS_ASSERTION(mClassObject, "This should never be called when there is no class object");
   PRBool compiled = PR_TRUE;
   for (nsXBLProtoImplMember* curr = mMembers; curr; curr = curr->GetNext()) {
     if (curr == aBrokenMember) {
       compiled = PR_FALSE;
--- a/content/xbl/src/nsXBLProtoImpl.h
+++ b/content/xbl/src/nsXBLProtoImpl.h
@@ -37,89 +37,67 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsXBLProtoImpl_h__
 #define nsXBLProtoImpl_h__
 
 #include "nsMemory.h"
 #include "nsXBLPrototypeHandler.h"
 #include "nsXBLProtoImplMember.h"
-#include "nsXBLProtoImplField.h"
+#include "nsXBLPrototypeBinding.h"
 
 class nsIXPConnectJSObjectHolder;
-class nsXBLPrototypeBinding;
-class nsXBLProtoImplAnonymousMethod;
 
 class nsXBLProtoImpl
 {
 public:
   nsXBLProtoImpl() 
     : mClassObject(nsnull),
       mMembers(nsnull),
-      mFields(nsnull),
       mConstructor(nsnull),
       mDestructor(nsnull)
   { 
     MOZ_COUNT_CTOR(nsXBLProtoImpl); 
   }
   ~nsXBLProtoImpl() 
   { 
     MOZ_COUNT_DTOR(nsXBLProtoImpl);
     // Note: the constructor and destructor are in mMembers, so we'll
     // clean them up automatically.
     for (nsXBLProtoImplMember* curr = mMembers; curr; curr=curr->GetNext())
       curr->Destroy(mClassObject != nsnull);
-    delete mMembers;
-    delete mFields;
+    delete mMembers; 
   }
   
   nsresult InstallImplementation(nsXBLPrototypeBinding* aBinding, nsIContent* aBoundElement);
   nsresult InitTargetObjects(nsXBLPrototypeBinding* aBinding, nsIScriptContext* aContext, 
                              nsIContent* aBoundElement, 
                              nsIXPConnectJSObjectHolder** aScriptObjectHolder,
                              void** aTargetClassObject);
   nsresult CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding);
 
-  void SetMemberList(nsXBLProtoImplMember* aMemberList)
-  {
-    delete mMembers;
-    mMembers = aMemberList;
-  }
-
-  void SetFieldList(nsXBLProtoImplField* aFieldList)
-  {
-    delete mFields;
-    mFields = aFieldList;
-  }
+  void SetMemberList(nsXBLProtoImplMember* aMemberList) { delete mMembers; mMembers = aMemberList; }
 
   void Traverse(nsCycleCollectionTraversalCallback &cb) const;
 
-  nsXBLProtoImplField* FindField(const nsString& aFieldName) const;
-
-  // Resolve all the fields for this implementation on the object |obj| False
-  // return means a JS exception was set.
-  PRBool ResolveAllFields(JSContext *cx, JSObject *obj) const;
-
 protected:
   // Function to call if compilation of a member fails.  When this is called,
   // all members before aBrokenMember are compiled, compilation of
   // aBrokenMember failed, and members after aBrokenMember are uncompiled.
   // This function assumes that aBrokenMember is _not_ compiled.
   void DestroyMembers(nsXBLProtoImplMember* aBrokenMember);
   
 public:
   nsCString mClassName; // The name of the class. 
 
 protected:
   void* mClassObject;   // The class object for the binding. We'll use this to pre-compile properties 
                         // and methods for the binding.
 
   nsXBLProtoImplMember* mMembers; // The members of an implementation are chained in this singly-linked list.
-
-  nsXBLProtoImplField* mFields; // Our fields
   
 public:
   nsXBLProtoImplAnonymousMethod* mConstructor; // Our class constructor.
   nsXBLProtoImplAnonymousMethod* mDestructor;  // Our class destructor.
 };
 
 nsresult
 NS_NewXBLProtoImpl(nsXBLPrototypeBinding* aBinding, 
--- a/content/xbl/src/nsXBLProtoImplField.cpp
+++ b/content/xbl/src/nsXBLProtoImplField.cpp
@@ -41,42 +41,42 @@
 #include "jsapi.h"
 #include "nsIContent.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsReadableUtils.h"
 #include "nsXBLProtoImplField.h"
 #include "nsIScriptContext.h"
 #include "nsContentUtils.h"
-#include "nsIURI.h"
 
 nsXBLProtoImplField::nsXBLProtoImplField(const PRUnichar* aName, const PRUnichar* aReadOnly)
-  : mNext(nsnull),
+  : nsXBLProtoImplMember(aName),
     mFieldText(nsnull),
     mFieldTextLength(0),
     mLineNumber(0)
 {
   MOZ_COUNT_CTOR(nsXBLProtoImplField);
-  mName = NS_strdup(aName);  // XXXbz make more sense to use a stringbuffer?
-  
   mJSAttributes = JSPROP_ENUMERATE;
   if (aReadOnly) {
     nsAutoString readOnly; readOnly.Assign(*aReadOnly);
     if (readOnly.LowerCaseEqualsLiteral("true"))
       mJSAttributes |= JSPROP_READONLY;
   }
 }
 
 nsXBLProtoImplField::~nsXBLProtoImplField()
 {
   MOZ_COUNT_DTOR(nsXBLProtoImplField);
   if (mFieldText)
     nsMemory::Free(mFieldText);
-  NS_Free(mName);
-  delete mNext;
+}
+
+void
+nsXBLProtoImplField::Destroy(PRBool aIsCompiled)
+{
 }
 
 void 
 nsXBLProtoImplField::AppendFieldText(const nsAString& aText)
 {
   if (mFieldText) {
     nsDependentString fieldTextStr(mFieldText, mFieldTextLength);
     nsAutoString newFieldText = fieldTextStr + aText;
@@ -87,61 +87,72 @@ nsXBLProtoImplField::AppendFieldText(con
   }
   else {
     mFieldText = ToNewUnicode(aText);
     mFieldTextLength = aText.Length();
   }
 }
 
 nsresult
-nsXBLProtoImplField::InstallField(nsIScriptContext* aContext,
-                                  JSObject* aBoundNode,
-                                  nsIURI* aBindingDocURI) const
+nsXBLProtoImplField::InstallMember(nsIScriptContext* aContext,
+                                   nsIContent* aBoundElement, 
+                                   void* aScriptObject,
+                                   void* aTargetClassObject,
+                                   const nsCString& aClassStr)
 {
-  NS_PRECONDITION(aBoundNode,
-                  "uh-oh, bound node should NOT be null or bad things will "
-                  "happen");
+  if (mFieldTextLength == 0)
+    return NS_OK; // nothing to do.
+
+  JSContext* cx = (JSContext*) aContext->GetNativeContext();
+  NS_ASSERTION(aScriptObject, "uh-oh, script Object should NOT be null or bad things will happen");
+  if (!aScriptObject)
+    return NS_ERROR_FAILURE;
 
-  jsval result = JSVAL_VOID;
+  nsCAutoString bindingURI(aClassStr);
+  PRInt32 hash = bindingURI.RFindChar('#');
+  if (hash != kNotFound)
+    bindingURI.Truncate(hash);
+  
+  // compile the literal string 
+  jsval result = JSVAL_NULL;
   
   // EvaluateStringWithValue and JS_DefineUCProperty can both trigger GC, so
   // protect |result| here.
   nsresult rv;
   nsAutoGCRoot root(&result, &rv);
   if (NS_FAILED(rv))
     return rv;
+  PRBool undefined;
+  // XXX Need a URI here!
+  nsCOMPtr<nsIScriptContext> context = aContext;
+  rv = context->EvaluateStringWithValue(nsDependentString(mFieldText,
+                                                          mFieldTextLength), 
+                                        aScriptObject,
+                                        nsnull, bindingURI.get(),
+                                        mLineNumber, nsnull,
+                                        (void*) &result, &undefined);
+  if (NS_FAILED(rv))
+    return rv;
 
-  if (mFieldTextLength != 0) {
-    nsCAutoString uriSpec;
-    aBindingDocURI->GetSpec(uriSpec);
-  
-    // compile the literal string
-    // XXX Could we produce a better principal here?  Should be able
-    // to, really!
-    PRBool undefined;
-    nsCOMPtr<nsIScriptContext> context = aContext;
-    rv = context->EvaluateStringWithValue(nsDependentString(mFieldText,
-                                                            mFieldTextLength), 
-                                          aBoundNode,
-                                          nsnull, uriSpec.get(),
-                                          mLineNumber, nsnull,
-                                          (void*) &result, &undefined);
-    if (NS_FAILED(rv))
-      return rv;
-
-    if (undefined) {
-      result = JSVAL_VOID;
-    }
-  }
-
-  // Define the evaluated result as a JS property
-  nsDependentString name(mName);
-  JSContext* cx = (JSContext*) aContext->GetNativeContext();
-  JSAutoRequest ar(cx);
-  if (!::JS_DefineUCProperty(cx, aBoundNode,
-                             reinterpret_cast<const jschar*>(mName), 
-                             name.Length(), result, nsnull, nsnull,
-                             mJSAttributes)) {
-    return NS_ERROR_OUT_OF_MEMORY;
+  if (!undefined) {
+    // Define the evaluated result as a JS property
+    nsDependentString name(mName);
+    JSAutoRequest ar(cx);
+    if (!::JS_DefineUCProperty(cx, static_cast<JSObject *>(aScriptObject),
+                               reinterpret_cast<const jschar*>(mName), 
+                               name.Length(), result, nsnull, nsnull, mJSAttributes))
+      return NS_ERROR_OUT_OF_MEMORY;
   }
   
   return NS_OK;
 }
+
+nsresult 
+nsXBLProtoImplField::CompileMember(nsIScriptContext* aContext, const nsCString& aClassStr,
+                                   void* aClassObject)
+{
+  return NS_OK;
+}
+
+void
+nsXBLProtoImplField::Traverse(nsCycleCollectionTraversalCallback &cb) const
+{
+}
--- a/content/xbl/src/nsXBLProtoImplField.h
+++ b/content/xbl/src/nsXBLProtoImplField.h
@@ -41,40 +41,39 @@
 
 #include "nsIAtom.h"
 #include "nsString.h"
 #include "jsapi.h"
 #include "nsIContent.h"
 #include "nsString.h"
 #include "nsXBLProtoImplMember.h"
 
-class nsIURI;
-
-class nsXBLProtoImplField
+class nsXBLProtoImplField: public nsXBLProtoImplMember
 {
 public:
   nsXBLProtoImplField(const PRUnichar* aName, const PRUnichar* aReadOnly);
-  ~nsXBLProtoImplField();
+  virtual ~nsXBLProtoImplField();
+  virtual void Destroy(PRBool aIsCompiled);
 
   void AppendFieldText(const nsAString& aText);
   void SetLineNumber(PRUint32 aLineNumber) {
     mLineNumber = aLineNumber;
   }
   
-  nsXBLProtoImplField* GetNext() const { return mNext; }
-  void SetNext(nsXBLProtoImplField* aNext) { mNext = aNext; }
+  virtual nsresult InstallMember(nsIScriptContext* aContext,
+                                 nsIContent* aBoundElement, 
+                                 void* aScriptObject,
+                                 void* aTargetClassObject,
+                                 const nsCString& aClassStr);
+  virtual nsresult CompileMember(nsIScriptContext* aContext,
+                                 const nsCString& aClassStr,
+                                 void* aClassObject);
 
-  nsresult InstallField(nsIScriptContext* aContext,
-                        JSObject* aBoundNode, nsIURI*
-                        aBindingDocURI) const;
-
-  const PRUnichar* GetName() const { return mName; }
+  virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const;
 
 protected:
-  nsXBLProtoImplField* mNext;
-  PRUnichar* mName;
   PRUnichar* mFieldText;
   PRUint32 mFieldTextLength;
   PRUint32 mLineNumber;
   uintN mJSAttributes;
 };
 
 #endif // nsXBLProtoImplField_h__
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -817,17 +817,17 @@ nsXBLPrototypeBinding::InitClass(const n
                                  JSObject * aScriptObject,
                                  void ** aClassObject)
 {
   NS_ENSURE_ARG_POINTER(aClassObject); 
 
   *aClassObject = nsnull;
 
   return nsXBLBinding::DoInitJSClass(aContext, aGlobal, aScriptObject,
-                                     aClassName, this, aClassObject);
+                                     aClassName, aClassObject);
 }
 
 nsIContent*
 nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement,
                                       nsIContent* aTemplRoot,
                                       nsIContent* aCopyRoot, 
                                       nsIContent* aTemplChild)
 {
--- a/content/xbl/src/nsXBLPrototypeBinding.h
+++ b/content/xbl/src/nsXBLPrototypeBinding.h
@@ -45,26 +45,25 @@
 #include "nsXBLProtoImplMethod.h"
 #include "nsICSSStyleSheet.h"
 #include "nsICSSLoaderObserver.h"
 #include "nsWeakReference.h"
 #include "nsIContent.h"
 #include "nsHashtable.h"
 #include "nsIXBLDocumentInfo.h"
 #include "nsCOMArray.h"
-#include "nsXBLProtoImpl.h"
 
 class nsIAtom;
 class nsIDocument;
 class nsIScriptContext;
 class nsISupportsArray;
 class nsSupportsHashtable;
 class nsIXBLService;
 class nsFixedSizeAllocator;
-class nsXBLProtoImplField;
+class nsXBLProtoImpl;
 class nsXBLBinding;
 
 // *********************************************************************/
 // The XBLPrototypeBinding class
 
 // Instances of this class are owned by the nsXBLDocumentInfo object returned
 // by XBLDocumentInfo().  Consumers who want to refcount things should refcount
 // that.
@@ -90,32 +89,16 @@ public:
   nsXBLPrototypeHandler* GetPrototypeHandlers() { return mPrototypeHandler; }
   void SetPrototypeHandlers(nsXBLPrototypeHandler* aHandler) { mPrototypeHandler = aHandler; }
 
   nsXBLProtoImplAnonymousMethod* GetConstructor();
   nsresult SetConstructor(nsXBLProtoImplAnonymousMethod* aConstructor);
   nsXBLProtoImplAnonymousMethod* GetDestructor();
   nsresult SetDestructor(nsXBLProtoImplAnonymousMethod* aDestructor);
 
-  nsXBLProtoImplField* FindField(const nsString& aFieldName) const
-  {
-    return mImplementation ? mImplementation->FindField(aFieldName) : nsnull;
-  }
-
-  // Resolve all the fields for this binding on the object |obj|.
-  // False return means a JS exception was set.
-  PRBool ResolveAllFields(JSContext* cx, JSObject* obj) const
-  {
-    return !mImplementation || mImplementation->ResolveAllFields(cx, obj);
-  }
-
-  const nsCString& ClassName() const {
-    return mImplementation ? mImplementation->mClassName : EmptyCString();
-  }
-
   nsresult InitClass(const nsCString& aClassName, JSContext * aContext,
                      JSObject * aGlobal, JSObject * aScriptObject,
                      void ** aClassObject);
 
   nsresult ConstructInterfaceTable(const nsAString& aImpls);
   
   void SetImplementation(nsXBLProtoImpl* aImpl) { mImplementation = aImpl; }
   nsresult InstallImplementation(nsIContent* aBoundElement);
--- a/content/xbl/test/Makefile.in
+++ b/content/xbl/test/Makefile.in
@@ -45,13 +45,12 @@ relativesrcdir  = content/xbl/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =	\
 		test_bug296375.xul \
 		test_bug366770.html \
 		test_bug371724.xhtml \
-		test_bug372769.xhtml \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -472,18 +472,17 @@ static const char kDOMStringBundleURL[] 
   ~nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY)
 
 // We need to let JavaScript QI elements to interfaces that are not in
 // the classinfo since XBL can be used to dynamically implement new
 // unknown interfaces on elements, accessibility relies on this being
 // possible.
 
 #define ELEMENT_SCRIPTABLE_FLAGS                                              \
-  ((NODE_SCRIPTABLE_FLAGS & ~nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY) |   \
-   nsIXPCScriptable::WANT_ENUMERATE)
+  (NODE_SCRIPTABLE_FLAGS & ~nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
 
 #define EXTERNAL_OBJ_SCRIPTABLE_FLAGS                                         \
   (ELEMENT_SCRIPTABLE_FLAGS & ~nsIXPCScriptable::USE_JSSTUB_FOR_SETPROPERTY | \
    nsIXPCScriptable::WANT_GETPROPERTY |                                       \
    nsIXPCScriptable::WANT_SETPROPERTY |                                       \
    nsIXPCScriptable::WANT_CALL)
 
 #define DOCUMENT_SCRIPTABLE_FLAGS                                             \
@@ -6936,42 +6935,16 @@ nsElementSH::PostCreate(nsIXPConnectWrap
   
   if (binding) {
     binding->ExecuteAttachedHandler();
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsElementSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                       JSObject *obj, PRBool *_retval)
-{
-  // Make sure to not call the superclass here!
-  nsCOMPtr<nsIContent> content(do_QueryWrappedNative(wrapper));
-  NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED);
-
-  nsIDocument* doc = content->GetOwnerDoc();
-  if (!doc) {
-    // Nothing else to do here
-    return NS_OK;
-  }
-
-  nsXBLBinding* binding = doc->BindingManager()->GetBinding(content);
-  if (!binding) {
-    // Nothing else to do here
-    return NS_OK;
-  }
-
-  *_retval = binding->ResolveAllFields(cx, obj);
-  
-  return NS_OK;
-}
-  
-
 // Generic array scriptable helper.
 
 NS_IMETHODIMP
 nsGenericArraySH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                              JSObject *obj, jsval id, PRUint32 flags,
                              JSObject **objp, PRBool *_retval)
 {
   PRBool is_number = PR_FALSE;
--- a/dom/src/base/nsDOMClassInfo.h
+++ b/dom/src/base/nsDOMClassInfo.h
@@ -558,18 +558,16 @@ protected:
 
   virtual ~nsElementSH()
   {
   }
 
 public:
   NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj);
-  NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
-                       JSObject *obj, PRBool *_retval);
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsElementSH(aData);
   }
 };