From 2375b7e89a67607b77f46be9bab202239f5a10e5 Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Wed, 29 Jun 2011 19:17:37 +0200 Subject: [PATCH] Bug 648801 (new DOM list bindings) - Add a pref (dom.new_bindings) to enable/disable new bindings. r=bz/jst/mrbkap. --HG-- extra : rebase_source : 055a7bdac534147baa29d8735794970234c98145 --- content/base/src/nsContentList.cpp | 10 +++--- content/base/src/nsContentList.h | 9 ++++-- content/base/src/nsGenericElement.cpp | 5 +-- content/base/src/nsGenericElement.h | 3 +- .../html/content/src/nsHTMLFormElement.cpp | 5 +-- .../html/content/src/nsHTMLTableElement.cpp | 5 +-- content/xbl/src/nsBindingManager.cpp | 5 +-- dom/base/nsDOMClassInfo.cpp | 6 ++-- dom/base/nsWrapperCache.h | 13 ++++++-- js/src/xpconnect/src/dombindings.cpp | 32 +++++++++++++------ js/src/xpconnect/src/dombindings.h | 8 ++--- js/src/xpconnect/src/xpcconvert.cpp | 16 +++++++--- js/src/xpconnect/src/xpcjsruntime.cpp | 6 ++++ js/src/xpconnect/src/xpcprivate.h | 14 ++++++++ js/src/xpconnect/src/xpcpublic.h | 5 +-- .../xpconnect/src/xpcwrappednativescope.cpp | 3 +- modules/libpref/src/init/all.js | 4 +++ 17 files changed, 106 insertions(+), 43 deletions(-) diff --git a/content/base/src/nsContentList.cpp b/content/base/src/nsContentList.cpp index 444f7784d390..fd8c3b788072 100644 --- a/content/base/src/nsContentList.cpp +++ b/content/base/src/nsContentList.cpp @@ -186,9 +186,10 @@ NS_IMPL_ADDREF_INHERITED(nsSimpleContentList, nsBaseContentList) NS_IMPL_RELEASE_INHERITED(nsSimpleContentList, nsBaseContentList) JSObject* -nsSimpleContentList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope) +nsSimpleContentList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *failed) { - return xpc::dom::NodeListBase::create(cx, scope, this); + return xpc::dom::NodeListBase::create(cx, scope, this, failed); } // nsFormContentList @@ -502,11 +503,12 @@ nsContentList::~nsContentList() } JSObject* -nsContentList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope) +nsContentList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *failed) { return xpc::dom::NodeListBase::create(cx, scope, static_cast(this), - this); + this, failed); } DOMCI_DATA(ContentList, nsContentList) diff --git a/content/base/src/nsContentList.h b/content/base/src/nsContentList.h index a26435d1d7db..86e11f30fd0d 100644 --- a/content/base/src/nsContentList.h +++ b/content/base/src/nsContentList.h @@ -129,7 +129,8 @@ public: virtual PRInt32 IndexOf(nsIContent *aContent, bool aDoFlush); - virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope) = 0; + virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *triedToWrap) = 0; protected: nsCOMArray mElements; @@ -152,7 +153,8 @@ public: { return mRoot; } - virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope); + virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *triedToWrap); private: // This has to be a strong reference, the root might go away before the list. @@ -284,7 +286,8 @@ public: virtual ~nsContentList(); // nsWrapperCache - virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope); + virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *triedToWrap); // nsIDOMHTMLCollection NS_DECL_NSIDOMHTMLCOLLECTION diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 220ece825d10..39045eee231b 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -1556,9 +1556,10 @@ NS_INTERFACE_TABLE_HEAD(nsChildContentList) NS_INTERFACE_MAP_END JSObject* -nsChildContentList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope) +nsChildContentList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *triedToWrap) { - return xpc::dom::NodeListBase::create(cx, scope, this); + return xpc::dom::NodeListBase::create(cx, scope, this, triedToWrap); } NS_IMETHODIMP diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index 87f6b22ea088..0625dcc413a8 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -107,7 +107,8 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsChildContentList) // nsWrapperCache - virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope); + virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *triedToWrap); // nsIDOMNodeList interface NS_DECL_NSIDOMNODELIST diff --git a/content/html/content/src/nsHTMLFormElement.cpp b/content/html/content/src/nsHTMLFormElement.cpp index bb3872d18c2b..879de68ae5e5 100644 --- a/content/html/content/src/nsHTMLFormElement.cpp +++ b/content/html/content/src/nsHTMLFormElement.cpp @@ -162,9 +162,10 @@ public: nsresult GetSortedControls(nsTArray& aControls) const; // nsWrapperCache - virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope) + virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *triedToWrap) { - return xpc::dom::NodeListBase::create(cx, scope, this, this); + return xpc::dom::NodeListBase::create(cx, scope, this, this, triedToWrap); } nsHTMLFormElement* mForm; // WEAK - the form owns me diff --git a/content/html/content/src/nsHTMLTableElement.cpp b/content/html/content/src/nsHTMLTableElement.cpp index 9e47e723614e..46d1f5dc95e8 100644 --- a/content/html/content/src/nsHTMLTableElement.cpp +++ b/content/html/content/src/nsHTMLTableElement.cpp @@ -84,9 +84,10 @@ public: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TableRowsCollection) // nsWrapperCache - virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope) + virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *triedToWrap) { - return xpc::dom::NodeListBase::create(cx, scope, this, this); + return xpc::dom::NodeListBase::create(cx, scope, this, this, triedToWrap); } protected: diff --git a/content/xbl/src/nsBindingManager.cpp b/content/xbl/src/nsBindingManager.cpp index 3b9b7135dba7..5ff0dd8e0687 100644 --- a/content/xbl/src/nsBindingManager.cpp +++ b/content/xbl/src/nsBindingManager.cpp @@ -115,9 +115,10 @@ public: nsXBLInsertionPoint* GetInsertionPointAt(PRInt32 i) { return static_cast(mElements->ElementAt(i)); } void RemoveInsertionPointAt(PRInt32 i) { mElements->RemoveElementAt(i); } - virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope) + virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *triedToWrap) { - return xpc::dom::NodeListBase::create(cx, scope, this); + return xpc::dom::NodeListBase::create(cx, scope, this, triedToWrap); } NS_DECLARE_STATIC_IID_ACCESSOR(NS_ANONYMOUS_CONTENT_LIST_IID) diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index 2dd5317fc72c..95a68c5fa2f5 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -6174,10 +6174,10 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { xpc::dom::DefineInterface define = sClassInfoData[name_struct->mDOMClassInfoID].mDefineDOMInterface; - if (define && xpc::dom::DefineConstructor(cx, obj, define)) { - *did_resolve = true; + if (define && xpc::dom::DefineConstructor(cx, obj, define, &rv)) { + *did_resolve = NS_SUCCEEDED(rv); - return NS_OK; + return rv; } } diff --git a/dom/base/nsWrapperCache.h b/dom/base/nsWrapperCache.h index 1cbf0122a826..1ba58dccc14b 100644 --- a/dom/base/nsWrapperCache.h +++ b/dom/base/nsWrapperCache.h @@ -120,10 +120,17 @@ public: /** - * Wrap the object corresponding to this wrapper cache. If non-null is - * returned, the object has already been stored in the wrapper cache. + * Wrap the object corresponding to this wrapper cache. If non-null is + * returned, the object has already been stored in the wrapper cache and the + * value set in triedToWrap is meaningless. If null is returned then + * triedToWrap indicates whether an error occurred, if it's false then the + * object doesn't actually support creating a wrapper through its WrapObject + * hook. */ - virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope) { + virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope, + bool *triedToWrap) + { + *triedToWrap = false; return nsnull; } diff --git a/js/src/xpconnect/src/dombindings.cpp b/js/src/xpconnect/src/dombindings.cpp index e257d159be0f..09869ba76c71 100644 --- a/js/src/xpconnect/src/dombindings.cpp +++ b/js/src/xpconnect/src/dombindings.cpp @@ -129,18 +129,18 @@ WrapNativeParent(JSContext *cx, JSObject *scope, T *p) JSObject * NodeListBase::create(JSContext *cx, XPCWrappedNativeScope *scope, - nsINodeList *aNodeList) + nsINodeList *aNodeList, bool *triedToWrap) { - return NodeList::create(cx, scope, aNodeList, aNodeList); + return NodeList::create(cx, scope, aNodeList, aNodeList, triedToWrap); } JSObject * NodeListBase::create(JSContext *cx, XPCWrappedNativeScope *scope, nsIHTMLCollection *aHTMLCollection, - nsWrapperCache *aWrapperCache) + nsWrapperCache *aWrapperCache, bool *triedToWrap) { return NodeList::create(cx, scope, aHTMLCollection, - aWrapperCache); + aWrapperCache, triedToWrap); } template @@ -222,9 +222,14 @@ Register(nsDOMClassInfoData *aData) } bool -DefineConstructor(JSContext *cx, JSObject *obj, DefineInterface aDefine) +DefineConstructor(JSContext *cx, JSObject *obj, DefineInterface aDefine, nsresult *aResult) { - return !!aDefine(cx, XPCWrappedNativeScope::FindInJSObjectScope(cx, obj)); + bool enabled; + bool defined = !!aDefine(cx, XPCWrappedNativeScope::FindInJSObjectScope(cx, obj), &enabled); + NS_ASSERTION(!defined || enabled, + "We defined a constructor but the new bindings are disabled?"); + *aResult = defined ? NS_OK : NS_ERROR_FAILURE; + return enabled; } template @@ -436,8 +441,15 @@ interface_hasInstance(JSContext *cx, JSObject *obj, const js::Value *vp, JSBool template JSObject * -NodeList::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope) +NodeList::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, bool *enabled) { + if(!scope->NewDOMBindingsEnabled()) { + *enabled = false; + return NULL; + } + + *enabled = true; + nsDataHashtable &cache = scope->GetCachedDOMPrototypes(); @@ -504,8 +516,10 @@ NodeList::getPrototype(JSContext *cx, XPCWrappedNativeScope *scope) template JSObject * NodeList::create(JSContext *cx, XPCWrappedNativeScope *scope, T *aNodeList, - nsWrapperCache* aWrapperCache) + nsWrapperCache* aWrapperCache, bool *triedToWrap) { + *triedToWrap = true; + JSObject *parent = WrapNativeParent(cx, scope->GetGlobalJSObject(), aNodeList->GetParentObject()); if (!parent) return NULL; @@ -518,7 +532,7 @@ NodeList::create(JSContext *cx, XPCWrappedNativeScope *scope, T *aNodeList, scope = XPCWrappedNativeScope::FindInJSObjectScope(cx, parent); } - JSObject *proto = getPrototype(cx, scope); + JSObject *proto = getPrototype(cx, scope, triedToWrap); if (!proto) return NULL; JSObject *obj = NewProxyObject(cx, &NodeList::instance, diff --git a/js/src/xpconnect/src/dombindings.h b/js/src/xpconnect/src/dombindings.h index d804cbd61746..ec2a5851e68b 100644 --- a/js/src/xpconnect/src/dombindings.h +++ b/js/src/xpconnect/src/dombindings.h @@ -84,10 +84,10 @@ public: NodeListBase() : ProxyHandler() {} static JSObject *create(JSContext *cx, XPCWrappedNativeScope *scope, - nsINodeList *aNodeList); + nsINodeList *aNodeList, bool *triedToWrap); static JSObject *create(JSContext *cx, XPCWrappedNativeScope *scope, nsIHTMLCollection *aHTMLCollection, - nsWrapperCache *aWrapperCache); + nsWrapperCache *aWrapperCache, bool *triedToWrap); }; /** @@ -110,7 +110,7 @@ class NodeList : public NodeListBase { static Methods sProtoMethods[]; static bool instanceIsNodeListObject(JSContext *cx, JSObject *obj, JSObject *callee); - static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope); + static JSObject *getPrototype(JSContext *cx, XPCWrappedNativeScope *scope, bool *enabled); static T *getNodeList(JSObject *obj); @@ -163,7 +163,7 @@ class NodeList : public NodeListBase { void finalize(JSContext *cx, JSObject *proxy); static JSObject *create(JSContext *cx, XPCWrappedNativeScope *scope, T *, - nsWrapperCache* aWrapperCache); + nsWrapperCache* aWrapperCache, bool *enabled); static bool objIsNodeList(JSObject *obj) { return js::IsProxy(obj) && js::GetProxyHandler(obj) == &instance; diff --git a/js/src/xpconnect/src/xpcconvert.cpp b/js/src/xpconnect/src/xpcconvert.cpp index f1b411112c25..b8c4dbf3a928 100644 --- a/js/src/xpconnect/src/xpcconvert.cpp +++ b/js/src/xpconnect/src/xpcconvert.cpp @@ -1155,7 +1155,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx, // implementing it doesn't want a wrapped native as its JS Object, but // instead it provides its own proxy object. In that case, the object // to use is found as cache->GetWrapper(). If that is null, then the - // object will create (and fill the cache) from its PreCreate call. + // object will create (and fill the cache) from its WrapObject call. nsWrapperCache *cache = aHelper.GetWrapperCache(); bool tryConstructSlimWrapper = false; @@ -1170,16 +1170,22 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx, return JS_FALSE; if(!flat) { - flat = cache->WrapObject(lccx.GetJSContext(), xpcscope); + bool triedToWrap; + flat = cache->WrapObject(lccx.GetJSContext(), xpcscope, + &triedToWrap); + if(!flat && triedToWrap) + return JS_FALSE; if (!flat) { flat = ConstructProxyObject(ccx, aHelper, xpcscope); } } - if(!JS_WrapObject(ccx, &flat)) - return JS_FALSE; + if(flat) { + if(!JS_WrapObject(ccx, &flat)) + return JS_FALSE; - return CreateHolderIfNeeded(ccx, flat, d, dest); + return CreateHolderIfNeeded(ccx, flat, d, dest); + } } if(!dest) diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index 15677848244b..5a8402714044 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -52,6 +52,7 @@ #include "nsPrintfCString.h" #include "mozilla/FunctionTimer.h" #include "prsystem.h" +#include "mozilla/Preferences.h" #ifdef MOZ_CRASHREPORTER #include "nsExceptionHandler.h" @@ -2018,6 +2019,8 @@ DiagnosticMemoryCallback(void *ptr, size_t size) } #endif +bool XPCJSRuntime::gNewDOMBindingsEnabled; + XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) : mXPConnect(aXPConnect), mJSRuntime(nsnull), @@ -2053,6 +2056,9 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect) NS_TIME_FUNCTION; DOM_InitInterfaces(); + Preferences::AddBoolVarCache(&gNewDOMBindingsEnabled, "dom.new_bindings", + JS_FALSE); + // these jsids filled in later when we have a JSContext to work with. mStrIDs[0] = JSID_VOID; diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 51b3fbdca775..61b9d0f09e0f 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -793,6 +793,11 @@ public: static void ActivityCallback(void *arg, JSBool active); + bool NewDOMBindingsEnabled() + { + return gNewDOMBindingsEnabled; + } + private: XPCJSRuntime(); // no implementation XPCJSRuntime(nsXPConnect* aXPConnect); @@ -802,6 +807,8 @@ private: static void WatchdogMain(void *arg); + static bool gNewDOMBindingsEnabled; + static const char* mStrings[IDX_TOTAL_COUNT]; jsid mStrIDs[IDX_TOTAL_COUNT]; jsval mStrJSVals[IDX_TOTAL_COUNT]; @@ -1616,6 +1623,11 @@ public: } void TraceDOMPrototypes(JSTracer *trc); + JSBool NewDOMBindingsEnabled() + { + return mNewDOMBindingsEnabled; + } + protected: XPCWrappedNativeScope(XPCCallContext& ccx, JSObject* aGlobal); virtual ~XPCWrappedNativeScope(); @@ -1657,6 +1669,8 @@ private: nsIScriptObjectPrincipal* mScriptObjectPrincipal; nsDataHashtable mCachedDOMPrototypes; + + JSBool mNewDOMBindingsEnabled; }; JSObject* xpc_CloneJSFunction(XPCCallContext &ccx, JSObject *funobj, diff --git a/js/src/xpconnect/src/xpcpublic.h b/js/src/xpconnect/src/xpcpublic.h index 42b31e0167c2..e267123baee6 100644 --- a/js/src/xpconnect/src/xpcpublic.h +++ b/js/src/xpconnect/src/xpcpublic.h @@ -286,12 +286,13 @@ enum { }; typedef JSObject* -(*DefineInterface)(JSContext *cx, XPCWrappedNativeScope *scope); +(*DefineInterface)(JSContext *cx, XPCWrappedNativeScope *scope, bool *enabled); void Register(nsDOMClassInfoData *aData); extern bool -DefineConstructor(JSContext *cx, JSObject *obj, DefineInterface aDefine); +DefineConstructor(JSContext *cx, JSObject *obj, DefineInterface aDefine, + nsresult *aResult); } } diff --git a/js/src/xpconnect/src/xpcwrappednativescope.cpp b/js/src/xpconnect/src/xpcwrappednativescope.cpp index 51323a2d7cbc..6db4d32bc2b1 100644 --- a/js/src/xpconnect/src/xpcwrappednativescope.cpp +++ b/js/src/xpconnect/src/xpcwrappednativescope.cpp @@ -148,7 +148,8 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(XPCCallContext& ccx, mPrototypeJSObject(nsnull), mPrototypeJSFunction(nsnull), mPrototypeNoHelper(nsnull), - mScriptObjectPrincipal(nsnull) + mScriptObjectPrincipal(nsnull), + mNewDOMBindingsEnabled(ccx.GetRuntime()->NewDOMBindingsEnabled()) { // add ourselves to the scopes list { // scoped lock diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 65aba6412360..92b5cca9a652 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -599,6 +599,10 @@ pref("dom.min_timeout_value", 4); // And for background windows pref("dom.min_background_timeout_value", 1000); +// Use the new DOM bindings (only affects any scopes created after the pref is +// changed) +pref("dom.new_bindings", false); + // Parsing perf prefs. For now just mimic what the old code did. #ifndef XP_WIN pref("content.sink.pending_event_mode", 0);