Back to index

lightning-sunbird  0.9+nobinonly
xpcstack.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) 1999
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   John Bandhauer <jband@netscape.com> (original author)
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 /* Implements nsIStackFrame. */
00042 
00043 #include "xpcprivate.h"
00044 
00045 class XPCJSStackFrame : public nsIStackFrame
00046 {
00047 public:
00048     NS_DECL_ISUPPORTS
00049     NS_DECL_NSISTACKFRAME
00050 
00051     static nsresult CreateStack(JSContext* cx, JSStackFrame* fp,
00052                                 XPCJSStackFrame** stack);
00053 
00054     static nsresult CreateStackFrameLocation(
00055                                         PRUint32 aLanguage,
00056                                         const char* aFilename,
00057                                         const char* aFunctionName,
00058                                         PRInt32 aLineNumber,
00059                                         nsIStackFrame* aCaller,
00060                                         XPCJSStackFrame** stack);
00061 
00062     XPCJSStackFrame();
00063     virtual ~XPCJSStackFrame();
00064 
00065     JSBool IsJSFrame() const
00066         {return mLanguage == nsIProgrammingLanguage::JAVASCRIPT;}
00067 
00068 private:
00069     nsIStackFrame* mCaller;
00070 
00071     char* mFilename;
00072     char* mFunname;
00073     PRInt32 mLineno;
00074     PRUint32 mLanguage;
00075 };
00076 
00077 /**********************************************/
00078 
00079 // static
00080 
00081 nsresult
00082 XPCJSStack::CreateStack(JSContext* cx, nsIStackFrame** stack)
00083 {
00084     if(!cx || !cx->fp)
00085         return NS_ERROR_FAILURE;
00086 
00087     return XPCJSStackFrame::CreateStack(cx, cx->fp, (XPCJSStackFrame**) stack);
00088 }
00089 
00090 // static
00091 nsresult
00092 XPCJSStack::CreateStackFrameLocation(PRUint32 aLanguage,
00093                                      const char* aFilename,
00094                                      const char* aFunctionName,
00095                                      PRInt32 aLineNumber,
00096                                      nsIStackFrame* aCaller,
00097                                      nsIStackFrame** stack)
00098 {
00099     return XPCJSStackFrame::CreateStackFrameLocation(
00100                                         aLanguage,
00101                                         aFilename,
00102                                         aFunctionName,
00103                                         aLineNumber,
00104                                         aCaller,
00105                                         (XPCJSStackFrame**) stack);
00106 }
00107 
00108 
00109 /**********************************************/
00110 
00111 XPCJSStackFrame::XPCJSStackFrame()
00112     :   mCaller(nsnull),
00113         mFilename(nsnull),
00114         mFunname(nsnull),
00115         mLineno(0),
00116         mLanguage(nsIProgrammingLanguage::UNKNOWN)
00117 {
00118 }
00119 
00120 XPCJSStackFrame::~XPCJSStackFrame()
00121 {
00122     if(mFilename)
00123         nsMemory::Free(mFilename);
00124     if(mFunname)
00125         nsMemory::Free(mFunname);
00126     NS_IF_RELEASE(mCaller);
00127 }
00128 
00129 NS_IMPL_THREADSAFE_ISUPPORTS1(XPCJSStackFrame, nsIStackFrame)
00130 
00131 nsresult
00132 XPCJSStackFrame::CreateStack(JSContext* cx, JSStackFrame* fp,
00133                              XPCJSStackFrame** stack)
00134 {
00135     XPCJSStackFrame* self = new XPCJSStackFrame();
00136     JSBool failed = JS_FALSE;
00137     if(self)
00138     {
00139         NS_ADDREF(self);
00140 
00141         if(fp->down)
00142         {
00143             if(NS_FAILED(CreateStack(cx, fp->down,
00144                          (XPCJSStackFrame**) &self->mCaller)))
00145                 failed = JS_TRUE;
00146         }
00147 
00148         if(!failed)
00149         {
00150             if (JS_IsNativeFrame(cx, fp))
00151                 self->mLanguage = nsIProgrammingLanguage::CPLUSPLUS;
00152             else
00153                 self->mLanguage = nsIProgrammingLanguage::JAVASCRIPT;
00154             if(self->IsJSFrame())
00155             {
00156                 JSScript* script = JS_GetFrameScript(cx, fp);
00157                 jsbytecode* pc = JS_GetFramePC(cx, fp);
00158                 if(script && pc)
00159                 {
00160                     const char* filename = JS_GetScriptFilename(cx, script);
00161                     if(filename)
00162                     {
00163                         self->mFilename = (char*)
00164                                 nsMemory::Clone(filename,
00165                                         sizeof(char)*(strlen(filename)+1));
00166                     }
00167 
00168                     self->mLineno = (PRInt32) JS_PCToLineNumber(cx, script, pc);
00169 
00170 
00171                     JSFunction* fun = JS_GetFrameFunction(cx, fp);
00172                     if(fun)
00173                     {
00174                         const char* funname = JS_GetFunctionName(fun);
00175                         if(funname)
00176                         {
00177                         self->mFunname = (char*)
00178                                 nsMemory::Clone(funname,
00179                                         sizeof(char)*(strlen(funname)+1));
00180                         }
00181                     }
00182                 }
00183                 else
00184                 {
00185                     self->mLanguage = nsIProgrammingLanguage::CPLUSPLUS;
00186                 }
00187             }
00188         }
00189         if(failed)
00190             NS_RELEASE(self);
00191     }
00192 
00193     *stack = self;
00194     return self ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00195 }
00196 
00197 // static
00198 nsresult
00199 XPCJSStackFrame::CreateStackFrameLocation(PRUint32 aLanguage,
00200                                           const char* aFilename,
00201                                           const char* aFunctionName,
00202                                           PRInt32 aLineNumber,
00203                                           nsIStackFrame* aCaller,
00204                                           XPCJSStackFrame** stack)
00205 {
00206     JSBool failed = JS_FALSE;
00207     XPCJSStackFrame* self = new XPCJSStackFrame();
00208     if(self)
00209         NS_ADDREF(self);
00210     else
00211         failed = JS_TRUE;
00212 
00213     if(!failed)
00214     {
00215         self->mLanguage = aLanguage;
00216         self->mLineno = aLineNumber;
00217     }
00218 
00219     if(!failed && aFilename)
00220     {
00221         self->mFilename = (char*)
00222                 nsMemory::Clone(aFilename,
00223                         sizeof(char)*(strlen(aFilename)+1));
00224         if(!self->mFilename)
00225             failed = JS_TRUE;
00226     }
00227 
00228     if(!failed && aFunctionName)
00229     {
00230         self->mFunname = (char*)
00231                 nsMemory::Clone(aFunctionName,
00232                         sizeof(char)*(strlen(aFunctionName)+1));
00233         if(!self->mFunname)
00234             failed = JS_TRUE;
00235     }
00236 
00237     if(!failed && aCaller)
00238     {
00239         NS_ADDREF(aCaller);
00240         self->mCaller = aCaller;
00241     }
00242 
00243     if(failed && self)
00244     {
00245         NS_RELEASE(self);   // sets self to nsnull
00246     }
00247 
00248     *stack = self;
00249     return self ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00250 }
00251 
00252 /* readonly attribute PRUint32 language; */
00253 NS_IMETHODIMP XPCJSStackFrame::GetLanguage(PRUint32 *aLanguage)
00254 {
00255     *aLanguage = mLanguage;
00256     return NS_OK;
00257 }
00258 
00259 /* readonly attribute string languageName; */
00260 NS_IMETHODIMP XPCJSStackFrame::GetLanguageName(char * *aLanguageName)
00261 {
00262     static const char js[] = "JavaScript";
00263     static const char cpp[] = "C++";
00264     char* temp;
00265 
00266     if(IsJSFrame())
00267         *aLanguageName = temp = (char*) nsMemory::Clone(js, sizeof(js));
00268     else
00269         *aLanguageName = temp = (char*) nsMemory::Clone(cpp, sizeof(cpp));
00270 
00271     return temp ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00272 }
00273 
00274 /* readonly attribute string filename; */
00275 NS_IMETHODIMP XPCJSStackFrame::GetFilename(char * *aFilename)
00276 {
00277     XPC_STRING_GETTER_BODY(aFilename, mFilename);
00278 }
00279 
00280 /* readonly attribute string name; */
00281 NS_IMETHODIMP XPCJSStackFrame::GetName(char * *aFunction)
00282 {
00283     XPC_STRING_GETTER_BODY(aFunction, mFunname);
00284 }
00285 
00286 /* readonly attribute PRInt32 lineNumber; */
00287 NS_IMETHODIMP XPCJSStackFrame::GetLineNumber(PRInt32 *aLineNumber)
00288 {
00289     if(!aLineNumber)
00290         return NS_ERROR_NULL_POINTER;
00291 
00292     *aLineNumber = mLineno;
00293     return NS_OK;
00294 }
00295 
00296 /* readonly attribute string sourceLine; */
00297 NS_IMETHODIMP XPCJSStackFrame::GetSourceLine(char * *aSourceLine)
00298 {
00299     if(!aSourceLine)
00300         return NS_ERROR_NULL_POINTER;
00301     *aSourceLine = nsnull;
00302     return NS_OK;
00303 }
00304 
00305 /* readonly attribute nsIStackFrame caller; */
00306 NS_IMETHODIMP XPCJSStackFrame::GetCaller(nsIStackFrame * *aCaller)
00307 {
00308     if(!aCaller)
00309         return NS_ERROR_NULL_POINTER;
00310 
00311     if(mCaller)
00312         NS_ADDREF(mCaller);
00313     *aCaller = mCaller;
00314     return NS_OK;
00315 }
00316 
00317 /* string toString (); */
00318 NS_IMETHODIMP XPCJSStackFrame::ToString(char **_retval)
00319 {
00320     if(!_retval)
00321         return NS_ERROR_NULL_POINTER;
00322 
00323     const char* frametype = IsJSFrame() ? "JS" : "native";
00324     const char* filename = mFilename ? mFilename : "<unknown filename>";
00325     const char* funname = mFunname ? mFunname : "<TOP_LEVEL>";
00326     static const char format[] = "%s frame :: %s :: %s :: line %d";
00327     int len = sizeof(char)*
00328                 (strlen(frametype) + strlen(filename) + strlen(funname)) +
00329               sizeof(format) + 6 /* space for lineno */;
00330 
00331     char* buf = (char*) nsMemory::Alloc(len);
00332     if(!buf)
00333         return NS_ERROR_OUT_OF_MEMORY;
00334 
00335     JS_snprintf(buf, len, format, frametype, filename, funname, mLineno);
00336     *_retval = buf;
00337     return NS_OK;
00338 }
00339