Bug 500846 - Calculate sObjectClass in non-browser embeddings. r+sr=bzbarsky
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1444,26 +1444,31 @@ jsval nsDOMClassInfo::sOnpaste_id
jsval nsDOMClassInfo::sJava_id = JSVAL_VOID;
jsval nsDOMClassInfo::sPackages_id = JSVAL_VOID;
static const JSClass *sObjectClass = nsnull;
const JSClass *nsDOMClassInfo::sXPCNativeWrapperClass = nsnull;
static PRBool sDoSecurityCheckInAddProperty = PR_TRUE;
-const JSClass*
-NS_DOMClassInfo_GetXPCNativeWrapperClass()
-{
- return nsDOMClassInfo::GetXPCNativeWrapperClass();
-}
-
-void
-NS_DOMClassInfo_SetXPCNativeWrapperClass(JSClass* aClass)
-{
- nsDOMClassInfo::SetXPCNativeWrapperClass(aClass);
+/**
+ * Set our JSClass pointer for the Object class
+ */
+static void
+FindObjectClass(JSObject* aGlobalObject)
+{
+ NS_ASSERTION(!sObjectClass,
+ "Double set of sObjectClass");
+ JSObject *obj, *proto = aGlobalObject;
+ do {
+ obj = proto;
+ proto = STOBJ_GET_PROTO(obj);
+ } while (proto);
+
+ sObjectClass = STOBJ_GET_CLASS(obj);
}
static void
PrintWarningOnConsole(JSContext *cx, const char *stringBundleProperty)
{
nsCOMPtr<nsIStringBundleService>
stringService(do_GetService(NS_STRINGBUNDLE_CONTRACTID));
if (!stringService) {
@@ -4149,16 +4154,25 @@ nsDOMClassInfo::PostCreatePrototype(JSCo
static const nsIID *sSupportsIID = &NS_GET_IID(nsISupports);
// This is safe because...
if (mData->mProtoChainInterface == sSupportsIID ||
!mData->mProtoChainInterface) {
return NS_OK;
}
+ // This is called before any other location that requires
+ // sObjectClass, so compute it here. We assume that nobody has had a
+ // chance to monkey around with proto's prototype chain before this.
+ if (!sObjectClass) {
+ FindObjectClass(proto);
+ NS_ASSERTION(sObjectClass && !strcmp(sObjectClass->name, "Object"),
+ "Incorrect object class!");
+ }
+
NS_ASSERTION(::JS_GetPrototype(cx, proto) &&
JS_GET_CLASS(cx, ::JS_GetPrototype(cx, proto)) == sObjectClass,
"Hmm, somebody did something evil?");
#ifdef DEBUG
if (mData->mHasClassInterface) {
nsCOMPtr<nsIInterfaceInfoManager>
iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
@@ -4394,31 +4408,16 @@ nsDOMClassInfo::ShutDown()
}
// Window helper
NS_IMETHODIMP
nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj)
{
- // Since this is one of the first calls we'll get from XPConnect,
- // grab the pointer to the Object class so we'll have it later on.
-
- if (!sObjectClass) {
- JSObject *obj, *proto = globalObj;
- JSAutoRequest ar(cx);
-
- do {
- obj = proto;
- proto = ::JS_GetPrototype(cx, obj);
- } while (proto);
-
- sObjectClass = JS_GET_CLASS(cx, obj);
- }
-
// Normally ::PreCreate() is used to give XPConnect the parent
// object for the object that's being wrapped, this parent object is
// set as the parent of the wrapper and it's also used to find the
// right scope for the object being wrapped. Now, in the case of the
// global object the wrapper shouldn't have a parent but we supply
// one here anyway (the global object itself) and this will be used
// by XPConnect only to find the right scope, once the scope is
// found XPConnect will find the existing wrapper (which always
@@ -5740,17 +5739,17 @@ ResolvePrototype(nsIXPConnect *aXPConnec
}
}
if (dot_prototype) {
JSObject *xpc_proto_proto = ::JS_GetPrototype(cx, dot_prototype);
if (proto &&
(!xpc_proto_proto ||
- JS_GET_CLASS(cx, xpc_proto_proto) == sObjectClass)) {
+ JS_GET_CLASS(cx, xpc_proto_proto) == nsDOMClassInfo::GetObjectClass())) {
if (!::JS_SetPrototype(cx, dot_prototype, proto)) {
return NS_ERROR_UNEXPECTED;
}
}
} else {
dot_prototype = ::JS_NewObject(cx, &sDOMConstructorProtoClass, proto,
obj);
NS_ENSURE_TRUE(dot_prototype, NS_ERROR_OUT_OF_MEMORY);
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -38,16 +38,17 @@
* ***** END LICENSE BLOCK ***** */
#ifndef nsDOMClassInfo_h___
#define nsDOMClassInfo_h___
#include "nsIDOMClassInfo.h"
#include "nsIXPCScriptable.h"
#include "jsapi.h"
+#include "jsobj.h"
#include "nsIScriptSecurityManager.h"
#include "nsIScriptContext.h"
#include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
#include "nsIScriptGlobalObject.h"
class nsIDOMWindow;
class nsIDOMNSHTMLOptionCollection;
class nsIPluginInstance;
@@ -151,17 +152,17 @@ public:
static nsresult ThrowJSException(JSContext *cx, nsresult aResult);
/**
* Get our JSClass pointer for the XPCNativeWrapper class
*/
static const JSClass* GetXPCNativeWrapperClass() {
return sXPCNativeWrapperClass;
}
-
+
/**
* Set our JSClass pointer for the XPCNativeWrapper class
*/
static void SetXPCNativeWrapperClass(JSClass* aClass) {
NS_ASSERTION(!sXPCNativeWrapperClass,
"Double set of sXPCNativeWrapperClass");
sXPCNativeWrapperClass = aClass;
}
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2450,19 +2450,16 @@ nsJSContext::ConnectToInner(nsIScriptGlo
}
void *
nsJSContext::GetNativeContext()
{
return mContext;
}
-const JSClass* NS_DOMClassInfo_GetXPCNativeWrapperClass();
-void NS_DOMClassInfo_SetXPCNativeWrapperClass(JSClass* aClass);
-
nsresult
nsJSContext::InitContext(nsIScriptGlobalObject *aGlobalObject)
{
// Make sure callers of this use
// WillInitializeContext/DidInitializeContext around this call.
NS_ENSURE_TRUE(!mIsInitialized, NS_ERROR_ALREADY_INITIALIZED);
if (!mContext)
@@ -2512,17 +2509,17 @@ nsJSContext::InitContext(nsIScriptGlobal
rv = xpc->InitClassesWithNewWrappedGlobal(mContext, aGlobalObject,
NS_GET_IID(nsISupports),
flags,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
// Now check whether we need to grab a pointer to the
// XPCNativeWrapper class
- if (!NS_DOMClassInfo_GetXPCNativeWrapperClass()) {
+ if (!nsDOMClassInfo::GetXPCNativeWrapperClass()) {
JSAutoRequest ar(mContext);
rv = FindXPCNativeWrapperClass(holder);
NS_ENSURE_SUCCESS(rv, rv);
}
} else {
// If there's already a global object in mContext we're called
// after ::JS_ClearScope() was called. We'll have to tell
// XPConnect to re-initialize the global object to do things like
@@ -2922,17 +2919,17 @@ nsJSContext::AddSupportsPrimitiveTojsval
}
}
return NS_OK;
}
nsresult
nsJSContext::FindXPCNativeWrapperClass(nsIXPConnectJSObjectHolder *aHolder)
{
- NS_ASSERTION(!NS_DOMClassInfo_GetXPCNativeWrapperClass(),
+ NS_ASSERTION(!nsDOMClassInfo::GetXPCNativeWrapperClass(),
"Why was this called?");
JSObject *globalObj;
aHolder->GetJSObject(&globalObj);
NS_ASSERTION(globalObj, "Must have global by now!");
const char* arg = "arg";
NS_NAMED_LITERAL_STRING(body, "return new XPCNativeWrapper(arg);");
@@ -2959,18 +2956,19 @@ nsJSContext::FindXPCNativeWrapperClass(n
if (!ok) {
// No need to notify about pending exceptions here; we don't
// expect any other than out of memory, really.
return NS_ERROR_FAILURE;
}
NS_ASSERTION(JSVAL_IS_OBJECT(wrapper), "This should be an object!");
- NS_DOMClassInfo_SetXPCNativeWrapperClass(
+ nsDOMClassInfo::SetXPCNativeWrapperClass(
::JS_GET_CLASS(mContext, JSVAL_TO_OBJECT(wrapper)));
+
return NS_OK;
}
static JSPropertySpec OptionsProperties[] = {
{"strict", (int8)JSOPTION_STRICT, JSPROP_ENUMERATE | JSPROP_PERMANENT},
{"werror", (int8)JSOPTION_WERROR, JSPROP_ENUMERATE | JSPROP_PERMANENT},
{"relimit", (int8)JSOPTION_RELIMIT, JSPROP_ENUMERATE | JSPROP_PERMANENT},
{0}