vendor/tracemonkey/xpconnect/src/nsXPConnect.cpp in johnson-2.0.0.pre0 vs vendor/tracemonkey/xpconnect/src/nsXPConnect.cpp in johnson-2.0.0.pre1

- old
+ new

@@ -65,11 +65,11 @@ JSBool nsXPConnect::gOnceAliveNowDead = JS_FALSE; PRUint32 nsXPConnect::gReportAllJSExceptions = 0; // Global cache of the default script security manager (QI'd to // nsIScriptSecurityManager) -nsIScriptSecurityManager *gScriptSecurityManager = nsnull; +nsIScriptSecurityManager_1_9_2 *gScriptSecurityManager = nsnull; const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1"; const char XPC_RUNTIME_CONTRACTID[] = "@mozilla.org/js/xpc/RuntimeService;1"; const char XPC_EXCEPTION_CONTRACTID[] = "@mozilla.org/js/xpc/Exception;1"; const char XPC_CONSOLE_CONTRACTID[] = "@mozilla.org/consoleservice;1"; @@ -569,30 +569,13 @@ #endif GetRuntime()->AddXPConnectRoots(mCycleCollectionContext->GetJSContext(), cb); -#ifndef XPCONNECT_STANDALONE - if(!mScopes.IsInitialized()) - { - mScopes.Init(); - } - NS_ASSERTION(mScopes.Count() == 0, "Didn't clear mScopes?"); - XPCWrappedNativeScope::TraverseScopes(*mCycleCollectionContext); -#endif - return NS_OK; } -#ifndef XPCONNECT_STANDALONE -void -nsXPConnect::RecordTraversal(void *p, nsISupports *s) -{ - mScopes.Put(p, s); -} -#endif - nsresult nsXPConnect::FinishCycleCollection() { #ifdef DEBUG_CC if(mExplainCycleCollectionContext) @@ -602,14 +585,10 @@ GetRuntime()->RootContextGlobals(); } #endif -#ifndef XPCONNECT_STANDALONE - mScopes.Clear(); -#endif - #ifdef DEBUG_CC if(mJSRoots.ops) { PL_DHashTableFinish(&mJSRoots); mJSRoots.ops = nsnull; @@ -623,10 +602,20 @@ nsXPConnect::ToParticipant(void *p) { return this; } +void +nsXPConnect::CommenceShutdown() +{ +#ifdef DEBUG + fprintf(stderr, "nsXPConnect::CommenceShutdown()\n"); +#endif + // Tell the JS engine that we are about to destroy the runtime. + JS_CommenceRuntimeShutDown(mRuntime->GetJSRuntime()); +} + NS_IMETHODIMP nsXPConnect::RootAndUnlinkJSObjects(void *p) { return NS_OK; } @@ -670,25 +659,27 @@ NoteJSChild(JSTracer *trc, void *thing, uint32 kind) { if(ADD_TO_CC(kind)) { TraversalTracer *tracer = static_cast<TraversalTracer*>(trc); -#if defined(DEBUG) && defined(DEBUG_CC) - // based on DumpNotify in jsapi.c - if (tracer->debugPrinter) { - char buffer[200]; - tracer->debugPrinter(trc, buffer, sizeof(buffer)); - tracer->cb.NoteNextEdgeName(buffer); - } else if (tracer->debugPrintIndex != (size_t)-1) { - char buffer[200]; - JS_snprintf(buffer, sizeof(buffer), "%s[%lu]", - static_cast<const char *>(tracer->debugPrintArg), - tracer->debugPrintIndex); - tracer->cb.NoteNextEdgeName(buffer); - } else { - tracer->cb.NoteNextEdgeName( - static_cast<const char*>(tracer->debugPrintArg)); +#if defined(DEBUG) + if (NS_UNLIKELY(tracer->cb.WantDebugInfo())) { + // based on DumpNotify in jsapi.c + if (tracer->debugPrinter) { + char buffer[200]; + tracer->debugPrinter(trc, buffer, sizeof(buffer)); + tracer->cb.NoteNextEdgeName(buffer); + } else if (tracer->debugPrintIndex != (size_t)-1) { + char buffer[200]; + JS_snprintf(buffer, sizeof(buffer), "%s[%lu]", + static_cast<const char *>(tracer->debugPrintArg), + tracer->debugPrintIndex); + tracer->cb.NoteNextEdgeName(buffer); + } else { + tracer->cb.NoteNextEdgeName( + static_cast<const char*>(tracer->debugPrintArg)); + } } #endif tracer->cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, thing); } else if(kind != JSTRACE_DOUBLE && kind != JSTRACE_STRING) @@ -751,11 +742,10 @@ } CCNodeType type; #ifdef DEBUG_CC - { // Note that the conditions under which we specify GCMarked vs. // GCUnmarked are different between ExplainLiveExpectedGarbage and // the normal case. In the normal case, we're saying that anything // reachable from a JS runtime root is itself such a root. This // doesn't actually break anything; it really just does some of the @@ -771,153 +761,154 @@ PL_DHashTableOperate(&mJSRoots, p, PL_DHASH_LOOKUP); type = markJSObject || PL_DHASH_ENTRY_IS_BUSY(entry) ? GCMarked : GCUnmarked; } else +#endif { // Normal codepath (matches non-DEBUG_CC codepath). type = !markJSObject && JS_IsAboutToBeFinalized(cx, p) ? GCUnmarked : GCMarked; } - char name[72]; - if(traceKind == JSTRACE_OBJECT) - { - JSObject *obj = static_cast<JSObject*>(p); - JSClass *clazz = OBJ_GET_CLASS(cx, obj); - if(XPCNativeWrapper::IsNativeWrapperClass(clazz)) + if (cb.WantDebugInfo()) { + char name[72]; + if(traceKind == JSTRACE_OBJECT) { - XPCWrappedNative* wn = XPCNativeWrapper::GetWrappedNative(obj); - if(wn) + JSObject *obj = static_cast<JSObject*>(p); + JSClass *clazz = OBJ_GET_CLASS(cx, obj); + if(XPCNativeWrapper::IsNativeWrapperClass(clazz)) { - XPCNativeScriptableInfo* si = wn->GetScriptableInfo(); - if(si) + XPCWrappedNative* wn; + if(XPCNativeWrapper::GetWrappedNative(cx, obj, &wn) && wn) { - JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)", - si->GetJSClass()->name); - } - else - { - nsIClassInfo* ci = wn->GetClassInfo(); - char* className = nsnull; - if(ci) - ci->GetClassDescription(&className); - if(className) + XPCNativeScriptableInfo* si = wn->GetScriptableInfo(); + if(si) { JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)", - className); - PR_Free(className); + si->GetJSClass()->name); } else { - XPCNativeSet* set = wn->GetSet(); - XPCNativeInterface** array = set->GetInterfaceArray(); - PRUint16 count = set->GetInterfaceCount(); - - if(count > 0) + nsIClassInfo* ci = wn->GetClassInfo(); + char* className = nsnull; + if(ci) + ci->GetClassDescription(&className); + if(className) + { JS_snprintf(name, sizeof(name), - "XPCNativeWrapper (%s)", - array[0]->GetNameString()); + "XPCNativeWrapper (%s)", className); + PR_Free(className); + } else - JS_snprintf(name, sizeof(name), "XPCNativeWrapper"); + { + XPCNativeSet* set = wn->GetSet(); + XPCNativeInterface** array = + set->GetInterfaceArray(); + PRUint16 count = set->GetInterfaceCount(); + + if(count > 0) + JS_snprintf(name, sizeof(name), + "XPCNativeWrapper (%s)", + array[0]->GetNameString()); + else + JS_snprintf(name, sizeof(name), + "XPCNativeWrapper"); + } } } + else + { + JS_snprintf(name, sizeof(name), "XPCNativeWrapper"); + } } else { - JS_snprintf(name, sizeof(name), "XPCNativeWrapper"); - } - } - else - { - XPCNativeScriptableInfo* si = nsnull; - if(IS_PROTO_CLASS(clazz)) - { - XPCWrappedNativeProto* p = - (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); - si = p->GetScriptableInfo(); - } - if(si) - { - JS_snprintf(name, sizeof(name), "JS Object (%s - %s)", - clazz->name, si->GetJSClass()->name); - } - else if(clazz == &js_ScriptClass) - { - JSScript* script = (JSScript*) xpc_GetJSPrivate(obj); - if(script->filename) + XPCNativeScriptableInfo* si = nsnull; + if(IS_PROTO_CLASS(clazz)) { - JS_snprintf(name, sizeof(name), "JS Object (Script - %s)", - script->filename); + XPCWrappedNativeProto* p = + (XPCWrappedNativeProto*) xpc_GetJSPrivate(obj); + si = p->GetScriptableInfo(); } - else + if(si) { - JS_snprintf(name, sizeof(name), "JS Object (Script)"); + JS_snprintf(name, sizeof(name), "JS Object (%s - %s)", + clazz->name, si->GetJSClass()->name); } - } - else if(clazz == &js_FunctionClass) - { - JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj); - JSString* str = JS_GetFunctionId(fun); - if(str) + else if(clazz == &js_ScriptClass) { - NS_ConvertUTF16toUTF8 - fname(JS_GetStringChars(str)); - JS_snprintf(name, sizeof(name), "JS Object (Function - %s)", - fname.get()); + JSScript* script = (JSScript*) xpc_GetJSPrivate(obj); + if(script->filename) + { + JS_snprintf(name, sizeof(name), + "JS Object (Script - %s)", + script->filename); + } + else + { + JS_snprintf(name, sizeof(name), "JS Object (Script)"); + } } + else if(clazz == &js_FunctionClass) + { + JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj); + JSString* str = JS_GetFunctionId(fun); + if(str) + { + NS_ConvertUTF16toUTF8 + fname(reinterpret_cast<const PRUnichar*>(JS_GetStringChars(str))); + JS_snprintf(name, sizeof(name), + "JS Object (Function - %s)", fname.get()); + } + else + { + JS_snprintf(name, sizeof(name), "JS Object (Function)"); + } + } else { - JS_snprintf(name, sizeof(name), "JS Object (Function)"); + JS_snprintf(name, sizeof(name), "JS Object (%s)", + clazz->name); } } - else - { - JS_snprintf(name, sizeof(name), "JS Object (%s)", clazz->name); - } } - } - else - { - static const char trace_types[JSTRACE_LIMIT][7] = { - "Object", - "Double", - "String", - "Xml" - }; - JS_snprintf(name, sizeof(name), "JS %s", trace_types[traceKind]); - } + else + { + static const char trace_types[JSTRACE_LIMIT][7] = { + "Object", + "Double", + "String", + "Xml" + }; + JS_snprintf(name, sizeof(name), "JS %s", trace_types[traceKind]); + } - if(traceKind == JSTRACE_OBJECT) { - JSObject *global = static_cast<JSObject*>(p), *parent; - while((parent = JS_GetParent(cx, global))) - global = parent; - char fullname[100]; - JS_snprintf(fullname, sizeof(fullname), "%s (global=%p)", name, global); - cb.DescribeNode(type, 0, sizeof(JSObject), fullname); + if(traceKind == JSTRACE_OBJECT) { + JSObject *global = static_cast<JSObject*>(p), *parent; + while((parent = JS_GetParent(cx, global))) + global = parent; + char fullname[100]; + JS_snprintf(fullname, sizeof(fullname), + "%s (global=%p)", name, global); + cb.DescribeNode(type, 0, sizeof(JSObject), fullname); + } else { + cb.DescribeNode(type, 0, sizeof(JSObject), name); + } } else { - cb.DescribeNode(type, 0, sizeof(JSObject), name); + cb.DescribeNode(type, 0, sizeof(JSObject), "JS Object"); } - } -#else - type = !markJSObject && JS_IsAboutToBeFinalized(cx, p) ? GCUnmarked : - GCMarked; - cb.DescribeNode(type, 0); -#endif - if(!ADD_TO_CC(traceKind)) return NS_OK; -#ifndef DEBUG_CC // There's no need to trace objects that have already been marked by the JS // GC. Any JS objects hanging from them will already be marked. Only do this // if DEBUG_CC is not defined, else we do want to know about all JS objects // to get better graphs and explanations. - if(type == GCMarked) + if(!cb.WantAllTraces() && type == GCMarked) return NS_OK; -#endif TraversalTracer trc(cb); JS_TRACER_INIT(&trc, cx, NoteJSChild); JS_TraceChildren(&trc, p, traceKind); @@ -945,20 +936,10 @@ { NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "xpc_GetJSPrivate(obj)"); cb.NoteXPCOMChild(static_cast<nsISupports*>(xpc_GetJSPrivate(obj))); } -#ifndef XPCONNECT_STANDALONE - if(clazz->flags & JSCLASS_IS_GLOBAL) - { - nsISupports *principal = nsnull; - mScopes.Get(obj, &principal); - NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "scope principal"); - cb.NoteXPCOMChild(principal); - } -#endif - return NS_OK; } PRInt32 nsXPConnect::GetRequestDepth(JSContext* cx) @@ -997,17 +978,13 @@ // requests the context needs to be kept alive and adding unknown // edges will ensure that any cycles this context is in won't be // collected. PRInt32 refCount = nsXPConnect::GetXPConnect()->GetRequestDepth(cx) + 1; -#ifdef DEBUG_CC cb.DescribeNode(RefCounted, refCount, sizeof(JSContext), "JSContext"); - cb.NoteNextEdgeName("[global object]"); -#else - cb.DescribeNode(RefCounted, refCount); -#endif + NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[global object]"); cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, cx->globalObject); return NS_OK; } @@ -1084,21 +1061,19 @@ scope->RemoveWrappedNativeProtos(); if(!nsXPCComponents::AttachNewComponentsObject(ccx, scope, aGlobalJSObj)) return UnexpectedFailure(NS_ERROR_FAILURE); -#ifdef XPC_IDISPATCH_SUPPORT - // Initialize any properties IDispatch needs on the global object - XPCIDispatchExtension::Initialize(ccx, aGlobalJSObj); -#endif + if(XPCPerThreadData::IsMainThread(ccx)) + { + if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj)) + return UnexpectedFailure(NS_ERROR_FAILURE); - if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj)) - return UnexpectedFailure(NS_ERROR_FAILURE); + if (!XPC_SJOW_AttachNewConstructorObject(ccx, aGlobalJSObj)) + return UnexpectedFailure(NS_ERROR_FAILURE); + } - if (!XPC_SJOW_AttachNewConstructorObject(ccx, aGlobalJSObj)) - return UnexpectedFailure(NS_ERROR_FAILURE); - return NS_OK; } static JSBool TempGlobalResolve(JSContext *aJSContext, JSObject *obj, jsval id) @@ -1108,11 +1083,11 @@ } static JSClass xpcTempGlobalClass = { "xpcTempGlobalClass", JSCLASS_GLOBAL_FLAGS, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, TempGlobalResolve, JS_ConvertStub, JS_FinalizeStub, + JS_EnumerateStub, TempGlobalResolve, JS_ConvertStub, nsnull, JSCLASS_NO_OPTIONAL_MEMBERS }; /* nsIXPConnectJSObjectHolder initClassesWithNewWrappedGlobal (in JSContextPtr aJSContext, in nsISupports aCOMObj, in nsIIDRef aIID, in PRUint32 aFlags); */ NS_IMETHODIMP @@ -1206,15 +1181,18 @@ if(!(aFlags & nsIXPConnect::OMIT_COMPONENTS_OBJECT)) { SaveFrame sf(ccx); if(!nsXPCComponents::AttachNewComponentsObject(ccx, scope, globalJSObj)) return UnexpectedFailure(NS_ERROR_FAILURE); - if(!XPCNativeWrapper::AttachNewConstructorObject(ccx, globalJSObj)) - return UnexpectedFailure(NS_ERROR_FAILURE); + if(XPCPerThreadData::IsMainThread(ccx)) + { + if(!XPCNativeWrapper::AttachNewConstructorObject(ccx, globalJSObj)) + return UnexpectedFailure(NS_ERROR_FAILURE); - if(!XPC_SJOW_AttachNewConstructorObject(ccx, globalJSObj)) - return UnexpectedFailure(NS_ERROR_FAILURE); + if(!XPC_SJOW_AttachNewConstructorObject(ccx, globalJSObj)) + return UnexpectedFailure(NS_ERROR_FAILURE); + } } NS_ADDREF(*_retval = holder); return NS_OK; @@ -1229,19 +1207,21 @@ nsIXPConnectJSObjectHolder **aHolder) { NS_ASSERTION(aHolder, "bad param"); jsval v; - return WrapNativeToJSVal(aJSContext, aScope, aCOMObj, &aIID, &v, aHolder); + return WrapNativeToJSVal(aJSContext, aScope, aCOMObj, &aIID, PR_FALSE, + &v, aHolder); } /* void wrapNativeToJSVal (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDPtr aIID, out JSVal aVal, out nsIXPConnectJSObjectHolder aHolder); */ NS_IMETHODIMP nsXPConnect::WrapNativeToJSVal(JSContext * aJSContext, JSObject * aScope, nsISupports *aCOMObj, const nsIID * aIID, + PRBool aAllowWrapping, jsval *aVal, nsIXPConnectJSObjectHolder **aHolder) { NS_ASSERTION(aJSContext, "bad param"); NS_ASSERTION(aScope, "bad param"); @@ -1251,14 +1231,15 @@ *aHolder = nsnull; XPCCallContext ccx(NATIVE_CALLER, aJSContext); if(!ccx.IsValid()) return UnexpectedFailure(NS_ERROR_FAILURE); + XPCLazyCallContext lccx(ccx); nsresult rv; if(!XPCConvert::NativeInterface2JSObject(ccx, aVal, aHolder, aCOMObj, aIID, - nsnull, nsnull, aScope, PR_FALSE, + nsnull, nsnull, aScope, aAllowWrapping, OBJ_IS_NOT_GLOBAL, &rv)) return rv; #ifdef DEBUG NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(JSVAL_TO_OBJECT(*aVal)), @@ -1330,18 +1311,80 @@ XPCCallContext ccx(NATIVE_CALLER, aJSContext); if(!ccx.IsValid()) return UnexpectedFailure(NS_ERROR_FAILURE); + SLIM_LOG_WILL_MORPH(aJSContext, aJSObj); + if(!IS_SLIM_WRAPPER(aJSObj) || MorphSlimWrapper(aJSContext, aJSObj)) + { + nsIXPConnectWrappedNative* wrapper = + XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aJSObj); + if(wrapper) + { + NS_ADDREF(wrapper); + *_retval = wrapper; + return NS_OK; + } + } + + // else... + *_retval = nsnull; + return NS_ERROR_FAILURE; +} + +/* nsISupports getNativeOfWrapper(in JSContextPtr aJSContext, in JSObjectPtr aJSObj); */ +NS_IMETHODIMP_(nsISupports*) +nsXPConnect::GetNativeOfWrapper(JSContext * aJSContext, + JSObject * aJSObj) +{ + NS_ASSERTION(aJSContext, "bad param"); + NS_ASSERTION(aJSObj, "bad param"); + + XPCCallContext ccx(NATIVE_CALLER, aJSContext); + if(!ccx.IsValid()) + { + UnexpectedFailure(NS_ERROR_FAILURE); + return nsnull; + } + + JSObject* obj2 = nsnull; nsIXPConnectWrappedNative* wrapper = - XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aJSObj); + XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aJSObj, nsnull, + &obj2); + + return wrapper ? wrapper->Native() : + (obj2 ? (nsISupports*)xpc_GetJSPrivate(obj2) : nsnull); +} + +/* JSObjectPtr getJSObjectOfWrapper (in JSContextPtr aJSContext, in JSObjectPtr aJSObj); */ +NS_IMETHODIMP +nsXPConnect::GetJSObjectOfWrapper(JSContext * aJSContext, + JSObject * aJSObj, + JSObject **_retval) +{ + NS_ASSERTION(aJSContext, "bad param"); + NS_ASSERTION(aJSObj, "bad param"); + NS_ASSERTION(_retval, "bad param"); + + XPCCallContext ccx(NATIVE_CALLER, aJSContext); + if(!ccx.IsValid()) + return UnexpectedFailure(NS_ERROR_FAILURE); + + JSObject* obj2 = nsnull; + nsIXPConnectWrappedNative* wrapper = + XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aJSObj, nsnull, + &obj2); if(wrapper) { - NS_ADDREF(wrapper); - *_retval = wrapper; + wrapper->GetJSObject(_retval); return NS_OK; } + if(obj2) + { + *_retval = obj2; + return NS_OK; + } // else... *_retval = nsnull; return NS_ERROR_FAILURE; } @@ -1414,12 +1457,13 @@ static JSDHashOperator MoveableWrapperFinder(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number, void *arg) { // Every element counts. - nsVoidArray *va = static_cast<nsVoidArray *>(arg); - va->AppendElement(((Native2WrappedNativeMap::Entry*)hdr)->value); + nsTArray<nsRefPtr<XPCWrappedNative> > *array = + static_cast<nsTArray<nsRefPtr<XPCWrappedNative> > *>(arg); + array->AppendElement(((Native2WrappedNativeMap::Entry*)hdr)->value); return JS_DHASH_NEXT; } /* void reparentScopeAwareWrappers(in JSContextPtr aJSContext, in JSObjectPtr aOldScope, in JSObjectPtr aNewScope); */ NS_IMETHODIMP @@ -1441,27 +1485,26 @@ if(!newScope) return UnexpectedFailure(NS_ERROR_FAILURE); // First, look through the old scope and find all of the wrappers that // we're going to move. - nsVoidArray wrappersToMove; + nsTArray<nsRefPtr<XPCWrappedNative> > wrappersToMove; { // scoped lock XPCAutoLock lock(GetRuntime()->GetMapLock()); Native2WrappedNativeMap *map = oldScope->GetWrappedNativeMap(); - wrappersToMove.SizeTo(map->Count()); + wrappersToMove.SetCapacity(map->Count()); map->Enumerate(MoveableWrapperFinder, &wrappersToMove); } // Now that we have the wrappers, reparent them to the new scope. - for(PRInt32 i = 0, stop = wrappersToMove.Count(); i < stop; ++i) + for(PRUint32 i = 0, stop = wrappersToMove.Length(); i < stop; ++i) { // First, check to see if this wrapper really needs to be // reparented. - XPCWrappedNative *wrapper = - static_cast<XPCWrappedNative *>(wrappersToMove[i]); + XPCWrappedNative *wrapper = wrappersToMove[i]; nsISupports *identity = wrapper->GetIdentityObject(); nsCOMPtr<nsIClassInfo> info(do_QueryInterface(identity)); // ClassInfo is implemented as singleton objects. If the identity // object here is the same object as returned by the QI, then it @@ -1581,11 +1624,11 @@ NS_IF_ADDREF(aManager); NS_IF_RELEASE(mDefaultSecurityManager); mDefaultSecurityManager = aManager; mDefaultSecurityManagerFlags = flags; - nsCOMPtr<nsIScriptSecurityManager> ssm = + nsCOMPtr<nsIScriptSecurityManager_1_9_2> ssm = do_QueryInterface(mDefaultSecurityManager); // Remember the result of the above QI for fast access to the // script securityt manager. gScriptSecurityManager = ssm; @@ -1814,11 +1857,12 @@ XPCNativeScriptableInfo *si = proto->GetScriptableInfo(); if(si && si->GetFlags().DontSharePrototype()) return UnexpectedFailure(NS_ERROR_INVALID_ARG); - ClassInfo2WrappedNativeProtoMap* map = scope->GetWrappedNativeProtoMap(); + ClassInfo2WrappedNativeProtoMap* map = + scope->GetWrappedNativeProtoMap(proto->ClassIsMainThreadOnly()); XPCLock* lock = GetRuntime()->GetMapLock(); { // scoped lock XPCAutoLock al(lock); @@ -1913,23 +1957,20 @@ NS_ConvertUTF16toUTF8(source).get(), 1, JSVERSION_DEFAULT, returnStringOnly, rval); #endif /* XPCONNECT_STANDALONE */ } -/* void GetXPCWrappedNativeJSClassInfo(out JSClassConstPtr clazz, out JSObjectOpsConstPtr ops1, out JSObjectOpsConstPtr ops2); */ +/* void GetXPCWrappedNativeJSClassInfo(out JSEqualityOp equality1, JSEqualityOp *equality2); */ NS_IMETHODIMP -nsXPConnect::GetXPCWrappedNativeJSClassInfo(const JSClass **clazz, - JSGetObjectOps *ops1, - JSGetObjectOps *ops2) +nsXPConnect::GetXPCWrappedNativeJSClassInfo(JSEqualityOp *equality1, + JSEqualityOp *equality2) { - // Expose the JSClass and JSGetObjectOps pointers used by - // IS_WRAPPER_CLASS(). If that macro ever changes, this function - // needs to stay in sync. + // Expose the equality pointer used by IS_WRAPPER_CLASS(). If that macro + // ever changes, this function needs to stay in sync. - *clazz = &XPC_WN_NoHelper_JSClass.base; - *ops1 = XPC_WN_GetObjectOpsNoCall; - *ops2 = XPC_WN_GetObjectOpsWithCall; + *equality1 = &XPC_WN_Equality; + *equality2 = &XPC_SWN_Equality; return NS_OK; } /* nsIXPConnectJSObjectHolder getWrappedNativePrototype (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsIClassInfo aClassInfo); */ @@ -1978,10 +2019,21 @@ *rval = OBJECT_TO_JSVAL(aWrappedObj); return XPC_XOW_WrapObject(aJSContext, aParent, rval) ? NS_OK : NS_ERROR_FAILURE; } +NS_IMETHODIMP +nsXPConnect::GetCOWForObject(JSContext * aJSContext, + JSObject * aParent, + JSObject * aWrappedObj, + jsval * rval) +{ + *rval = OBJECT_TO_JSVAL(aWrappedObj); + return XPC_COW_WrapObject(aJSContext, aParent, *rval, rval) + ? NS_OK : NS_ERROR_FAILURE; +} + static inline PRBool PerformOp(JSContext *cx, PRUint32 aWay, JSObject *obj) { NS_ASSERTION(aWay == nsIXPConnect::XPC_XOW_CLEARSCOPE, "Nothing else is implemented yet"); @@ -2196,13 +2248,14 @@ NS_PRECONDITION(_retval, "bad param"); XPCCallContext ccx(NATIVE_CALLER, ctx); if(!ccx.IsValid()) return NS_ERROR_FAILURE; + XPCLazyCallContext lccx(ccx); nsresult rv = NS_OK; - if(!XPCVariant::VariantDataToJS(ccx, value, scope, &rv, _retval)) + if(!XPCVariant::VariantDataToJS(lccx, value, scope, &rv, _retval)) { if(NS_FAILED(rv)) return rv; return NS_ERROR_FAILURE; @@ -2317,22 +2370,32 @@ "Must only be called from the main thread as these wrappers " "are not threadsafe!"); JSAutoRequest ar(aJSContext); - XPCWrappedNative *wrapper = - XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aObject); - if(!wrapper) + XPCWrappedNativeScope *objectscope; + XPCWrappedNative *wrapper = nsnull; + if(IS_SLIM_WRAPPER(aObject)) { - // Couldn't get the wrapped native (maybe a prototype?) so just return - // the original object. - *_retval = OBJECT_TO_JSVAL(aObject); - return NS_OK; + objectscope = GetSlimWrapperProto(aObject)->GetScope(); } + else + { + wrapper = + XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aObject); + if(!wrapper) + { + // Couldn't get the wrapped native (maybe a prototype?) so just return + // the original object. + *_retval = OBJECT_TO_JSVAL(aObject); + return NS_OK; + } + objectscope = wrapper->GetScope(); + } XPCWrappedNativeScope *xpcscope = - XPCWrappedNativeScope::FindInJSObjectScope(aJSContext, aScope); + XPCWrappedNativeScope::FindInJSObjectScope(aJSContext, aScope); if(!xpcscope) return NS_ERROR_FAILURE; #ifdef DEBUG_mrbkap { @@ -2341,11 +2404,10 @@ OBJ_TO_INNER_OBJECT(aJSContext, toInnerize); NS_ASSERTION(toInnerize == scopeobj, "Scope chain ending in outer object?"); } #endif - XPCWrappedNativeScope *objectscope = wrapper->GetScope(); { JSObject *possibleOuter = objectscope->GetGlobalJSObject(); OBJ_TO_INNER_OBJECT(aJSContext, possibleOuter); if(!possibleOuter) return NS_ERROR_FAILURE; @@ -2370,15 +2432,24 @@ // or // - We're from the same *scope* AND // - We're not about to force a XOW (e.g. for "window") OR // - We're not actually going to create a XOW (we're wrapping for // chrome). - if(STOBJ_IS_SYSTEM(aObject) || + if(aObject->isSystem() || (sameScope && (!forceXOW || (aFilenameFlags & JSFILENAME_SYSTEM)))) return NS_OK; + if(!wrapper) + { + SLIM_LOG_WILL_MORPH(aJSContext, aObject); + if(!MorphSlimWrapper(aJSContext, aObject)) + return NS_ERROR_FAILURE; + + wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(aObject)); + } + JSObject* wrappedObj = nsnull; if(aFilenameFlags & JSFILENAME_PROTECTED) { wrappedObj = XPCNativeWrapper::GetNewOrUsed(aJSContext, wrapper, @@ -2539,9 +2610,61 @@ if(!data) return NS_ERROR_FAILURE; return data->GetJSContextStack()->SetSafeJSContext(aSafeJSContext); +} + +nsIPrincipal* +nsXPConnect::GetPrincipal(JSObject* obj, PRBool allowShortCircuit) const +{ + NS_ASSERTION(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj)) || IS_SLIM_WRAPPER(obj), + "What kind of wrapper is this?"); + + if(IS_WRAPPER_CLASS(STOBJ_GET_CLASS(obj))) + { + XPCWrappedNative *xpcWrapper = + (XPCWrappedNative *)xpc_GetJSPrivate(obj); + if (xpcWrapper) { + if (allowShortCircuit) { + nsIPrincipal *result = xpcWrapper->GetObjectPrincipal(); + if (result) { + return result; + } + } + + // If not, check if it points to an nsIScriptObjectPrincipal + nsCOMPtr<nsIScriptObjectPrincipal> objPrin = + do_QueryInterface(xpcWrapper->Native()); + if (objPrin) { + nsIPrincipal *result = objPrin->GetPrincipal(); + if (result) { + return result; + } + } + } + } + else + { + if (allowShortCircuit) { + nsIPrincipal *result = + GetSlimWrapperProto(obj)->GetScope()->GetPrincipal(); + if (result) { + return result; + } + } + + nsCOMPtr<nsIScriptObjectPrincipal> objPrin = + do_QueryInterface((nsISupports*)xpc_GetJSPrivate(obj)); + if (objPrin) { + nsIPrincipal *result = objPrin->GetPrincipal(); + if (result) { + return result; + } + } + } + + return nsnull; } /* These are here to be callable from a debugger */ JS_BEGIN_EXTERN_C JS_EXPORT_API(void) DumpJSStack()