/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is mozilla.org. * Portions created by the Initial Developer are Copyright (C) 2005 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Mark Hammond (original author) * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsIScriptContext.h" #include "nsIScriptGlobalObject.h" #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" #include "nsITimelineService.h" #include "nsITimer.h" #include "nsIArray.h" #include "nsIAtom.h" #include "prtime.h" #include "nsStringAPI.h" #include "nsIWeakReference.h" // needed by nsGUIEvent.h #include "nsIWeakReferenceUtils.h" // needed by nsGUIEvent.h #include "nsGUIEvent.h" #include "nsServiceManagerUtils.h" #include "nsDOMScriptObjectHolder.h" #include "nsIDOMDocument.h" #include "nsPyDOM.h" #include "nsPyContext.h" #include "compile.h" #include "eval.h" #include "marshal.h" #ifdef NS_DEBUG nsPyDOMObjectLeakStats gLeakStats; #endif // Straight from nsJSEnvironment. static inline const char * AtomToEventHandlerName(nsIAtom *aName) { const char *name; aName->GetUTF8String(&name); #ifdef DEBUG const char *cp; char c; for (cp = name; *cp != '\0'; ++cp) { c = *cp; NS_ASSERTION (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'), "non-ASCII non-alphabetic event handler name"); } #endif return name; } // A simple "object holder" - an XPCOM object that keeps a reference to // a Python object. When the XPCOM object dies, the Python reference is // dropped. class nsPyObjectHolder : public nsISupports { public: NS_DECL_ISUPPORTS nsPyObjectHolder(PyObject *ob) : m_ob(ob) {Py_XINCREF(m_ob);} ~nsPyObjectHolder() { CEnterLeavePython _celp; Py_XDECREF(m_ob); } private: PyObject *m_ob; }; // QueryInterface implementation for nsPyObjectHolder NS_INTERFACE_MAP_BEGIN(nsPyObjectHolder) NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END NS_IMPL_ADDREF(nsPyObjectHolder) NS_IMPL_RELEASE(nsPyObjectHolder) nsPythonContext::nsPythonContext() : mIsInitialized(PR_FALSE), mScriptGlobal(nsnull), mScriptsEnabled(PR_TRUE), mProcessingScriptTag(PR_FALSE), mDelegate(NULL) { PYLEAK_STAT_INCREMENT(ScriptContext); } nsPythonContext::~nsPythonContext() { PYLEAK_STAT_DECREMENT(ScriptContext); } // QueryInterface implementation for nsPythonContext NS_INTERFACE_MAP_BEGIN(nsPythonContext) NS_INTERFACE_MAP_ENTRY(nsIScriptContext) NS_INTERFACE_MAP_ENTRY(nsITimerCallback) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptContext) NS_INTERFACE_MAP_END NS_IMPL_ADDREF(nsPythonContext) NS_IMPL_RELEASE(nsPythonContext) nsresult nsPythonContext::HandlePythonError() { // It looks like we first need to call the DOM. Depending on the result // of the DOM error handler, we may then just treat it as unhandled. if (!PyErr_Occurred()) return NS_OK; nsScriptErrorEvent errorevent(PR_TRUE, NS_LOAD_ERROR); nsString strFilename; PyObject *exc, *typ, *tb; PyErr_Fetch(&exc, &typ, &tb); PyErr_NormalizeException( &exc, &typ, &tb); // We must have a traceback object to report the filename/lineno. // *sob* - PyTracebackObject not in a header file in 2.3. Use getattr etc if (tb) { PyObject *frame = PyObject_GetAttrString(tb, "tb_frame"); if (frame) { PyObject *obLineNo = PyObject_GetAttrString(frame, "f_lineno"); if (obLineNo) { errorevent.lineNr = PyInt_AsLong(obLineNo); Py_DECREF(obLineNo); } else { NS_ERROR("Traceback had no lineNo attribute?"); PyErr_Clear(); } PyObject *code = PyObject_GetAttrString(frame, "f_code"); if (code) { PyObject *filename = PyObject_GetAttrString(code, "co_filename"); if (filename && PyString_Check(filename)) { CopyUTF8toUTF16(nsCString(PyString_AsString(filename)), strFilename); errorevent.fileName = strFilename.get(); } Py_XDECREF(filename); Py_DECREF(code); } Py_DECREF(frame); } } PRBool outOfMem = PyErr_GivenExceptionMatches(exc, PyExc_MemoryError); nsCAutoString cerrMsg; PyXPCOM_FormatGivenException(cerrMsg, exc, typ, tb); nsAutoString errMsg; CopyUTF8toUTF16(cerrMsg, errMsg); NS_ASSERTION(!errMsg.IsEmpty(), "Failed to extract a Python error message"); errorevent.errorMsg = errMsg.get(); nsEventStatus status = nsEventStatus_eIgnore; // Handle the script error before we restore the exception. if (mScriptGlobal != nsnull && !outOfMem) { mScriptGlobal->HandleScriptError(&errorevent, &status); } PyErr_Restore(exc, typ, tb); if (status != nsEventStatus_eConsumeNoDefault) { // report it 'normally'. We probably should use nsIScriptError // (OTOH, pyxpcom itself is probably what should) nsCAutoString streamout("Python DOM script error"); nsCAutoString level; if (status != nsEventStatus_eIgnore) { streamout += NS_LITERAL_CSTRING(" (suppressed by event handler)"); level = NS_LITERAL_CSTRING("info"); } else { level = NS_LITERAL_CSTRING("warning"); } PyXPCOM_FormatCurrentException(streamout); PyXPCOM_Log(level.get(), streamout); } // We always want the hresult and exception state cleared. nsresult ret = PyXPCOM_SetCOMErrorFromPyException(); PyErr_Clear(); return ret; } // WillInitializeContext() is called before InitContext(). Both // may be called multiple times as a context is re-initialized for a new // document. void nsPythonContext::WillInitializeContext() { mIsInitialized = PR_FALSE; // Don't create a new delegate if we are being re-initialized - it // may have useful state (eg, the previous script global) CEnterLeavePython _celp; if (!mDelegate) { // Load our delegate. PyObject *mod = PyImport_ImportModule("nsdom.context"); if (mod==NULL) { HandlePythonError(); return; } PyObject *klass = PyObject_GetAttrString(mod, "ScriptContext"); Py_DECREF(mod); if (klass == NULL) { HandlePythonError(); return; } mDelegate = PyObject_Call(klass, NULL, NULL); Py_DECREF(klass); } PyObject *ret = PyObject_CallMethod(mDelegate, "WillInitializeContext", NULL); if (ret == NULL) HandlePythonError(); } void nsPythonContext::DidInitializeContext() { NS_ASSERTION(mDelegate, "No delegate!"); if (mDelegate) { CEnterLeavePython _celp; PyObject *ret = PyObject_CallMethod(mDelegate, "DidInitializeContext", NULL); Py_XDECREF(ret); HandlePythonError(); } mIsInitialized = PR_TRUE; } PRBool nsPythonContext::IsContextInitialized() { return mIsInitialized; } nsresult nsPythonContext::InitContext(nsIScriptGlobalObject *aGlobalObject) { NS_TIMELINE_MARK_FUNCTION("nsPythonContext::InitContext"); NS_ENSURE_TRUE(!mIsInitialized, NS_ERROR_ALREADY_INITIALIZED); NS_ASSERTION(mDelegate != NULL, "WillInitContext didn't create delegate"); if (mDelegate == NULL) return NS_ERROR_UNEXPECTED; CEnterLeavePython _celp; PyObject *obGlobal; if (aGlobalObject) { obGlobal = PyObject_FromNSDOMInterface(mDelegate, aGlobalObject, NS_GET_IID(nsIScriptGlobalObject)); if (!obGlobal) return HandlePythonError(); } else { obGlobal = Py_None; Py_INCREF(Py_None); } PyObject *ret = PyObject_CallMethod(mDelegate, "InitContext", "N", obGlobal); if (ret == NULL) return HandlePythonError(); // stash the global away so we can fetch it locally. mScriptGlobal = aGlobalObject; return NS_OK; } void nsPythonContext::DidSetDocument(nsISupports *aSupDoc, void *aGlobal) { NS_TIMELINE_MARK_FUNCTION("nsPythonContext::DidSetDocument"); NS_ASSERTION(mDelegate != NULL, "No delegate"); if (mDelegate == NULL) return; CEnterLeavePython _celp; PyObject *obDoc; if (aSupDoc) { nsCOMPtr doc(do_QueryInterface(aSupDoc)); NS_ASSERTION(nsnull != doc, "not an nsIDOMDocument!?"); if (nsnull != doc) obDoc = PyObject_FromNSDOMInterface(mDelegate, aSupDoc, NS_GET_IID(nsIDOMDocument)); if (!obDoc) { HandlePythonError(); return; } } else { obDoc = Py_None; Py_INCREF(Py_None); } PyObject *ret = PyObject_CallMethod(mDelegate, "DidSetDocument", "NO", obDoc, aGlobal); Py_XDECREF(ret); HandlePythonError(); } nsresult nsPythonContext::EvaluateStringWithValue(const nsAString& aScript, void *aScopeObject, nsIPrincipal *aPrincipal, const char *aURL, PRUint32 aLineNo, PRUint32 aVersion, void* aRetValue, PRBool* aIsUndefined) { NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); if (!mScriptsEnabled) { if (aIsUndefined) { *aIsUndefined = PR_TRUE; } return NS_OK; } NS_ERROR("Not implemented"); return NS_ERROR_NOT_IMPLEMENTED; } nsresult nsPythonContext::EvaluateString(const nsAString& aScript, void *aScopeObject, nsIPrincipal *aPrincipal, const char *aURL, PRUint32 aLineNo, PRUint32 aVersion, nsAString *aRetValue, PRBool* aIsUndefined) { NS_TIMELINE_MARK_FUNCTION("nsPythonContext::EvaluateString"); NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); *aIsUndefined = PR_TRUE; if (!mScriptsEnabled) { *aIsUndefined = PR_TRUE; if (aRetValue) { aRetValue->Truncate(); } return NS_OK; } CEnterLeavePython _celp; // ignore principal param - no one uses it yet. PyObject *obScript = PyObject_FromNSString(aScript); PyObject *ret = PyObject_CallMethod(mDelegate, "EvaluateString", "NOOsii", obScript, (PyObject *)aScopeObject, Py_None, // principal place holder aURL, aLineNo, aVersion); // We happen to know that no impls use the return value. Py_XDECREF(ret); return HandlePythonError(); } nsresult nsPythonContext::ExecuteScript(void* aScriptObject, void *aScopeObject, nsAString* aRetValue, PRBool* aIsUndefined) { NS_TIMELINE_MARK_FUNCTION("nsPythonContext::ExecuteScript"); NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); if (aIsUndefined) { *aIsUndefined = PR_TRUE; } if (!mScriptsEnabled) { if (aRetValue) { aRetValue->Truncate(); } return NS_OK; } NS_ENSURE_TRUE(aScriptObject, NS_ERROR_NULL_POINTER); NS_ASSERTION(mDelegate, "Script context has no delegate"); NS_ENSURE_TRUE(mDelegate, NS_ERROR_UNEXPECTED); CEnterLeavePython _celp; PyObject *ret = PyObject_CallMethod(mDelegate, "ExecuteScript", "OO", aScriptObject, aScopeObject); // We always want to return OK here - any errors are "just" script errors. if (!ret) { HandlePythonError(); if (aRetValue) aRetValue->Truncate(); } else if (ret == Py_None) { if (aRetValue) aRetValue->Truncate(); } else { if (aRetValue) { PyObject_AsNSString(ret, *aRetValue); } if (aIsUndefined) { *aIsUndefined = PR_FALSE; } } Py_XDECREF(ret); return NS_OK; } nsresult nsPythonContext::CompileScript(const PRUnichar* aText, PRInt32 aTextLength, void *aScopeObject, nsIPrincipal *aPrincipal, const char *aURL, PRUint32 aLineNo, PRUint32 aVersion, nsScriptObjectHolder &aScriptObject) { NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); NS_TIMELINE_MARK_FUNCTION("nsPythonContext::CompileScript"); NS_ASSERTION(mDelegate, "Script context has no delegate"); NS_ENSURE_TRUE(mDelegate, NS_ERROR_UNEXPECTED); CEnterLeavePython _celp; PyObject *obCode = PyObject_FromNSString(aText, aTextLength); if (!obCode) return HandlePythonError(); PyObject *obPrincipal = Py_None; // fix this when we can use it! PyObject *ret = PyObject_CallMethod(mDelegate, "CompileScript", "NOOsii", obCode, aScopeObject ? aScopeObject : Py_None, obPrincipal, aURL, aLineNo, aVersion); if (!ret) { return HandlePythonError(); } NS_ASSERTION(aScriptObject.getScriptTypeID()==nsIProgrammingLanguage::PYTHON, "Expecting Python script object holder"); aScriptObject.set(ret); Py_DECREF(ret); return NS_OK; } nsresult nsPythonContext::CompileEventHandler(nsIAtom *aName, PRUint32 aArgCount, const char** aArgNames, const nsAString& aBody, const char *aURL, PRUint32 aLineNo, PRUint32 aVersion, nsScriptObjectHolder &aHandler) { NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); NS_TIMELINE_MARK_FUNCTION("nsPythonContext::CompileEventHandler"); NS_ASSERTION(mDelegate, "Script context has no delegate"); NS_ENSURE_TRUE(mDelegate, NS_ERROR_UNEXPECTED); CEnterLeavePython _celp; aHandler.drop(); PyObject *argNames = PyList_New(aArgCount); if (!argNames) return HandlePythonError(); for (PRUint32 i=0;i pyargv(do_QueryInterface(aargv)); if (pyargv) { obArgv = pyargv->GetArgs(); Py_XINCREF(obArgv); // match the non-py case } if (!obArgv) { obArgv = PyObject_FromNSDOMInterface(mDelegate, aargv); if (!obArgv) { Py_DECREF(obTarget); return HandlePythonError(); } } PyObject *ret = PyObject_CallMethod(mDelegate, "CallEventHandler", "NOON", obTarget, aScope, aHandler, obArgv); if (ret) { PyObject_AsVariant(ret, arv); Py_DECREF(ret); } return HandlePythonError(); } nsresult nsPythonContext::GetBoundEventHandler(nsISupports* aTarget, void *aScope, nsIAtom* aName, nsScriptObjectHolder &aHandler) { NS_TIMELINE_MARK_FUNCTION("nsPythonContext::GetBoundEventHandler"); NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); NS_ASSERTION(mDelegate, "Script context has no delegate"); NS_ENSURE_TRUE(mDelegate, NS_ERROR_UNEXPECTED); CEnterLeavePython _celp; aHandler.drop(); PyObject *obTarget; obTarget = PyObject_FromNSDOMInterface(mDelegate, aTarget); if (!obTarget) return HandlePythonError(); PyObject *ret = PyObject_CallMethod(mDelegate, "GetBoundEventHandler", "NOs", obTarget, aScope, AtomToEventHandlerName(aName)); if (!ret) return HandlePythonError(); if (ret == Py_None) return NS_OK; NS_ASSERTION(aHandler.getScriptTypeID()==nsIProgrammingLanguage::PYTHON, "Expecting Python script object holder"); aHandler.set(ret); Py_DECREF(ret); return NS_OK; } nsresult nsPythonContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aVal) { NS_TIMELINE_MARK_FUNCTION("nsPythonContext::SetProperty"); NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); NS_ASSERTION(mDelegate, "Script context has no delegate"); NS_ENSURE_TRUE(mDelegate, NS_ERROR_UNEXPECTED); CEnterLeavePython _celp; PyObject *obVal; obVal = PyObject_FromNSDOMInterface(mDelegate, aVal); if (!obVal) return HandlePythonError(); PyObject *ret = PyObject_CallMethod(mDelegate, "SetProperty", "OsN", aTarget, aPropName, obVal); Py_XDECREF(ret); return HandlePythonError(); } nsresult nsPythonContext::InitClasses(void *aGlobalObj) { return NS_OK; } nsresult nsPythonContext::Serialize(nsIObjectOutputStream* aStream, void *aScriptObject) { NS_TIMELINE_MARK_FUNCTION("nsPythonContext::Serialize"); CEnterLeavePython _celp; nsresult rv; PyObject *pyScriptObject = (PyObject *)aScriptObject; if (!PyCode_Check(pyScriptObject) && !PyFunction_Check(pyScriptObject)) { NS_ERROR("aScriptObject is not a code or function object"); return NS_ERROR_UNEXPECTED; } rv = aStream->Write32(PyImport_GetMagicNumber()); if (NS_FAILED(rv)) return rv; PyObject *obMarshal = #ifdef Py_MARSHAL_VERSION PyMarshal_WriteObjectToString((PyObject *)aScriptObject, Py_MARSHAL_VERSION); #else // 2.3 etc - only takes 1 arg. PyMarshal_WriteObjectToString((PyObject *)aScriptObject); #endif if (!obMarshal) return HandlePythonError(); NS_ASSERTION(PyString_Check(obMarshal), "marshal returned a non string?"); rv |= aStream->Write32(PyString_GET_SIZE(obMarshal)); rv |= aStream->WriteBytes(PyString_AS_STRING(obMarshal), PyString_GET_SIZE(obMarshal)); Py_DECREF(obMarshal); return rv; } nsresult nsPythonContext::Deserialize(nsIObjectInputStream* aStream, nsScriptObjectHolder &aResult) { NS_TIMELINE_MARK_FUNCTION("nsPythonContext::Deserialize"); nsresult rv; PRUint32 magic; aResult.drop(); rv = aStream->Read32(&magic); if (NS_FAILED(rv)) return rv; // Note that if we find a different marshalled version, we should // still read the bytes from the stream, but throw them away and // simply return nsnull in aResult. // Failure to do this throws the stream out for future objects. PRUint32 nBytes; rv = aStream->Read32(&nBytes); if (NS_FAILED(rv)) return rv; char* data = nsnull; rv = aStream->ReadBytes(nBytes, &data); if (NS_FAILED(rv)) return rv; if (magic != (PRUint32)PyImport_GetMagicNumber()) { NS_WARNING("Python has different marshal version"); if (data) nsMemory::Free(data); return NS_OK; } CEnterLeavePython _celp; PyObject *codeObject = PyMarshal_ReadObjectFromString(data, nBytes); if (data) nsMemory::Free(data); if (codeObject == NULL) return HandlePythonError(); NS_ASSERTION(PyCode_Check(codeObject) || PyFunction_Check(codeObject), "unmarshal returned non code/functions"); NS_ASSERTION(aResult.getScriptTypeID()==nsIProgrammingLanguage::PYTHON, "Expecting Python script object holder"); aResult.set(codeObject); Py_DECREF(codeObject); return NS_OK; } void nsPythonContext::SetDefaultLanguageVersion(PRUint32 aVersion) { return; } nsIScriptGlobalObject * nsPythonContext::GetGlobalObject() { return mScriptGlobal; } void * nsPythonContext::GetNativeContext() { return nsnull; } void * nsPythonContext::GetNativeGlobal() { NS_ASSERTION(mDelegate, "Script context has no delegate"); NS_ENSURE_TRUE(mDelegate, nsnull); NS_TIMELINE_MARK_FUNCTION("nsPythonContext::GetNativeGlobal"); CEnterLeavePython _celp; PyObject *ret = PyObject_CallMethod(mDelegate, "GetNativeGlobal", NULL); if (!ret) { HandlePythonError(); return nsnull; } // This is assumed a borrowed reference. NS_ASSERTION(ret->ob_refcnt > 1, "Can't have a new object here!?"); Py_DECREF(ret); return ret; } nsresult nsPythonContext::CreateNativeGlobalForInner( nsIScriptGlobalObject *aGlobal, PRBool aIsChrome, void **aNativeGlobal, nsISupports **aHolder) { NS_TIMELINE_MARK_FUNCTION("nsPythonContext::CreateNativeGlobalForInner"); CEnterLeavePython _celp; PyObject *obGlob = PyObject_FromNSDOMInterface(mDelegate, aGlobal, NS_GET_IID(nsIScriptGlobalObject)); if (!obGlob) return HandlePythonError(); PyObject *ret = PyObject_CallMethod(mDelegate, "CreateNativeGlobalForInner", "Ni", obGlob, aIsChrome); if (!ret) { HandlePythonError(); return nsnull; } // Create a new holder to manage the lifetime of the returned object. nsPyObjectHolder *holder = new nsPyObjectHolder(ret); *aNativeGlobal = ret; Py_DECREF(ret); if (!holder) return NS_ERROR_OUT_OF_MEMORY; return holder->QueryInterface(NS_GET_IID(nsISupports), (void **)aHolder); } nsresult nsPythonContext::ConnectToInner(nsIScriptGlobalObject *aNewInner, void *aOuterGlobal) { NS_ENSURE_ARG(aNewInner); NS_TIMELINE_MARK_FUNCTION("nsPythonContext::ConnectToInner"); CEnterLeavePython _celp; PyObject *obNewInner = PyObject_FromNSDOMInterface(mDelegate, aNewInner, NS_GET_IID(nsIScriptGlobalObject)); if (!obNewInner) return HandlePythonError(); // Python code can't call this method - so we do it here and pass it in. PyObject *obInnerScope = (PyObject *)aNewInner->GetScriptGlobal( nsIProgrammingLanguage::PYTHON); PyObject *ret = PyObject_CallMethod(mDelegate, "ConnectToInner", "NOO", obNewInner, aOuterGlobal, obInnerScope); Py_XDECREF(ret); return HandlePythonError(); } PRBool nsPythonContext::GetProcessingScriptTag() { return mProcessingScriptTag; } void nsPythonContext::SetProcessingScriptTag(PRBool aResult) { mProcessingScriptTag = aResult; } PRBool nsPythonContext::GetScriptsEnabled() { return mScriptsEnabled; } void nsPythonContext::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts) { // eeek - this seems the wrong way around - the global should callback // into the context. mScriptsEnabled = aEnabled; nsIScriptGlobalObject *global = GetGlobalObject(); if (global) { global->SetScriptsEnabled(aEnabled, aFireTimeouts); } } nsresult nsPythonContext::SetTerminationFunction(nsScriptTerminationFunc aFunc, nsISupports* aRef) { NS_ERROR("Term functions need thought"); return NS_ERROR_UNEXPECTED; } void nsPythonContext::ScriptEvaluated(PRBool aTerminated) { ; } void nsPythonContext::FinalizeContext() { NS_ASSERTION(mDelegate, "No delegate?"); NS_ASSERTION(!mScriptGlobal, "ClearScope not called to clean me up?"); if (mDelegate) { CEnterLeavePython _celp; PyObject *ret = PyObject_CallMethod(mDelegate, "FinalizeContext", NULL); HandlePythonError(); Py_XDECREF(ret); Py_DECREF(mDelegate); mDelegate = NULL; } } void nsPythonContext::GC() { // sadly as at python 2.4, PyGC_Collect(); is not correctly exported. } void nsPythonContext::ClearScope(void *aGlobalObj, PRBool aWhatever) { CEnterLeavePython _celp; if (mDelegate) { PyObject *ret = PyObject_CallMethod(mDelegate, "ClearScope", "O", aGlobalObj); Py_XDECREF(ret); } mScriptGlobal = nsnull; HandlePythonError(); } NS_IMETHODIMP nsPythonContext::Notify(nsITimer *timer) { return NS_ERROR_NOT_IMPLEMENTED; } nsresult nsPythonContext::DropScriptObject(void *object) { if (object) { PYLEAK_STAT_DECREMENT(ScriptObject); CEnterLeavePython _celp; Py_DECREF((PyObject *)object); } return NS_OK; } nsresult nsPythonContext::HoldScriptObject(void *object) { if (object) { PYLEAK_STAT_INCREMENT(ScriptObject); CEnterLeavePython _celp; Py_INCREF((PyObject *)object); } return NS_OK; } #ifdef XULRUNNER_1_9_1 void nsPythonContext::ReportPendingException() { // Not sure there's anything to do here } #else void nsPythonContext::EnterModalState() { // Nothing to do (I hope). } void nsPythonContext::LeaveModalState() { // Nothing to do (I hope). } #endif