Back to index

lightning-sunbird  0.9+nobinonly
nsXPConnect.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code, released
00017  * March 31, 1998.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1998
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   John Bandhauer <jband@netscape.com> (original author)
00026  *   Pierre Phaneuf <pp@ludusdesign.com>
00027  *   Nate Nielsen <nielsen@memberwebs.com>
00028  *
00029  * Alternatively, the contents of this file may be used under the terms of
00030  * either of the GNU General Public License Version 2 or later (the "GPL"),
00031  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00032  * in which case the provisions of the GPL or the LGPL are applicable instead
00033  * of those above. If you wish to allow use of your version of this file only
00034  * under the terms of either the GPL or the LGPL, and not to allow others to
00035  * use your version of this file under the terms of the MPL, indicate your
00036  * decision by deleting the provisions above and replace them with the notice
00037  * and other provisions required by the GPL or the LGPL. If you do not delete
00038  * the provisions above, a recipient may use your version of this file under
00039  * the terms of any one of the MPL, the GPL or the LGPL.
00040  *
00041  * ***** END LICENSE BLOCK ***** */
00042 
00043 /* High level class and public functions implementation. */
00044 
00045 #include "xpcprivate.h"
00046 #include "XPCNativeWrapper.h"
00047 
00048 NS_IMPL_THREADSAFE_ISUPPORTS5(nsXPConnect,
00049                               nsIXPConnect,
00050                               nsIXPConnect_MOZILLA_1_8_BRANCH,
00051                               nsIXPConnect_MOZILLA_1_8_BRANCH2,
00052                               nsISupportsWeakReference,
00053                               nsIEventQueueListener)
00054 
00055 nsXPConnect* nsXPConnect::gSelf = nsnull;
00056 JSBool       nsXPConnect::gOnceAliveNowDead = JS_FALSE;
00057 PRThread*    nsXPConnect::gMainThread = nsnull;
00058 
00059 const char XPC_CONTEXT_STACK_CONTRACTID[] = "@mozilla.org/js/xpc/ContextStack;1";
00060 const char XPC_RUNTIME_CONTRACTID[]       = "@mozilla.org/js/xpc/RuntimeService;1";
00061 const char XPC_EXCEPTION_CONTRACTID[]     = "@mozilla.org/js/xpc/Exception;1";
00062 const char XPC_CONSOLE_CONTRACTID[]       = "@mozilla.org/consoleservice;1";
00063 const char XPC_SCRIPT_ERROR_CONTRACTID[]  = "@mozilla.org/scripterror;1";
00064 const char XPC_ID_CONTRACTID[]            = "@mozilla.org/js/xpc/ID;1";
00065 const char XPC_XPCONNECT_CONTRACTID[]     = "@mozilla.org/js/xpc/XPConnect;1";
00066 
00067 /***************************************************************************/
00068 
00069 nsXPConnect::nsXPConnect()
00070     :   mRuntime(nsnull),
00071         mInterfaceInfoManager(nsnull),
00072         mContextStack(nsnull),
00073         mDefaultSecurityManager(nsnull),
00074         mDefaultSecurityManagerFlags(0),
00075         mShuttingDown(JS_FALSE)
00076 {
00077     // Ignore the result. If the runtime service is not ready to rumble
00078     // then we'll set this up later as needed.
00079     CreateRuntime();
00080 
00081     nsCOMPtr<nsIInterfaceInfoManager> iim = 
00082         dont_AddRef(XPTI_GetInterfaceInfoManager());
00083     CallQueryInterface(iim, &mInterfaceInfoManager);
00084 
00085     CallGetService(XPC_CONTEXT_STACK_CONTRACTID, &mContextStack);
00086 
00087 #ifdef XPC_TOOLS_SUPPORT
00088   {
00089     char* filename = PR_GetEnv("MOZILLA_JS_PROFILER_OUTPUT");
00090     if(filename && *filename)
00091     {
00092         mProfilerOutputFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
00093         if(mProfilerOutputFile &&
00094            NS_SUCCEEDED(mProfilerOutputFile->InitWithNativePath(nsDependentCString(filename))))
00095         {
00096             mProfiler = do_GetService(XPCTOOLS_PROFILER_CONTRACTID);
00097             if(mProfiler)
00098             {
00099                 if(NS_SUCCEEDED(mProfiler->Start()))
00100                 {
00101 #ifdef DEBUG
00102                     printf("***** profiling JavaScript. Output to: %s\n",
00103                            filename);
00104 #endif
00105                 }
00106             }
00107         }
00108     }
00109   }
00110 #endif
00111 
00112 }
00113 
00114 nsXPConnect::~nsXPConnect()
00115 {
00116     // XXX It would be nice if we could get away with doing a GC here and also
00117     // calling Release on the natives no longer reachable via XPConnect. As
00118     // noted all over the place, this makes bad things happen since shutdown is
00119     // an unstable time for so many modules who have not planned well for it.
00120 
00121     mShuttingDown = JS_TRUE;
00122     { // scoped callcontext
00123         XPCCallContext ccx(NATIVE_CALLER);
00124         if(ccx.IsValid())
00125         {
00126             XPCWrappedNativeScope::SystemIsBeingShutDown(ccx);
00127             if(mRuntime)
00128                 mRuntime->SystemIsBeingShutDown(&ccx);
00129                 
00130         }
00131     }
00132 
00133     NS_IF_RELEASE(mInterfaceInfoManager);
00134     NS_IF_RELEASE(mContextStack);
00135     NS_IF_RELEASE(mDefaultSecurityManager);
00136 
00137     // Unfortunately calling CleanupAllThreads before the stuff above
00138     // (esp. SystemIsBeingShutDown) causes too many bad things to happen
00139     // as the Release calls propagate. See the comment in this function in
00140     // revision 1.35 of this file.
00141     //
00142     // I filed a bug on xpcom regarding the bad things that happen
00143     // if people try to create components during shutdown.
00144     // http://bugzilla.mozilla.org/show_bug.cgi?id=37058
00145     //
00146     // Also, we just plain need the context stack for at least the current
00147     // thread to be in place. Unfortunately, this will leak stuff on the
00148     // stacks' safeJSContexts. But, this is a shutdown leak only.
00149 
00150     XPCPerThreadData::CleanupAllThreads();
00151 
00152     // shutdown the logging system
00153     XPC_LOG_FINISH();
00154 
00155     delete mRuntime;
00156 
00157     gSelf = nsnull;
00158     gOnceAliveNowDead = JS_TRUE;
00159 }
00160 
00161 // static
00162 nsXPConnect*
00163 nsXPConnect::GetXPConnect()
00164 {
00165     if(!gSelf)
00166     {
00167         if(gOnceAliveNowDead)
00168             return nsnull;
00169         gSelf = new nsXPConnect();
00170         if(!gSelf)
00171             return nsnull;
00172 
00173         if(!gSelf->mInterfaceInfoManager ||
00174            !gSelf->mContextStack)
00175         {
00176             // ctor failed to create an acceptable instance
00177             delete gSelf;
00178             gSelf = nsnull;
00179         }
00180         else
00181         {
00182             // Initial extra ref to keep the singleton alive
00183             // balanced by explicit call to ReleaseXPConnectSingleton()
00184             NS_ADDREF(gSelf);
00185         }
00186     }
00187     return gSelf;
00188 }
00189 
00190 // In order to enable this jsgc heap dumping you need to compile
00191 // _both_ js/src/jsgc.c and this file with 'GC_MARK_DEBUG' #defined.
00192 // Normally this is done by adding -DGC_MARK_DEBUG to the appropriate
00193 // defines lists in the makefiles.
00194 
00195 #ifdef GC_MARK_DEBUG
00196 extern "C" JS_FRIEND_DATA(FILE *) js_DumpGCHeap;
00197 #endif
00198 
00199 // static
00200 nsXPConnect*
00201 nsXPConnect::GetSingleton()
00202 {
00203     nsXPConnect* xpc = nsXPConnect::GetXPConnect();
00204     NS_IF_ADDREF(xpc);
00205     return xpc;
00206 }
00207 
00208 // static
00209 void
00210 nsXPConnect::ReleaseXPConnectSingleton()
00211 {
00212     nsXPConnect* xpc = gSelf;
00213     if(xpc)
00214     {
00215 
00216 #ifdef XPC_TOOLS_SUPPORT
00217         if(xpc->mProfiler)
00218         {
00219             xpc->mProfiler->Stop();
00220             xpc->mProfiler->WriteResults(xpc->mProfilerOutputFile);
00221         }
00222 #endif
00223 
00224 #ifdef GC_MARK_DEBUG
00225         // force a dump of the JavaScript gc heap if JS is still alive
00226         XPCCallContext ccx(NATIVE_CALLER);
00227         if(ccx.IsValid())
00228         {
00229             FILE* oldFileHandle = js_DumpGCHeap;
00230             js_DumpGCHeap = stdout;
00231             JS_GC(ccx);
00232             js_DumpGCHeap = oldFileHandle;
00233         }
00234 #endif
00235 #ifdef XPC_DUMP_AT_SHUTDOWN
00236         // NOTE: to see really interesting stuff turn on the prlog stuff.
00237         // See the comment at the top of xpclog.h to see how to do that.
00238         xpc->DebugDump(7);
00239 #endif
00240         nsrefcnt cnt;
00241         NS_RELEASE2(xpc, cnt);
00242 #ifdef XPC_DUMP_AT_SHUTDOWN
00243         if(0 != cnt)
00244             printf("*** dangling reference to nsXPConnect: refcnt=%d\n", cnt);
00245         else
00246             printf("+++ XPConnect had no dangling references.\n");
00247 #endif
00248     }
00249 }
00250 
00251 // static
00252 nsresult
00253 nsXPConnect::GetInterfaceInfoManager(nsIInterfaceInfoSuperManager** iim,
00254                                      nsXPConnect* xpc /*= nsnull*/)
00255 {
00256     if(!xpc && !(xpc = GetXPConnect()))
00257         return NS_ERROR_FAILURE;
00258 
00259     *iim = xpc->mInterfaceInfoManager;
00260     NS_IF_ADDREF(*iim);
00261     return NS_OK;
00262 }
00263 
00264 // static
00265 nsresult
00266 nsXPConnect::GetContextStack(nsIThreadJSContextStack** stack,
00267                              nsXPConnect* xpc /*= nsnull*/)
00268 {
00269     nsIThreadJSContextStack* temp;
00270 
00271     if(!xpc && !(xpc = GetXPConnect()))
00272         return NS_ERROR_FAILURE;
00273 
00274     *stack = temp = xpc->mContextStack;
00275     NS_IF_ADDREF(temp);
00276     return NS_OK;
00277 }
00278 
00279 // static
00280 XPCJSRuntime*
00281 nsXPConnect::GetRuntime(nsXPConnect* xpc /*= nsnull*/)
00282 {
00283     if(!xpc && !(xpc = GetXPConnect()))
00284         return nsnull;
00285 
00286     return xpc->EnsureRuntime() ? xpc->mRuntime : nsnull;
00287 }
00288 
00289 // static 
00290 nsIJSRuntimeService* 
00291 nsXPConnect::GetJSRuntimeService(nsXPConnect* xpc /* = nsnull */)
00292 {
00293     XPCJSRuntime* rt = GetRuntime(xpc); 
00294     return rt ? rt->GetJSRuntimeService() : nsnull;
00295 }
00296 
00297 // static
00298 XPCContext*
00299 nsXPConnect::GetContext(JSContext* cx, nsXPConnect* xpc /*= nsnull*/)
00300 {
00301     NS_PRECONDITION(cx,"bad param");
00302 
00303     XPCJSRuntime* rt = GetRuntime(xpc);
00304     if(!rt)
00305         return nsnull;
00306 
00307     if(rt->GetJSRuntime() != JS_GetRuntime(cx))
00308     {
00309         NS_WARNING("XPConnect was passed aJSContext from a foreign JSRuntime!");
00310         return nsnull;
00311     }
00312     return rt->GetXPCContext(cx);
00313 }
00314 
00315 // static
00316 JSBool
00317 nsXPConnect::IsISupportsDescendant(nsIInterfaceInfo* info)
00318 {
00319     PRBool found = PR_FALSE;
00320     if(info)
00321         info->HasAncestor(&NS_GET_IID(nsISupports), &found);
00322     return found;
00323 }
00324 
00325 JSBool
00326 nsXPConnect::CreateRuntime()
00327 {
00328     NS_ASSERTION(!mRuntime,"CreateRuntime called but mRuntime already init'd");
00329     nsresult rv;
00330     nsCOMPtr<nsIJSRuntimeService> rtsvc = 
00331              do_GetService(XPC_RUNTIME_CONTRACTID, &rv);
00332     if(NS_SUCCEEDED(rv) && rtsvc)
00333     {
00334         mRuntime = XPCJSRuntime::newXPCJSRuntime(this, rtsvc);
00335     }
00336     return nsnull != mRuntime;
00337 }
00338 
00339 // static 
00340 PRThread* 
00341 nsXPConnect::FindMainThread()
00342 {
00343     nsCOMPtr<nsIThread> t;
00344     nsresult rv;
00345     rv = nsIThread::GetMainThread(getter_AddRefs(t));
00346     NS_ASSERTION(NS_SUCCEEDED(rv) && t, "bad");
00347     rv = t->GetPRThread(&gMainThread);
00348     NS_ASSERTION(NS_SUCCEEDED(rv) && gMainThread, "bad");
00349     return gMainThread;
00350 }
00351 
00352 /***************************************************************************/
00353 
00354 typedef PRBool (*InfoTester)(nsIInterfaceInfoManager* manager, const void* data,
00355                              nsIInterfaceInfo** info);
00356 
00357 static PRBool IIDTester(nsIInterfaceInfoManager* manager, const void* data,
00358                         nsIInterfaceInfo** info)
00359 {
00360     return NS_SUCCEEDED(manager->GetInfoForIID((const nsIID *) data, info)) &&
00361            *info;
00362 }
00363 
00364 static PRBool NameTester(nsIInterfaceInfoManager* manager, const void* data,
00365                       nsIInterfaceInfo** info)
00366 {
00367     return NS_SUCCEEDED(manager->GetInfoForName((const char *) data, info)) &&
00368            *info;
00369 }
00370 
00371 static nsresult FindInfo(InfoTester tester, const void* data, 
00372                          nsIInterfaceInfoSuperManager* iism,
00373                          nsIInterfaceInfo** info)
00374 {
00375     if(tester(iism, data, info))
00376         return NS_OK;
00377     
00378     // If not found, then let's ask additional managers.
00379 
00380     PRBool yes;
00381     nsCOMPtr<nsISimpleEnumerator> list;
00382 
00383     if(NS_SUCCEEDED(iism->HasAdditionalManagers(&yes)) && yes &&
00384        NS_SUCCEEDED(iism->EnumerateAdditionalManagers(getter_AddRefs(list))) &&
00385        list)
00386     {
00387         PRBool more;
00388         nsCOMPtr<nsIInterfaceInfoManager> current;
00389 
00390         while(NS_SUCCEEDED(list->HasMoreElements(&more)) && more &&
00391               NS_SUCCEEDED(list->GetNext(getter_AddRefs(current))) && current)
00392         {
00393             if(tester(current, data, info))
00394                 return NS_OK;
00395         }
00396     }
00397     
00398     return NS_ERROR_NO_INTERFACE;
00399 }    
00400 
00401 nsresult
00402 nsXPConnect::GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info)
00403 {
00404     return FindInfo(IIDTester, aIID, mInterfaceInfoManager, info);
00405 }
00406 
00407 nsresult
00408 nsXPConnect::GetInfoForName(const char * name, nsIInterfaceInfo** info)
00409 {
00410     return FindInfo(NameTester, name, mInterfaceInfoManager, info);
00411 }
00412 
00413 /***************************************************************************/
00414 /***************************************************************************/
00415 // nsIXPConnect interface methods...
00416 
00417 inline nsresult UnexpectedFailure(nsresult rv)
00418 {
00419     NS_ERROR("This is not supposed to fail!");
00420     return rv;
00421 }
00422 
00423 class SaveFrame
00424 {
00425 public:
00426     SaveFrame(JSContext *cx)
00427         : mJSContext(cx) {
00428         mFrame = JS_SaveFrameChain(mJSContext);
00429     }
00430 
00431     ~SaveFrame() {
00432         JS_RestoreFrameChain(mJSContext, mFrame);
00433     }
00434 
00435 private:
00436     JSContext *mJSContext;
00437     JSStackFrame *mFrame;
00438 };
00439 
00440 /* void initClasses (in JSContextPtr aJSContext, in JSObjectPtr aGlobalJSObj); */
00441 NS_IMETHODIMP
00442 nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
00443 {
00444     NS_ASSERTION(aJSContext, "bad param");
00445     NS_ASSERTION(aGlobalJSObj, "bad param");
00446 
00447     SaveFrame sf(aJSContext);
00448     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00449     if(!ccx.IsValid())
00450         return UnexpectedFailure(NS_ERROR_FAILURE);
00451 
00452     if(!xpc_InitJSxIDClassObjects())
00453         return UnexpectedFailure(NS_ERROR_FAILURE);
00454 
00455     if(!xpc_InitWrappedNativeJSOps())
00456         return UnexpectedFailure(NS_ERROR_FAILURE);
00457 
00458     XPCWrappedNativeScope* scope =
00459         XPCWrappedNativeScope::GetNewOrUsed(ccx, aGlobalJSObj);
00460 
00461     if(!scope)
00462         return UnexpectedFailure(NS_ERROR_FAILURE);
00463 
00464     scope->RemoveWrappedNativeProtos();
00465 
00466     if(!nsXPCComponents::AttachNewComponentsObject(ccx, scope, aGlobalJSObj))
00467         return UnexpectedFailure(NS_ERROR_FAILURE);
00468 
00469 #ifdef XPC_IDISPATCH_SUPPORT
00470     // Initialize any properties IDispatch needs on the global object
00471     XPCIDispatchExtension::Initialize(ccx, aGlobalJSObj);
00472 #endif
00473 
00474     if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, aGlobalJSObj))
00475         return UnexpectedFailure(NS_ERROR_FAILURE);
00476 
00477     return NS_OK;
00478 }
00479 
00480 JS_STATIC_DLL_CALLBACK(JSBool)
00481 TempGlobalResolve(JSContext *aJSContext, JSObject *obj, jsval id)
00482 {
00483     JSBool resolved;
00484     return JS_ResolveStandardClass(aJSContext, obj, id, &resolved);
00485 }
00486 
00487 static JSClass xpcTempGlobalClass = {
00488     "xpcTempGlobalClass", 0,
00489     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,
00490     JS_EnumerateStub, TempGlobalResolve, JS_ConvertStub,   JS_FinalizeStub,
00491     JSCLASS_NO_OPTIONAL_MEMBERS
00492 };
00493 
00494 /* nsIXPConnectJSObjectHolder initClassesWithNewWrappedGlobal (in JSContextPtr aJSContext, in nsISupports aCOMObj, in nsIIDRef aIID, in PRUint32 aFlags); */
00495 NS_IMETHODIMP
00496 nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
00497                                              nsISupports *aCOMObj,
00498                                              const nsIID & aIID,
00499                                              PRUint32 aFlags,
00500                                              nsIXPConnectJSObjectHolder **_retval)
00501 {
00502     NS_ASSERTION(aJSContext, "bad param");
00503     NS_ASSERTION(aCOMObj, "bad param");
00504     NS_ASSERTION(_retval, "bad param");
00505 
00506     // XXX This is not pretty. We make a temporary global object and
00507     // init it with all the Components object junk just so we have a
00508     // parent with an xpc scope to use when wrapping the object that will
00509     // become the 'real' global.
00510 
00511     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00512 
00513     JSObject* tempGlobal = JS_NewObject(aJSContext, &xpcTempGlobalClass,
00514                                         nsnull, nsnull);
00515 
00516     if(!tempGlobal ||
00517        !JS_SetParent(aJSContext, tempGlobal, nsnull) ||
00518        !JS_SetPrototype(aJSContext, tempGlobal, nsnull))
00519         return UnexpectedFailure(NS_ERROR_FAILURE);
00520 
00521     if(aFlags & nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT)
00522         JS_FlagSystemObject(aJSContext, tempGlobal);
00523 
00524     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
00525     {
00526         // Scope for our auto-marker; it just needs to keep tempGlobal alive
00527         // long enough for InitClasses and WrapNative to do their work
00528         AUTO_MARK_JSVAL(ccx, OBJECT_TO_JSVAL(tempGlobal));
00529 
00530         if(NS_FAILED(InitClasses(aJSContext, tempGlobal)))
00531             return UnexpectedFailure(NS_ERROR_FAILURE);
00532 
00533         nsresult rv;
00534         if(!XPCConvert::NativeInterface2JSObject(ccx, getter_AddRefs(holder),
00535                                                  aCOMObj, &aIID, tempGlobal,
00536                                                  PR_FALSE, OBJ_IS_GLOBAL, &rv))
00537             return UnexpectedFailure(rv);
00538 
00539         NS_ASSERTION(NS_SUCCEEDED(rv) && holder, "Didn't wrap properly");
00540     }
00541 
00542     JSObject* globalJSObj;
00543     if(NS_FAILED(holder->GetJSObject(&globalJSObj)) || !globalJSObj)
00544         return UnexpectedFailure(NS_ERROR_FAILURE);
00545 
00546     if(aFlags & nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT)
00547         NS_ASSERTION(JS_IsSystemObject(aJSContext, globalJSObj), "huh?!");
00548 
00549     // voodoo to fixup scoping and parenting...
00550 
00551     JS_SetParent(aJSContext, globalJSObj, nsnull);
00552 
00553     JSObject* oldGlobal = JS_GetGlobalObject(aJSContext);
00554     if(!oldGlobal || oldGlobal == tempGlobal)
00555         JS_SetGlobalObject(aJSContext, globalJSObj);
00556 
00557     if((aFlags & nsIXPConnect::INIT_JS_STANDARD_CLASSES) &&
00558        !JS_InitStandardClasses(aJSContext, globalJSObj))
00559         return UnexpectedFailure(NS_ERROR_FAILURE);
00560 
00561     XPCWrappedNative* wrapper =
00562         NS_REINTERPRET_CAST(XPCWrappedNative*, holder.get());
00563     XPCWrappedNativeScope* scope = wrapper->GetScope();
00564 
00565     if(!scope)
00566         return UnexpectedFailure(NS_ERROR_FAILURE);
00567 
00568     NS_ASSERTION(scope->GetGlobalJSObject() == tempGlobal, "stealing scope!");
00569 
00570     scope->SetGlobal(ccx, globalJSObj);
00571 
00572     JSObject* protoJSObject = wrapper->HasProto() ?
00573                                     wrapper->GetProto()->GetJSProtoObject() :
00574                                     globalJSObj;
00575     if(protoJSObject)
00576     {
00577         if(protoJSObject != globalJSObj)
00578             JS_SetParent(aJSContext, protoJSObject, globalJSObj);
00579         JS_SetPrototype(aJSContext, protoJSObject, scope->GetPrototypeJSObject());
00580     }
00581 
00582     SaveFrame sf(ccx);
00583     if(!nsXPCComponents::AttachNewComponentsObject(ccx, scope, globalJSObj))
00584         return UnexpectedFailure(NS_ERROR_FAILURE);
00585 
00586     if (!XPCNativeWrapper::AttachNewConstructorObject(ccx, globalJSObj))
00587         return UnexpectedFailure(NS_ERROR_FAILURE);
00588 
00589     NS_ADDREF(*_retval = holder);
00590 
00591     return NS_OK;
00592 }
00593 
00594 /* nsIXPConnectJSObjectHolder wrapNative (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDRef aIID); */
00595 NS_IMETHODIMP
00596 nsXPConnect::WrapNative(JSContext * aJSContext,
00597                         JSObject * aScope,
00598                         nsISupports *aCOMObj,
00599                         const nsIID & aIID,
00600                         nsIXPConnectJSObjectHolder **_retval)
00601 {
00602     NS_ASSERTION(aJSContext, "bad param");
00603     NS_ASSERTION(aScope, "bad param");
00604     NS_ASSERTION(aCOMObj, "bad param");
00605     NS_ASSERTION(_retval, "bad param");
00606 
00607     *_retval = nsnull;
00608 
00609     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00610     if(!ccx.IsValid())
00611         return UnexpectedFailure(NS_ERROR_FAILURE);
00612 
00613     nsresult rv;
00614     if(!XPCConvert::NativeInterface2JSObject(ccx, _retval, aCOMObj, &aIID,
00615                                              aScope, PR_FALSE,
00616                                              OBJ_IS_NOT_GLOBAL, &rv))
00617         return rv;
00618 
00619 #ifdef DEBUG
00620     JSObject* returnObj;
00621     (*_retval)->GetJSObject(&returnObj);
00622     NS_ASSERTION(!XPCNativeWrapper::IsNativeWrapper(aJSContext, returnObj),
00623                  "Shouldn't be returning a native wrapper here");
00624 #endif
00625     
00626     return NS_OK;
00627 }
00628 
00629 /* void wrapJS (in JSContextPtr aJSContext, in JSObjectPtr aJSObj, in nsIIDRef aIID, [iid_is (aIID), retval] out nsQIResult result); */
00630 NS_IMETHODIMP
00631 nsXPConnect::WrapJS(JSContext * aJSContext,
00632                     JSObject * aJSObj,
00633                     const nsIID & aIID,
00634                     void * *result)
00635 {
00636     NS_ASSERTION(aJSContext, "bad param");
00637     NS_ASSERTION(aJSObj, "bad param");
00638     NS_ASSERTION(result, "bad param");
00639 
00640     *result = nsnull;
00641 
00642     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00643     if(!ccx.IsValid())
00644         return UnexpectedFailure(NS_ERROR_FAILURE);
00645 
00646     nsresult rv;
00647     if(!XPCConvert::JSObject2NativeInterface(ccx, result, aJSObj,
00648                                              &aIID, nsnull, &rv))
00649         return rv;
00650     return NS_OK;
00651 }
00652 
00653 /* void wrapJSAggregatedToNative (in nsISupports aOuter, in JSContextPtr aJSContext, in JSObjectPtr aJSObj, in nsIIDRef aIID, [iid_is (aIID), retval] out nsQIResult result); */
00654 NS_IMETHODIMP
00655 nsXPConnect::WrapJSAggregatedToNative(nsISupports *aOuter,
00656                                       JSContext * aJSContext,
00657                                       JSObject * aJSObj,
00658                                       const nsIID & aIID,
00659                                       void * *result)
00660 {
00661     NS_ASSERTION(aOuter, "bad param");
00662     NS_ASSERTION(aJSContext, "bad param");
00663     NS_ASSERTION(aJSObj, "bad param");
00664     NS_ASSERTION(result, "bad param");
00665 
00666     *result = nsnull;
00667 
00668     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00669     if(!ccx.IsValid())
00670         return UnexpectedFailure(NS_ERROR_FAILURE);
00671 
00672     nsresult rv;
00673     if(!XPCConvert::JSObject2NativeInterface(ccx, result, aJSObj,
00674                                              &aIID, aOuter, &rv))
00675         return rv;
00676     return NS_OK;
00677 }
00678 
00679 /* nsIXPConnectWrappedNative getWrappedNativeOfJSObject (in JSContextPtr aJSContext, in JSObjectPtr aJSObj); */
00680 NS_IMETHODIMP
00681 nsXPConnect::GetWrappedNativeOfJSObject(JSContext * aJSContext,
00682                                         JSObject * aJSObj,
00683                                         nsIXPConnectWrappedNative **_retval)
00684 {
00685     NS_ASSERTION(aJSContext, "bad param");
00686     NS_ASSERTION(aJSObj, "bad param");
00687     NS_ASSERTION(_retval, "bad param");
00688 
00689     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00690     if(!ccx.IsValid())
00691         return UnexpectedFailure(NS_ERROR_FAILURE);
00692 
00693     nsIXPConnectWrappedNative* wrapper =
00694         XPCWrappedNative::GetWrappedNativeOfJSObject(aJSContext, aJSObj);
00695     if(wrapper)
00696     {
00697         NS_ADDREF(wrapper);
00698         *_retval = wrapper;
00699         return NS_OK;
00700     }
00701     // else...
00702     *_retval = nsnull;
00703     return NS_ERROR_FAILURE;
00704 }
00705 
00706 /* nsIXPConnectWrappedNative getWrappedNativeOfNativeObject (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsISupports aCOMObj, in nsIIDRef aIID); */
00707 NS_IMETHODIMP
00708 nsXPConnect::GetWrappedNativeOfNativeObject(JSContext * aJSContext,
00709                                             JSObject * aScope,
00710                                             nsISupports *aCOMObj,
00711                                             const nsIID & aIID,
00712                                             nsIXPConnectWrappedNative **_retval)
00713 {
00714     NS_ASSERTION(aJSContext, "bad param");
00715     NS_ASSERTION(aScope, "bad param");
00716     NS_ASSERTION(aCOMObj, "bad param");
00717     NS_ASSERTION(_retval, "bad param");
00718 
00719     *_retval = nsnull;
00720 
00721     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00722     if(!ccx.IsValid())
00723         return UnexpectedFailure(NS_ERROR_FAILURE);
00724 
00725     XPCWrappedNativeScope* scope =
00726         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope);
00727     if(!scope)
00728         return UnexpectedFailure(NS_ERROR_FAILURE);
00729 
00730     AutoMarkingNativeInterfacePtr iface(ccx);
00731     iface = XPCNativeInterface::GetNewOrUsed(ccx, &aIID);
00732     if(!iface)
00733         return NS_ERROR_FAILURE;
00734 
00735     XPCWrappedNative* wrapper;
00736 
00737     nsresult rv = XPCWrappedNative::GetUsedOnly(ccx, aCOMObj, scope, iface,
00738                                                 &wrapper);
00739     if(NS_FAILED(rv))
00740         return NS_ERROR_FAILURE;
00741     *_retval = NS_STATIC_CAST(nsIXPConnectWrappedNative*, wrapper);
00742     return NS_OK;
00743 }
00744 
00745 /* nsIXPConnectJSObjectHolder reparentWrappedNativeIfFound (in JSContextPtr aJSContext, in JSObjectPtr aScope, in JSObjectPtr aNewParent, in nsISupports aCOMObj); */
00746 NS_IMETHODIMP
00747 nsXPConnect::ReparentWrappedNativeIfFound(JSContext * aJSContext,
00748                                           JSObject * aScope,
00749                                           JSObject * aNewParent,
00750                                           nsISupports *aCOMObj,
00751                                           nsIXPConnectJSObjectHolder **_retval)
00752 {
00753     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00754     if(!ccx.IsValid())
00755         return UnexpectedFailure(NS_ERROR_FAILURE);
00756 
00757     XPCWrappedNativeScope* scope =
00758         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope);
00759     if(!scope)
00760         return UnexpectedFailure(NS_ERROR_FAILURE);
00761 
00762     XPCWrappedNativeScope* scope2 =
00763         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aNewParent);
00764     if(!scope2)
00765         return UnexpectedFailure(NS_ERROR_FAILURE);
00766 
00767     return XPCWrappedNative::
00768         ReparentWrapperIfFound(ccx, scope, scope2, aNewParent, aCOMObj,
00769                                (XPCWrappedNative**) _retval);
00770 }
00771 
00772 JS_STATIC_DLL_CALLBACK(JSDHashOperator)
00773 MoveableWrapperFinder(JSDHashTable *table, JSDHashEntryHdr *hdr,
00774                       uint32 number, void *arg)
00775 {
00776     // Every element counts.
00777     nsVoidArray *va = NS_STATIC_CAST(nsVoidArray *,arg);
00778     va->AppendElement(((Native2WrappedNativeMap::Entry*)hdr)->value);
00779     return JS_DHASH_NEXT;
00780 }
00781 
00782 /* void reparentScopeAwareWrappers(in JSContextPtr aJSContext, in JSObjectPtr  aOldScope, in JSObjectPtr  aNewScope); */
00783 NS_IMETHODIMP
00784 nsXPConnect::ReparentScopeAwareWrappers(JSContext *aJSContext,
00785                                         JSObject *aOldScope,
00786                                         JSObject *aNewScope)
00787 {
00788     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00789     if(!ccx.IsValid())
00790         return UnexpectedFailure(NS_ERROR_FAILURE);
00791 
00792     XPCWrappedNativeScope *oldScope =
00793         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aOldScope);
00794     if(!oldScope)
00795         return UnexpectedFailure(NS_ERROR_FAILURE);
00796 
00797     XPCWrappedNativeScope *newScope =
00798         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aNewScope);
00799     if(!newScope)
00800         return UnexpectedFailure(NS_ERROR_FAILURE);
00801 
00802     {   // scoped lock
00803         XPCAutoLock lock(oldScope->GetRuntime()->GetMapLock());
00804 
00805         // First, look through the old scope and find all of the wrappers that
00806         // we're going to move.
00807 
00808         Native2WrappedNativeMap *map = oldScope->GetWrappedNativeMap();
00809         nsVoidArray wrappersToMove(map->Count());
00810         map->Enumerate(MoveableWrapperFinder, &wrappersToMove);
00811 
00812         // Now that we have the wrappers, reparent them to the new scope.
00813         for(PRInt32 i = 0, stop = wrappersToMove.Count(); i < stop; ++i)
00814         {
00815             // First, check to see if this wrapper really needs to be
00816             // reparented.
00817 
00818             XPCWrappedNative *wrapper =
00819                 NS_STATIC_CAST(XPCWrappedNative *, wrappersToMove[i]);
00820             nsISupports *identity = wrapper->GetIdentityObject();
00821             nsCOMPtr<nsIClassInfo> info(do_QueryInterface(identity));
00822 
00823             // ClassInfo is implemented as singleton objects. If the identity
00824             // object here is the same object as returned by the QI, then it
00825             // is the singleton classinfo, so we don't need to reparent it.
00826             if(SameCOMIdentity(identity, info))
00827                 info = nsnull;
00828 
00829             if(!info)
00830                 continue;
00831 
00832             XPCNativeScriptableCreateInfo sciProto;
00833             XPCNativeScriptableCreateInfo sciWrapper;
00834 
00835             nsresult rv =
00836                 XPCWrappedNative::GatherScriptableCreateInfo(identity,
00837                                                              info.get(),
00838                                                              &sciProto,
00839                                                              &sciWrapper);
00840             if(NS_FAILED(rv))
00841                 return NS_ERROR_FAILURE;
00842 
00843             // If the wrapper doesn't want precreate, then we don't need to
00844             // worry about reparenting it.
00845             if(!sciWrapper.GetFlags().WantPreCreate())
00846                 continue;
00847 
00848             JSObject *newParent = aOldScope;
00849             rv = sciWrapper.GetCallback()->PreCreate(identity, ccx, aOldScope,
00850                                                      &newParent);
00851             if(NS_FAILED(rv))
00852                 return rv;
00853 
00854             if(newParent != aOldScope)
00855             {
00856                 // The wrapper returned a new parent. If the new parent is in
00857                 // a different scope, then we need to reparent it, otherwise,
00858                 // the old scope is fine.
00859 
00860                 XPCWrappedNativeScope *betterScope =
00861                     XPCWrappedNativeScope::FindInJSObjectScope(ccx, newParent);
00862                 if(betterScope == oldScope)
00863                     continue;
00864 
00865                 NS_ASSERTION(betterScope == newScope, "Weird scope returned");
00866             }
00867             else
00868             {
00869                 // The old scope still works for this wrapper.
00870                 continue;
00871             }
00872 
00873             // Now, reparent the wrapper, since we know that it wants to be
00874             // reparented.
00875 
00876             nsRefPtr<XPCWrappedNative> junk;
00877             rv = XPCWrappedNative::ReparentWrapperIfFound(ccx, oldScope,
00878                                                           newScope, newParent,
00879                                                           wrapper->GetIdentityObject(),
00880                                                           getter_AddRefs(junk));
00881             NS_ENSURE_SUCCESS(rv, rv);
00882         }
00883     }
00884 
00885     return NS_OK;
00886 }
00887 
00888 /* void setSecurityManagerForJSContext (in JSContextPtr aJSContext, in nsIXPCSecurityManager aManager, in PRUint16 flags); */
00889 NS_IMETHODIMP
00890 nsXPConnect::SetSecurityManagerForJSContext(JSContext * aJSContext,
00891                                             nsIXPCSecurityManager *aManager,
00892                                             PRUint16 flags)
00893 {
00894     NS_ASSERTION(aJSContext, "bad param");
00895 
00896     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00897     if(!ccx.IsValid())
00898         return UnexpectedFailure(NS_ERROR_FAILURE);
00899 
00900     XPCContext* xpcc = ccx.GetXPCContext();
00901 
00902     NS_IF_ADDREF(aManager);
00903     nsIXPCSecurityManager* oldManager = xpcc->GetSecurityManager();
00904     NS_IF_RELEASE(oldManager);
00905 
00906     xpcc->SetSecurityManager(aManager);
00907     xpcc->SetSecurityManagerFlags(flags);
00908     return NS_OK;
00909 }
00910 
00911 /* void getSecurityManagerForJSContext (in JSContextPtr aJSContext, out nsIXPCSecurityManager aManager, out PRUint16 flags); */
00912 NS_IMETHODIMP
00913 nsXPConnect::GetSecurityManagerForJSContext(JSContext * aJSContext,
00914                                             nsIXPCSecurityManager **aManager,
00915                                             PRUint16 *flags)
00916 {
00917     NS_ASSERTION(aJSContext, "bad param");
00918     NS_ASSERTION(aManager, "bad param");
00919     NS_ASSERTION(flags, "bad param");
00920 
00921     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
00922     if(!ccx.IsValid())
00923         return UnexpectedFailure(NS_ERROR_FAILURE);
00924 
00925     XPCContext* xpcc = ccx.GetXPCContext();
00926 
00927     nsIXPCSecurityManager* manager = xpcc->GetSecurityManager();
00928     NS_IF_ADDREF(manager);
00929     *aManager = manager;
00930     *flags = xpcc->GetSecurityManagerFlags();
00931     return NS_OK;
00932 }
00933 
00934 /* void setDefaultSecurityManager (in nsIXPCSecurityManager aManager, in PRUint16 flags); */
00935 NS_IMETHODIMP
00936 nsXPConnect::SetDefaultSecurityManager(nsIXPCSecurityManager *aManager,
00937                                        PRUint16 flags)
00938 {
00939     NS_IF_ADDREF(aManager);
00940     NS_IF_RELEASE(mDefaultSecurityManager);
00941     mDefaultSecurityManager = aManager;
00942     mDefaultSecurityManagerFlags = flags;
00943     return NS_OK;
00944 }
00945 
00946 /* void getDefaultSecurityManager (out nsIXPCSecurityManager aManager, out PRUint16 flags); */
00947 NS_IMETHODIMP
00948 nsXPConnect::GetDefaultSecurityManager(nsIXPCSecurityManager **aManager,
00949                                        PRUint16 *flags)
00950 {
00951     NS_ASSERTION(aManager, "bad param");
00952     NS_ASSERTION(flags, "bad param");
00953 
00954     NS_IF_ADDREF(mDefaultSecurityManager);
00955     *aManager = mDefaultSecurityManager;
00956     *flags = mDefaultSecurityManagerFlags;
00957     return NS_OK;
00958 }
00959 
00960 /* nsIStackFrame createStackFrameLocation (in PRUint32 aLanguage, in string aFilename, in string aFunctionName, in PRInt32 aLineNumber, in nsIStackFrame aCaller); */
00961 NS_IMETHODIMP
00962 nsXPConnect::CreateStackFrameLocation(PRUint32 aLanguage,
00963                                       const char *aFilename,
00964                                       const char *aFunctionName,
00965                                       PRInt32 aLineNumber,
00966                                       nsIStackFrame *aCaller,
00967                                       nsIStackFrame **_retval)
00968 {
00969     NS_ASSERTION(_retval, "bad param");
00970 
00971     return XPCJSStack::CreateStackFrameLocation(aLanguage,
00972                                                 aFilename,
00973                                                 aFunctionName,
00974                                                 aLineNumber,
00975                                                 aCaller,
00976                                                 _retval);
00977 }
00978 
00979 /* readonly attribute nsIStackFrame CurrentJSStack; */
00980 NS_IMETHODIMP
00981 nsXPConnect::GetCurrentJSStack(nsIStackFrame * *aCurrentJSStack)
00982 {
00983     NS_ASSERTION(aCurrentJSStack, "bad param");
00984     *aCurrentJSStack = nsnull;
00985 
00986     JSContext* cx;
00987     // is there a current context available?
00988     if(mContextStack && NS_SUCCEEDED(mContextStack->Peek(&cx)) && cx)
00989     {
00990         nsCOMPtr<nsIStackFrame> stack;
00991         XPCJSStack::CreateStack(cx, getter_AddRefs(stack));
00992         if(stack)
00993         {
00994             // peel off native frames...
00995             PRUint32 language;
00996             nsCOMPtr<nsIStackFrame> caller;
00997             while(stack &&
00998                   NS_SUCCEEDED(stack->GetLanguage(&language)) &&
00999                   language != nsIProgrammingLanguage::JAVASCRIPT &&
01000                   NS_SUCCEEDED(stack->GetCaller(getter_AddRefs(caller))) &&
01001                   caller)
01002             {
01003                 stack = caller;
01004             }
01005             NS_IF_ADDREF(*aCurrentJSStack = stack);
01006         }
01007     }
01008     return NS_OK;
01009 }
01010 
01011 /* readonly attribute nsIXPCNativeCallContext CurrentNativeCallContext; */
01012 NS_IMETHODIMP
01013 nsXPConnect::GetCurrentNativeCallContext(nsIXPCNativeCallContext * *aCurrentNativeCallContext)
01014 {
01015     NS_ASSERTION(aCurrentNativeCallContext, "bad param");
01016 
01017     XPCPerThreadData* data = XPCPerThreadData::GetData();
01018     if(data)
01019     {
01020         nsIXPCNativeCallContext* temp = data->GetCallContext();
01021         NS_IF_ADDREF(temp);
01022         *aCurrentNativeCallContext = temp;
01023         return NS_OK;
01024     }
01025     //else...
01026     *aCurrentNativeCallContext = nsnull;
01027     return UnexpectedFailure(NS_ERROR_FAILURE);
01028 }
01029 
01030 /* attribute nsIException PendingException; */
01031 NS_IMETHODIMP
01032 nsXPConnect::GetPendingException(nsIException * *aPendingException)
01033 {
01034     NS_ASSERTION(aPendingException, "bad param");
01035 
01036     XPCPerThreadData* data = XPCPerThreadData::GetData();
01037     if(!data)
01038     {
01039         *aPendingException = nsnull;
01040         return UnexpectedFailure(NS_ERROR_FAILURE);
01041     }
01042 
01043     return data->GetException(aPendingException);
01044 }
01045 
01046 NS_IMETHODIMP
01047 nsXPConnect::SetPendingException(nsIException * aPendingException)
01048 {
01049     XPCPerThreadData* data = XPCPerThreadData::GetData();
01050     if(!data)
01051         return UnexpectedFailure(NS_ERROR_FAILURE);
01052 
01053     data->SetException(aPendingException);
01054     return NS_OK;
01055 }
01056 
01057 /* void syncJSContexts (); */
01058 NS_IMETHODIMP
01059 nsXPConnect::SyncJSContexts(void)
01060 {
01061     XPCJSRuntime* rt = GetRuntime(this);
01062     if(rt)
01063         rt->SyncXPCContextList();
01064     return NS_OK;
01065 }
01066 
01067 /* nsIXPCFunctionThisTranslator setFunctionThisTranslator (in nsIIDRef aIID, in nsIXPCFunctionThisTranslator aTranslator); */
01068 NS_IMETHODIMP
01069 nsXPConnect::SetFunctionThisTranslator(const nsIID & aIID,
01070                                        nsIXPCFunctionThisTranslator *aTranslator,
01071                                        nsIXPCFunctionThisTranslator **_retval)
01072 {
01073     XPCJSRuntime* rt = GetRuntime(this);
01074     if(!rt)
01075         return NS_ERROR_UNEXPECTED;
01076 
01077     nsIXPCFunctionThisTranslator* old;
01078     IID2ThisTranslatorMap* map = rt->GetThisTranslatorMap();
01079 
01080     {
01081         XPCAutoLock lock(rt->GetMapLock()); // scoped lock
01082         if(_retval)
01083         {
01084             old = map->Find(aIID);
01085             NS_IF_ADDREF(old);
01086             *_retval = old;
01087         }
01088         map->Add(aIID, aTranslator);
01089     }
01090     return NS_OK;
01091 }
01092 
01093 /* nsIXPCFunctionThisTranslator getFunctionThisTranslator (in nsIIDRef aIID); */
01094 NS_IMETHODIMP
01095 nsXPConnect::GetFunctionThisTranslator(const nsIID & aIID,
01096                                        nsIXPCFunctionThisTranslator **_retval)
01097 {
01098     XPCJSRuntime* rt = GetRuntime(this);
01099     if(!rt)
01100         return NS_ERROR_UNEXPECTED;
01101 
01102     nsIXPCFunctionThisTranslator* old;
01103     IID2ThisTranslatorMap* map = rt->GetThisTranslatorMap();
01104 
01105     {
01106         XPCAutoLock lock(rt->GetMapLock()); // scoped lock
01107         old = map->Find(aIID);
01108         NS_IF_ADDREF(old);
01109         *_retval = old;
01110     }
01111     return NS_OK;
01112 }
01113 
01114 /* void setSafeJSContextForCurrentThread (in JSContextPtr cx); */
01115 NS_IMETHODIMP 
01116 nsXPConnect::SetSafeJSContextForCurrentThread(JSContext * cx)
01117 {
01118     XPCCallContext ccx(NATIVE_CALLER);
01119     if(!ccx.IsValid())
01120         return UnexpectedFailure(NS_ERROR_FAILURE);
01121     return ccx.GetThreadData()->GetJSContextStack()->SetSafeJSContext(cx);
01122 }
01123 
01124 /* void clearAllWrappedNativeSecurityPolicies (); */
01125 NS_IMETHODIMP
01126 nsXPConnect::ClearAllWrappedNativeSecurityPolicies()
01127 {
01128     XPCCallContext ccx(NATIVE_CALLER);
01129     if(!ccx.IsValid())
01130         return UnexpectedFailure(NS_ERROR_FAILURE);
01131 
01132     return XPCWrappedNativeScope::ClearAllWrappedNativeSecurityPolicies(ccx);
01133 }
01134 
01135 /* void restoreWrappedNativePrototype (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsIClassInfo aClassInfo, in nsIXPConnectJSObjectHolder aPrototype); */
01136 NS_IMETHODIMP 
01137 nsXPConnect::RestoreWrappedNativePrototype(JSContext * aJSContext, 
01138                                            JSObject * aScope, 
01139                                            nsIClassInfo * aClassInfo, 
01140                                            nsIXPConnectJSObjectHolder * aPrototype)
01141 {
01142     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
01143     if(!ccx.IsValid())
01144         return UnexpectedFailure(NS_ERROR_FAILURE);
01145 
01146     if(!aClassInfo || !aPrototype)
01147         return UnexpectedFailure(NS_ERROR_INVALID_ARG);
01148 
01149     JSObject *protoJSObject;
01150     nsresult rv = aPrototype->GetJSObject(&protoJSObject);
01151     if(NS_FAILED(rv))
01152         return UnexpectedFailure(rv);
01153 
01154     if(!IS_PROTO_CLASS(JS_GET_CLASS(ccx, protoJSObject)))
01155         return UnexpectedFailure(NS_ERROR_INVALID_ARG);
01156 
01157     XPCWrappedNativeScope* scope =
01158         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope);
01159     if(!scope)
01160         return UnexpectedFailure(NS_ERROR_FAILURE);
01161 
01162     XPCWrappedNativeProto *proto =
01163         (XPCWrappedNativeProto*)JS_GetPrivate(ccx, protoJSObject);
01164     if(!proto)
01165         return UnexpectedFailure(NS_ERROR_FAILURE);
01166 
01167     if(scope != proto->GetScope())
01168     {
01169         NS_ERROR("Attempt to reset prototype to a prototype from a"
01170                  "different scope!");
01171 
01172         return UnexpectedFailure(NS_ERROR_INVALID_ARG);
01173     }
01174 
01175     XPCNativeScriptableInfo *si = proto->GetScriptableInfo();
01176 
01177     if(si && si->GetFlags().DontSharePrototype())
01178         return UnexpectedFailure(NS_ERROR_INVALID_ARG);
01179 
01180     ClassInfo2WrappedNativeProtoMap* map = scope->GetWrappedNativeProtoMap();
01181     XPCLock* lock = scope->GetRuntime()->GetMapLock();
01182 
01183     {   // scoped lock
01184         XPCAutoLock al(lock);
01185 
01186         XPCWrappedNativeProtoMap* detachedMap =
01187             GetRuntime()->GetDetachedWrappedNativeProtoMap();
01188 
01189         // If we're replacing an old proto, make sure to put it on the
01190         // map of detached wrapped native protos so that the old proto
01191         // gets properly cleaned up, especially during shutdown.
01192         XPCWrappedNativeProto *oldProto = map->Find(aClassInfo);
01193         if (oldProto) {
01194             detachedMap->Add(oldProto);
01195 
01196             // ClassInfo2WrappedNativeProtoMap doesn't ever replace
01197             // entries in the map, so now since we know there's an
01198             // entry for aClassInfo in the map we haveto remove it to
01199             // be able to add the new one.
01200             map->Remove(aClassInfo);
01201 
01202             // This code should do the right thing even if we're
01203             // restoring the current proto, but warn in that case
01204             // since doing that is pointless.
01205             NS_WARN_IF_FALSE(proto != oldProto,
01206                              "Restoring current prototype, fix caller!");
01207         }
01208 
01209         map->Add(aClassInfo, proto);
01210 
01211         // Remove the prototype from the map of detached wrapped
01212         // native prototypes now that the prototype is part of a scope
01213         // again.
01214         detachedMap->Remove(proto);
01215     }
01216 
01217     // The global in this scope didn't change, but a prototype did
01218     // (most likely the global object's prototype), which means the
01219     // scope needs to get a chance to update its cached
01220     // Object.prototype pointers etc.
01221     scope->SetGlobal(ccx, aScope);
01222 
01223     return NS_OK;
01224 }
01225 
01226 NS_IMETHODIMP
01227 nsXPConnect::CreateSandbox(JSContext *cx, nsIPrincipal *principal,
01228                            nsIXPConnectJSObjectHolder **_retval)
01229 {
01230 #ifdef XPCONNECT_STANDALONE
01231     return NS_ERROR_NOT_AVAILABLE;
01232 #else /* XPCONNECT_STANDALONE */
01233     XPCCallContext ccx(NATIVE_CALLER, cx);
01234     if(!ccx.IsValid())
01235         return UnexpectedFailure(NS_ERROR_FAILURE);
01236 
01237     *_retval = nsnull;
01238 
01239     jsval rval = JSVAL_VOID;
01240     AUTO_MARK_JSVAL(ccx, &rval);
01241 
01242     nsresult rv = xpc_CreateSandboxObject(cx, &rval, principal);
01243     NS_ASSERTION(NS_FAILED(rv) || !JSVAL_IS_PRIMITIVE(rval),
01244                  "Bad return value from xpc_CreateSandboxObject()!");
01245 
01246     if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(rval)) {
01247         *_retval = XPCJSObjectHolder::newHolder(cx, JSVAL_TO_OBJECT(rval));
01248         NS_ENSURE_TRUE(*_retval, NS_ERROR_OUT_OF_MEMORY);
01249 
01250         NS_ADDREF(*_retval);
01251     }
01252 
01253     return rv;
01254 #endif /* XPCONNECT_STANDALONE */
01255 }
01256 
01257 // nsIXPConnect_MOZILLA_1_8_BRANCH version.
01258 NS_IMETHODIMP
01259 nsXPConnect::EvalInSandboxObject(const nsAString& source, JSContext *cx,
01260                                  nsIXPConnectJSObjectHolder *sandbox,
01261                                  jsval *rval)
01262 {
01263     return EvalInSandboxObject2(source, cx, sandbox, PR_FALSE, rval);
01264 }
01265 
01266 // nsIXPConnect_MOZILLA_1_8_BRANCH2 version.
01267 NS_IMETHODIMP
01268 nsXPConnect::EvalInSandboxObject2(const nsAString& source, JSContext *cx,
01269                                   nsIXPConnectJSObjectHolder *sandbox,
01270                                   PRBool returnStringOnly, jsval *rval)
01271 {
01272 #ifdef XPCONNECT_STANDALONE
01273     return NS_ERROR_NOT_AVAILABLE;
01274 #else /* XPCONNECT_STANDALONE */
01275     if (!sandbox)
01276         return NS_ERROR_INVALID_ARG;
01277 
01278     JSObject *obj;
01279     nsresult rv = sandbox->GetJSObject(&obj);
01280     NS_ENSURE_SUCCESS(rv, rv);
01281 
01282     return xpc_EvalInSandbox(cx, obj, source,
01283                              NS_ConvertUTF16toUTF8(source).get(), 1,
01284                              returnStringOnly, rval);
01285 #endif /* XPCONNECT_STANDALONE */
01286 }
01287 
01288 /* nsIXPConnectJSObjectHolder getWrappedNativePrototype (in JSContextPtr aJSContext, in JSObjectPtr aScope, in nsIClassInfo aClassInfo); */
01289 NS_IMETHODIMP 
01290 nsXPConnect::GetWrappedNativePrototype(JSContext * aJSContext, 
01291                                        JSObject * aScope, 
01292                                        nsIClassInfo *aClassInfo, 
01293                                        nsIXPConnectJSObjectHolder **_retval)
01294 {
01295     XPCCallContext ccx(NATIVE_CALLER, aJSContext);
01296     if(!ccx.IsValid())
01297         return UnexpectedFailure(NS_ERROR_FAILURE);
01298 
01299     XPCWrappedNativeScope* scope =
01300         XPCWrappedNativeScope::FindInJSObjectScope(ccx, aScope);
01301     if(!scope)
01302         return UnexpectedFailure(NS_ERROR_FAILURE);
01303 
01304     XPCNativeScriptableCreateInfo sciProto;
01305     XPCWrappedNative::GatherProtoScriptableCreateInfo(aClassInfo, &sciProto);
01306 
01307     AutoMarkingWrappedNativeProtoPtr proto(ccx);
01308     proto = XPCWrappedNativeProto::GetNewOrUsed(ccx, scope, aClassInfo, 
01309                                                 &sciProto, JS_FALSE,
01310                                                 OBJ_IS_NOT_GLOBAL);
01311     if(!proto)
01312         return UnexpectedFailure(NS_ERROR_FAILURE);
01313 
01314     nsIXPConnectJSObjectHolder* holder;
01315     *_retval = holder = XPCJSObjectHolder::newHolder(ccx, 
01316                                                      proto->GetJSProtoObject());
01317     if(!holder)
01318         return UnexpectedFailure(NS_ERROR_FAILURE);
01319 
01320     NS_ADDREF(holder);
01321     return NS_OK;
01322 }
01323 
01324 /* attribute PRBool collectGarbageOnMainThreadOnly; */
01325 NS_IMETHODIMP 
01326 nsXPConnect::GetCollectGarbageOnMainThreadOnly(PRBool *aCollectGarbageOnMainThreadOnly)
01327 {
01328     XPCJSRuntime* rt = GetRuntime();
01329     if(!rt)
01330         return UnexpectedFailure(NS_ERROR_FAILURE);
01331 
01332     *aCollectGarbageOnMainThreadOnly = rt->GetMainThreadOnlyGC();
01333     return NS_OK;
01334 }
01335 
01336 NS_IMETHODIMP 
01337 nsXPConnect::SetCollectGarbageOnMainThreadOnly(PRBool aCollectGarbageOnMainThreadOnly)
01338 {
01339     XPCJSRuntime* rt = GetRuntime();
01340     if(!rt)
01341         return UnexpectedFailure(NS_ERROR_FAILURE);
01342 
01343     rt->SetMainThreadOnlyGC(aCollectGarbageOnMainThreadOnly);
01344     return NS_OK;
01345 }
01346 
01347 /* attribute PRBool deferReleasesUntilAfterGarbageCollection; */
01348 NS_IMETHODIMP 
01349 nsXPConnect::GetDeferReleasesUntilAfterGarbageCollection(PRBool *aDeferReleasesUntilAfterGarbageCollection)
01350 {
01351     XPCJSRuntime* rt = GetRuntime();
01352     if(!rt)
01353         return UnexpectedFailure(NS_ERROR_FAILURE);
01354 
01355     *aDeferReleasesUntilAfterGarbageCollection = rt->GetDeferReleases();
01356     return NS_OK;
01357 }
01358 
01359 NS_IMETHODIMP 
01360 nsXPConnect::SetDeferReleasesUntilAfterGarbageCollection(PRBool aDeferReleasesUntilAfterGarbageCollection)
01361 {
01362     XPCJSRuntime* rt = GetRuntime();
01363     if(!rt)
01364         return UnexpectedFailure(NS_ERROR_FAILURE);
01365 
01366     rt->SetDeferReleases(aDeferReleasesUntilAfterGarbageCollection);
01367     return NS_OK;
01368 }
01369 
01370 /* void releaseJSContext (in JSContextPtr aJSContext, in PRBool noGC); */
01371 NS_IMETHODIMP 
01372 nsXPConnect::ReleaseJSContext(JSContext * aJSContext, PRBool noGC)
01373 {
01374     NS_ASSERTION(aJSContext, "bad param");
01375     XPCPerThreadData* tls = XPCPerThreadData::GetData();
01376     if(tls)
01377     {
01378         XPCCallContext* ccx = nsnull;
01379         for(XPCCallContext* cur = tls->GetCallContext(); 
01380             cur; 
01381             cur = cur->GetPrevCallContext())
01382         {
01383             if(cur->GetJSContext() == aJSContext)
01384             {
01385                 ccx = cur;
01386                 // Keep looping to find the deepest matching call context.
01387             }
01388         }
01389     
01390         if(ccx)
01391         {
01392 #ifdef DEBUG_xpc_hacker
01393             printf("!xpc - deferring destruction of JSContext @ %0x\n", 
01394                    aJSContext);
01395 #endif
01396             ccx->SetDestroyJSContextInDestructor(JS_TRUE);
01397             JS_ClearNewbornRoots(aJSContext);
01398             return NS_OK;
01399         }
01400         // else continue on and synchronously destroy the JSContext ...
01401 
01402         NS_ASSERTION(!tls->GetJSContextStack() || 
01403                      !tls->GetJSContextStack()->
01404                         DEBUG_StackHasJSContext(aJSContext),
01405                      "JSContext still in threadjscontextstack!");
01406     }
01407     
01408     if(noGC)
01409         JS_DestroyContextNoGC(aJSContext);
01410     else
01411         JS_DestroyContext(aJSContext);
01412     SyncJSContexts();
01413     return NS_OK;
01414 }
01415 
01416 /* void debugDump (in short depth); */
01417 NS_IMETHODIMP
01418 nsXPConnect::DebugDump(PRInt16 depth)
01419 {
01420 #ifdef DEBUG
01421     depth-- ;
01422     XPC_LOG_ALWAYS(("nsXPConnect @ %x with mRefCnt = %d", this, mRefCnt.get()));
01423     XPC_LOG_INDENT();
01424         XPC_LOG_ALWAYS(("gSelf @ %x", gSelf));
01425         XPC_LOG_ALWAYS(("gOnceAliveNowDead is %d", (int)gOnceAliveNowDead));
01426         XPC_LOG_ALWAYS(("mDefaultSecurityManager @ %x", mDefaultSecurityManager));
01427         XPC_LOG_ALWAYS(("mDefaultSecurityManagerFlags of %x", mDefaultSecurityManagerFlags));
01428         XPC_LOG_ALWAYS(("mInterfaceInfoManager @ %x", mInterfaceInfoManager));
01429         XPC_LOG_ALWAYS(("mContextStack @ %x", mContextStack));
01430         if(mRuntime)
01431         {
01432             if(depth)
01433                 mRuntime->DebugDump(depth);
01434             else
01435                 XPC_LOG_ALWAYS(("XPCJSRuntime @ %x", mRuntime));
01436         }
01437         else
01438             XPC_LOG_ALWAYS(("mRuntime is null"));
01439         XPCWrappedNativeScope::DebugDumpAllScopes(depth);
01440     XPC_LOG_OUTDENT();
01441 #endif
01442     return NS_OK;
01443 }
01444 
01445 /* void debugDumpObject (in nsISupports aCOMObj, in short depth); */
01446 NS_IMETHODIMP
01447 nsXPConnect::DebugDumpObject(nsISupports *p, PRInt16 depth)
01448 {
01449 #ifdef DEBUG
01450     if(!depth)
01451         return NS_OK;
01452     if(!p)
01453     {
01454         XPC_LOG_ALWAYS(("*** Cound not dump object with NULL address"));
01455         return NS_OK;
01456     }
01457 
01458     nsIXPConnect* xpc;
01459     nsIXPCWrappedJSClass* wjsc;
01460     nsIXPConnectWrappedNative* wn;
01461     nsIXPConnectWrappedJS* wjs;
01462 
01463     if(NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPConnect),
01464                         (void**)&xpc)))
01465     {
01466         XPC_LOG_ALWAYS(("Dumping a nsIXPConnect..."));
01467         xpc->DebugDump(depth);
01468         NS_RELEASE(xpc);
01469     }
01470     else if(NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPCWrappedJSClass),
01471                         (void**)&wjsc)))
01472     {
01473         XPC_LOG_ALWAYS(("Dumping a nsIXPCWrappedJSClass..."));
01474         wjsc->DebugDump(depth);
01475         NS_RELEASE(wjsc);
01476     }
01477     else if(NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPConnectWrappedNative),
01478                         (void**)&wn)))
01479     {
01480         XPC_LOG_ALWAYS(("Dumping a nsIXPConnectWrappedNative..."));
01481         wn->DebugDump(depth);
01482         NS_RELEASE(wn);
01483     }
01484     else if(NS_SUCCEEDED(p->QueryInterface(NS_GET_IID(nsIXPConnectWrappedJS),
01485                         (void**)&wjs)))
01486     {
01487         XPC_LOG_ALWAYS(("Dumping a nsIXPConnectWrappedJS..."));
01488         wjs->DebugDump(depth);
01489         NS_RELEASE(wjs);
01490     }
01491     else
01492         XPC_LOG_ALWAYS(("*** Could not dump the nsISupports @ %x", p));
01493 #endif
01494     return NS_OK;
01495 }
01496 
01497 /* void debugDumpJSStack (in PRBool showArgs, in PRBool showLocals, in PRBool showThisProps); */
01498 NS_IMETHODIMP
01499 nsXPConnect::DebugDumpJSStack(PRBool showArgs,
01500                               PRBool showLocals,
01501                               PRBool showThisProps)
01502 {
01503 #ifdef DEBUG
01504     JSContext* cx;
01505     nsresult rv;
01506     nsCOMPtr<nsIThreadJSContextStack> stack = 
01507              do_GetService(XPC_CONTEXT_STACK_CONTRACTID, &rv);
01508     if(NS_FAILED(rv) || !stack)
01509         printf("failed to get nsIThreadJSContextStack service!\n");
01510     else if(NS_FAILED(stack->Peek(&cx)))
01511         printf("failed to peek into nsIThreadJSContextStack service!\n");
01512     else if(!cx)
01513         printf("there is no JSContext on the nsIThreadJSContextStack!\n");
01514     else
01515         xpc_DumpJSStack(cx, showArgs, showLocals, showThisProps);
01516 #endif
01517     return NS_OK;
01518 }
01519 
01520 /* void debugDumpEvalInJSStackFrame (in PRUint32 aFrameNumber, in string aSourceText); */
01521 NS_IMETHODIMP
01522 nsXPConnect::DebugDumpEvalInJSStackFrame(PRUint32 aFrameNumber, const char *aSourceText)
01523 {
01524 #ifdef DEBUG
01525     JSContext* cx;
01526     nsresult rv;
01527     nsCOMPtr<nsIThreadJSContextStack> stack = 
01528              do_GetService(XPC_CONTEXT_STACK_CONTRACTID, &rv);
01529     if(NS_FAILED(rv) || !stack)
01530         printf("failed to get nsIThreadJSContextStack service!\n");
01531     else if(NS_FAILED(stack->Peek(&cx)))
01532         printf("failed to peek into nsIThreadJSContextStack service!\n");
01533     else if(!cx)
01534         printf("there is no JSContext on the nsIThreadJSContextStack!\n");
01535     else
01536         xpc_DumpEvalInJSStackFrame(cx, aFrameNumber, aSourceText);
01537 #endif
01538     return NS_OK;
01539 }
01540 
01541 /* JSVal variantToJS (in JSContextPtr ctx, in JSObjectPtr scope, in nsIVariant value); */
01542 NS_IMETHODIMP 
01543 nsXPConnect::VariantToJS(JSContext* ctx, JSObject* scope, nsIVariant* value, jsval* _retval)
01544 {
01545     NS_PRECONDITION(ctx, "bad param");
01546     NS_PRECONDITION(scope, "bad param");
01547     NS_PRECONDITION(value, "bad param");
01548     NS_PRECONDITION(_retval, "bad param");
01549 
01550     XPCCallContext ccx(NATIVE_CALLER, ctx);
01551     if(!ccx.IsValid())
01552         return NS_ERROR_FAILURE;
01553 
01554     nsresult rv = NS_OK;
01555     if(!XPCVariant::VariantDataToJS(ccx, value, scope, &rv, _retval))
01556     {
01557         if(NS_FAILED(rv)) 
01558             return rv;
01559 
01560         return NS_ERROR_FAILURE;
01561     }
01562 
01563     return NS_OK;
01564 }
01565 
01566 /* nsIVariant JSToVariant (in JSContextPtr ctx, in JSVal value); */
01567 NS_IMETHODIMP 
01568 nsXPConnect::JSToVariant(JSContext* ctx, jsval value, nsIVariant** _retval)
01569 {
01570     NS_PRECONDITION(ctx, "bad param");
01571     NS_PRECONDITION(value, "bad param");
01572     NS_PRECONDITION(_retval, "bad param");
01573 
01574     XPCCallContext ccx(NATIVE_CALLER, ctx);
01575     if(!ccx.IsValid())
01576         return NS_ERROR_FAILURE;
01577 
01578     *_retval = XPCVariant::newVariant(ccx, value);
01579     if(!(*_retval)) 
01580         return NS_ERROR_FAILURE;
01581 
01582     return NS_OK;
01583 }
01584 
01585 /* void flagSystemFilenamePrefix (in string filenamePrefix); */
01586 NS_IMETHODIMP 
01587 nsXPConnect::FlagSystemFilenamePrefix(const char *aFilenamePrefix)
01588 {
01589     NS_PRECONDITION(aFilenamePrefix, "bad param");
01590 
01591     nsIJSRuntimeService* rtsvc = nsXPConnect::GetJSRuntimeService();
01592     if(!rtsvc)
01593         return NS_ERROR_NOT_INITIALIZED;
01594 
01595     JSRuntime* rt;
01596     nsresult rv = rtsvc->GetRuntime(&rt);
01597     if(NS_FAILED(rv))
01598         return rv;
01599 
01600     if(!JS_FlagScriptFilenamePrefix(rt, aFilenamePrefix, JSFILENAME_SYSTEM))
01601         return NS_ERROR_OUT_OF_MEMORY;
01602     return NS_OK;
01603 }
01604 
01605 NS_IMETHODIMP
01606 nsXPConnect::WillProcessEvents(nsIEventQueue *aQueue)
01607 {
01608     // Push a null JSContext so that we don't see any script during
01609     // event processing.
01610     NS_ENSURE_STATE(mContextStack);
01611     return mContextStack->Push(nsnull);
01612 }
01613 
01614 NS_IMETHODIMP
01615 nsXPConnect::DidProcessEvents(nsIEventQueue *aQueue)
01616 {
01617     NS_ENSURE_STATE(mContextStack);
01618     return mContextStack->Pop(nsnull);
01619 }
01620 
01621 #ifdef DEBUG
01622 /* These are here to be callable from a debugger */
01623 JS_BEGIN_EXTERN_C
01624 void DumpJSStack()
01625 {
01626     nsresult rv;
01627     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
01628     if(NS_SUCCEEDED(rv) && xpc)
01629         xpc->DebugDumpJSStack(PR_TRUE, PR_TRUE, PR_FALSE);
01630     else
01631         printf("failed to get XPConnect service!\n");
01632 }
01633 
01634 void DumpJSEval(PRUint32 frameno, const char* text)
01635 {
01636     nsresult rv;
01637     nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
01638     if(NS_SUCCEEDED(rv) && xpc)
01639         xpc->DebugDumpEvalInJSStackFrame(frameno, text);
01640     else
01641         printf("failed to get XPConnect service!\n");
01642 }
01643 
01644 void DumpJSObject(JSObject* obj)
01645 {
01646     xpc_DumpJSObject(obj);
01647 }
01648 
01649 void DumpJSValue(jsval val)
01650 {
01651     printf("Dumping 0x%lx. Value tag is %lu.\n", val, JSVAL_TAG(val));
01652     if(JSVAL_IS_NULL(val)) {
01653         printf("Value is null\n");
01654     }
01655     else if(JSVAL_IS_OBJECT(val)) {
01656         printf("Value is an object\n");
01657         JSObject* obj = JSVAL_TO_OBJECT(val);
01658         DumpJSObject(obj);
01659     }
01660     else if(JSVAL_IS_NUMBER(val)) {
01661         printf("Value is a number: ");
01662         if(JSVAL_IS_INT(val))
01663           printf("Integer %i\n", JSVAL_TO_INT(val));
01664         else if(JSVAL_IS_DOUBLE(val))
01665           printf("Floating-point value %f\n", *JSVAL_TO_DOUBLE(val));
01666     }
01667     else if(JSVAL_IS_STRING(val)) {
01668         printf("Value is a string: ");
01669         JSString* string = JSVAL_TO_STRING(val);
01670         char* bytes = JS_GetStringBytes(string);
01671         printf("<%s>\n", bytes);
01672     }
01673     else if(JSVAL_IS_BOOLEAN(val)) {
01674         printf("Value is boolean: ");
01675         printf(JSVAL_TO_BOOLEAN(val) ? "true" : "false");
01676     }
01677     else if(JSVAL_IS_VOID(val)) {
01678         printf("Value is undefined\n");
01679     }
01680     else {
01681         printf("No idea what this value is.\n");
01682     }
01683 }
01684 JS_END_EXTERN_C
01685 #endif