LCOV - code coverage report
Current view: directory - js/jsd - jsd_high.c (source / functions) Found Hit Coverage
Test: app.info Lines: 188 116 61.7 %
Date: 2012-06-02 Functions: 17 11 64.7 %

       1                 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : /*
      39                 :  * JavaScript Debugging support - 'High Level' functions
      40                 :  */
      41                 : 
      42                 : #include "jsd.h"
      43                 : 
      44                 : /***************************************************************************/
      45                 : 
      46                 : /* XXX not 'static' because of old Mac CodeWarrior bug */ 
      47                 : JSCList _jsd_context_list = JS_INIT_STATIC_CLIST(&_jsd_context_list);
      48                 : 
      49                 : /* these are used to connect JSD_SetUserCallbacks() with JSD_DebuggerOn() */
      50                 : static JSD_UserCallbacks _callbacks;
      51                 : static void*             _user = NULL; 
      52                 : static JSRuntime*        _jsrt = NULL;
      53                 : 
      54                 : #ifdef JSD_HAS_DANGEROUS_THREAD
      55                 : static void* _dangerousThread = NULL;
      56                 : #endif
      57                 : 
      58                 : #ifdef JSD_THREADSAFE
      59                 : void* _jsd_global_lock = NULL;
      60                 : #endif
      61                 : 
      62                 : #ifdef DEBUG
      63          439078 : void JSD_ASSERT_VALID_CONTEXT(JSDContext* jsdc)
      64                 : {
      65          439078 :     JS_ASSERT(jsdc->inited);
      66          439078 :     JS_ASSERT(jsdc->jsrt);
      67          439078 :     JS_ASSERT(jsdc->dumbContext);
      68          439078 :     JS_ASSERT(jsdc->glob);
      69          439078 : }
      70                 : #endif
      71                 : 
      72                 : static JSClass global_class = {
      73                 :     "JSDGlobal", JSCLASS_GLOBAL_FLAGS,
      74                 :     JS_PropertyStub,  JS_PropertyStub,  JS_PropertyStub,  JS_StrictPropertyStub,
      75                 :     JS_EnumerateStub, JS_ResolveStub,   JS_ConvertStub,   JS_FinalizeStub,
      76                 :     JSCLASS_NO_OPTIONAL_MEMBERS
      77                 : };
      78                 : 
      79                 : static JSBool
      80             280 : _validateUserCallbacks(JSD_UserCallbacks* callbacks)
      81                 : {
      82             560 :     return !callbacks ||
      83               0 :            (callbacks->size && callbacks->size <= sizeof(JSD_UserCallbacks));
      84                 : }    
      85                 : 
      86                 : static JSDContext*
      87             280 : _newJSDContext(JSRuntime*         jsrt, 
      88                 :                JSD_UserCallbacks* callbacks, 
      89                 :                void*              user,
      90                 :                JSObject*          scopeobj)
      91                 : {
      92             280 :     JSDContext* jsdc = NULL;
      93             280 :     JSCrossCompartmentCall *call = NULL;
      94                 :     JSBool ok;
      95                 : 
      96             280 :     if( ! jsrt )
      97               0 :         return NULL;
      98                 : 
      99             280 :     if( ! _validateUserCallbacks(callbacks) )
     100               0 :         return NULL;
     101                 : 
     102             280 :     jsdc = (JSDContext*) calloc(1, sizeof(JSDContext));
     103             280 :     if( ! jsdc )
     104               0 :         goto label_newJSDContext_failure;
     105                 : 
     106             280 :     if( ! JSD_INIT_LOCKS(jsdc) )
     107                 :         goto label_newJSDContext_failure;
     108                 : 
     109             280 :     JS_INIT_CLIST(&jsdc->links);
     110                 : 
     111             280 :     jsdc->jsrt = jsrt;
     112                 : 
     113             280 :     if( callbacks )
     114               0 :         memcpy(&jsdc->userCallbacks, callbacks, callbacks->size);
     115                 :     
     116             280 :     jsdc->user = user;
     117                 : 
     118                 : #ifdef JSD_HAS_DANGEROUS_THREAD
     119                 :     jsdc->dangerousThread = _dangerousThread;
     120                 : #endif
     121                 : 
     122             280 :     JS_INIT_CLIST(&jsdc->threadsStates);
     123             280 :     JS_INIT_CLIST(&jsdc->sources);
     124             280 :     JS_INIT_CLIST(&jsdc->removedSources);
     125                 : 
     126             280 :     jsdc->sourceAlterCount = 1;
     127                 : 
     128             280 :     if( ! jsd_CreateAtomTable(jsdc) )
     129               0 :         goto label_newJSDContext_failure;
     130                 : 
     131             280 :     if( ! jsd_InitObjectManager(jsdc) )
     132               0 :         goto label_newJSDContext_failure;
     133                 : 
     134             280 :     if( ! jsd_InitScriptManager(jsdc) )
     135               0 :         goto label_newJSDContext_failure;
     136                 : 
     137             280 :     jsdc->dumbContext = JS_NewContext(jsdc->jsrt, 256);
     138             280 :     if( ! jsdc->dumbContext )
     139               0 :         goto label_newJSDContext_failure;
     140                 : 
     141             280 :     JS_BeginRequest(jsdc->dumbContext);
     142                 : 
     143             280 :     jsdc->glob = JS_NewCompartmentAndGlobalObject(jsdc->dumbContext, &global_class, NULL);
     144                 : 
     145             280 :     if( ! jsdc->glob )
     146               0 :         goto label_newJSDContext_failure;
     147                 : 
     148             280 :     call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, jsdc->glob);
     149             280 :     if( ! call )
     150               0 :         goto label_newJSDContext_failure;
     151                 : 
     152             280 :     ok = JS_InitStandardClasses(jsdc->dumbContext, jsdc->glob);
     153                 : 
     154             280 :     JS_LeaveCrossCompartmentCall(call);
     155             280 :     if( ! ok )
     156               0 :         goto label_newJSDContext_failure;
     157                 : 
     158             280 :     JS_EndRequest(jsdc->dumbContext);
     159                 : 
     160             280 :     jsdc->data = NULL;
     161             280 :     jsdc->inited = JS_TRUE;
     162                 : 
     163             280 :     JSD_LOCK();
     164             280 :     JS_INSERT_LINK(&jsdc->links, &_jsd_context_list);
     165             280 :     JSD_UNLOCK();
     166                 : 
     167             280 :     return jsdc;
     168                 : 
     169                 : label_newJSDContext_failure:
     170               0 :     if( jsdc ) {
     171               0 :         jsd_DestroyObjectManager(jsdc);
     172               0 :         jsd_DestroyAtomTable(jsdc);
     173               0 :         if( jsdc->dumbContext )
     174               0 :             JS_EndRequest(jsdc->dumbContext);
     175               0 :         free(jsdc);
     176                 :     }
     177               0 :     return NULL;
     178                 : }
     179                 : 
     180                 : static void
     181             280 : _destroyJSDContext(JSDContext* jsdc)
     182                 : {
     183             280 :     JSD_ASSERT_VALID_CONTEXT(jsdc);
     184                 : 
     185             280 :     JSD_LOCK();
     186             280 :     JS_REMOVE_LINK(&jsdc->links);
     187             280 :     JSD_UNLOCK();
     188                 : 
     189             280 :     jsd_DestroyObjectManager(jsdc);
     190             280 :     jsd_DestroyAtomTable(jsdc);
     191                 : 
     192             280 :     jsdc->inited = JS_FALSE;
     193                 : 
     194                 :     /*
     195                 :     * We should free jsdc here, but we let it leak in case there are any 
     196                 :     * asynchronous hooks calling into the system using it as a handle
     197                 :     *
     198                 :     * XXX we also leak the locks
     199                 :     */
     200             280 :     JS_DestroyContext(jsdc->dumbContext);
     201             280 :     jsdc->dumbContext = NULL;
     202             280 : }
     203                 : 
     204                 : /***************************************************************************/
     205                 : 
     206                 : JSDContext*
     207             280 : jsd_DebuggerOnForUser(JSRuntime*         jsrt, 
     208                 :                       JSD_UserCallbacks* callbacks, 
     209                 :                       void*              user,
     210                 :                       JSObject*          scopeobj)
     211                 : {
     212                 :     JSDContext* jsdc;
     213             280 :     JSContext* iter = NULL;
     214                 : 
     215             280 :     jsdc = _newJSDContext(jsrt, callbacks, user, scopeobj);
     216             280 :     if( ! jsdc )
     217               0 :         return NULL;
     218                 : 
     219                 :     /*
     220                 :      * Set hooks here.  The new/destroy script hooks are on even when
     221                 :      * the debugger is paused.  The destroy hook so we'll clean up
     222                 :      * internal data structures when scripts are destroyed, and the
     223                 :      * newscript hook for backwards compatibility for now.  We'd like
     224                 :      * to stop doing that.
     225                 :      */
     226             280 :     JS_SetNewScriptHookProc(jsdc->jsrt, jsd_NewScriptHookProc, jsdc);
     227             280 :     JS_SetDestroyScriptHookProc(jsdc->jsrt, jsd_DestroyScriptHookProc, jsdc);
     228             280 :     jsd_DebuggerUnpause(jsdc);
     229                 : #ifdef LIVEWIRE
     230                 :     LWDBG_SetNewScriptHookProc(jsd_NewScriptHookProc, jsdc);
     231                 : #endif
     232             280 :     if( jsdc->userCallbacks.setContext )
     233               0 :         jsdc->userCallbacks.setContext(jsdc, jsdc->user);
     234             280 :     return jsdc;
     235                 : }
     236                 : 
     237                 : JSDContext*
     238               0 : jsd_DebuggerOn(void)
     239                 : {
     240               0 :     JS_ASSERT(_jsrt);
     241               0 :     JS_ASSERT(_validateUserCallbacks(&_callbacks));
     242               0 :     return jsd_DebuggerOnForUser(_jsrt, &_callbacks, _user, NULL);
     243                 : }
     244                 : 
     245                 : void
     246             280 : jsd_DebuggerOff(JSDContext* jsdc)
     247                 : {
     248             280 :     jsd_DebuggerPause(jsdc, JS_TRUE);
     249                 :     /* clear hooks here */
     250             280 :     JS_SetNewScriptHookProc(jsdc->jsrt, NULL, NULL);
     251             280 :     JS_SetDestroyScriptHookProc(jsdc->jsrt, NULL, NULL);
     252                 : #ifdef LIVEWIRE
     253                 :     LWDBG_SetNewScriptHookProc(NULL,NULL);
     254                 : #endif
     255                 : 
     256                 :     /* clean up */
     257             280 :     JSD_LockScriptSubsystem(jsdc);
     258             280 :     jsd_DestroyScriptManager(jsdc);
     259             280 :     JSD_UnlockScriptSubsystem(jsdc);
     260             280 :     jsd_DestroyAllSources(jsdc);
     261                 :     
     262             280 :     _destroyJSDContext(jsdc);
     263                 : 
     264             280 :     if( jsdc->userCallbacks.setContext )
     265               0 :         jsdc->userCallbacks.setContext(NULL, jsdc->user);
     266             280 : }
     267                 : 
     268                 : void
     269             282 : jsd_DebuggerPause(JSDContext* jsdc, JSBool forceAllHooksOff)
     270                 : {
     271             282 :     JS_SetDebuggerHandler(jsdc->jsrt, NULL, NULL);
     272             282 :     if (forceAllHooksOff || !(jsdc->flags & JSD_COLLECT_PROFILE_DATA)) {
     273             282 :         JS_SetExecuteHook(jsdc->jsrt, NULL, NULL);
     274             282 :         JS_SetCallHook(jsdc->jsrt, NULL, NULL);
     275                 :     }
     276             282 :     JS_SetThrowHook(jsdc->jsrt, NULL, NULL);
     277             282 :     JS_SetDebugErrorHook(jsdc->jsrt, NULL, NULL);
     278             282 : }
     279                 : 
     280                 : void
     281             282 : jsd_DebuggerUnpause(JSDContext* jsdc)
     282                 : {
     283             282 :     JS_SetDebuggerHandler(jsdc->jsrt, jsd_DebuggerHandler, jsdc);
     284             282 :     JS_SetExecuteHook(jsdc->jsrt, jsd_TopLevelCallHook, jsdc);
     285             282 :     JS_SetCallHook(jsdc->jsrt, jsd_FunctionCallHook, jsdc);
     286             282 :     JS_SetThrowHook(jsdc->jsrt, jsd_ThrowHandler, jsdc);
     287             282 :     JS_SetDebugErrorHook(jsdc->jsrt, jsd_DebugErrorHook, jsdc);
     288             282 : }
     289                 : 
     290                 : void
     291               0 : jsd_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user)
     292                 : {
     293               0 :     _jsrt = jsrt;
     294               0 :     _user = user;
     295                 : 
     296                 : #ifdef JSD_HAS_DANGEROUS_THREAD
     297                 :     _dangerousThread = JSD_CURRENT_THREAD();
     298                 : #endif
     299                 : 
     300               0 :     if( callbacks )
     301               0 :         memcpy(&_callbacks, callbacks, sizeof(JSD_UserCallbacks));
     302                 :     else
     303               0 :         memset(&_callbacks, 0 , sizeof(JSD_UserCallbacks));
     304               0 : }
     305                 : 
     306                 : void*
     307               0 : jsd_SetContextPrivate(JSDContext* jsdc, void *data)
     308                 : {
     309               0 :     void *rval = jsdc->data;
     310               0 :     jsdc->data = data;
     311               0 :     return data;
     312                 : }
     313                 : 
     314                 : void*
     315               0 : jsd_GetContextPrivate(JSDContext* jsdc)
     316                 : {
     317               0 :     return jsdc->data;
     318                 : }
     319                 : 
     320                 : void
     321               0 : jsd_ClearAllProfileData(JSDContext* jsdc)
     322                 : {
     323                 :     JSDScript *current;
     324                 :     
     325               0 :     JSD_LOCK_SCRIPTS(jsdc);
     326               0 :     current = (JSDScript *)jsdc->scripts.next;
     327               0 :     while (current != (JSDScript *)&jsdc->scripts)
     328                 :     {
     329               0 :         jsd_ClearScriptProfileData(jsdc, current);
     330               0 :         current = (JSDScript *)current->links.next;
     331                 :     }
     332                 : 
     333               0 :     JSD_UNLOCK_SCRIPTS(jsdc);
     334               0 : }
     335                 : 
     336                 : JSDContext*
     337               5 : jsd_JSDContextForJSContext(JSContext* context)
     338                 : {
     339                 :     JSDContext* iter;
     340               5 :     JSDContext* jsdc = NULL;
     341               5 :     JSRuntime*  runtime = JS_GetRuntime(context);
     342                 : 
     343               5 :     JSD_LOCK();
     344              10 :     for( iter = (JSDContext*)_jsd_context_list.next;
     345               5 :          iter != (JSDContext*)&_jsd_context_list;
     346               0 :          iter = (JSDContext*)iter->links.next )
     347                 :     {
     348               5 :         if( runtime == iter->jsrt )
     349                 :         {
     350               5 :             jsdc = iter;
     351               5 :             break;
     352                 :         }
     353                 :     }
     354               5 :     JSD_UNLOCK();
     355               5 :     return jsdc;
     356                 : }    
     357                 : 
     358                 : static JSBool
     359            2007 : jsd_DebugErrorHook(JSContext *cx, const char *message,
     360                 :                    JSErrorReport *report, void *closure)
     361                 : {
     362            2007 :     JSDContext* jsdc = (JSDContext*) closure;
     363                 :     JSD_ErrorReporter errorReporter;
     364                 :     void*             errorReporterData;
     365                 :     
     366            2007 :     if( ! jsdc )
     367                 :     {
     368               0 :         JS_ASSERT(0);
     369               0 :         return JS_TRUE;
     370                 :     }
     371                 :     if( JSD_IS_DANGEROUS_THREAD(jsdc) )
     372                 :         return JS_TRUE;
     373                 : 
     374                 :     /* local in case hook gets cleared on another thread */
     375            2007 :     JSD_LOCK();
     376            2007 :     errorReporter     = jsdc->errorReporter;
     377            2007 :     errorReporterData = jsdc->errorReporterData;
     378            2007 :     JSD_UNLOCK();
     379                 : 
     380            2007 :     if(!errorReporter)
     381            2007 :         return JS_TRUE;
     382                 : 
     383               0 :     switch(errorReporter(jsdc, cx, message, report, errorReporterData))
     384                 :     {
     385                 :         case JSD_ERROR_REPORTER_PASS_ALONG:
     386               0 :             return JS_TRUE;
     387                 :         case JSD_ERROR_REPORTER_RETURN:
     388               0 :             return JS_FALSE;
     389                 :         case JSD_ERROR_REPORTER_DEBUG:
     390                 :         {
     391                 :             jsval rval;
     392                 :             JSD_ExecutionHookProc   hook;
     393                 :             void*                   hookData;
     394                 : 
     395                 :             /* local in case hook gets cleared on another thread */
     396               0 :             JSD_LOCK();
     397               0 :             hook = jsdc->debugBreakHook;
     398               0 :             hookData = jsdc->debugBreakHookData;
     399               0 :             JSD_UNLOCK();
     400                 : 
     401               0 :             jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_DEBUG_REQUESTED,
     402                 :                                   hook, hookData, &rval);
     403                 :             /* XXX Should make this dependent on ExecutionHook retval */
     404               0 :             return JS_TRUE;
     405                 :         }
     406                 :         case JSD_ERROR_REPORTER_CLEAR_RETURN:
     407               0 :             if(report && JSREPORT_IS_EXCEPTION(report->flags))
     408               0 :                 JS_ClearPendingException(cx);
     409               0 :             return JS_FALSE;
     410                 :         default:
     411               0 :             JS_ASSERT(0);
     412                 :             break;
     413                 :     }
     414               0 :     return JS_TRUE;
     415                 : }
     416                 : 
     417                 : JSBool
     418             282 : jsd_SetErrorReporter(JSDContext*       jsdc, 
     419                 :                      JSD_ErrorReporter reporter, 
     420                 :                      void*             callerdata)
     421                 : {
     422             282 :     JSD_LOCK();
     423             282 :     jsdc->errorReporter = reporter;
     424             282 :     jsdc->errorReporterData = callerdata;
     425             282 :     JSD_UNLOCK();
     426             282 :     return JS_TRUE;
     427                 : }
     428                 : 
     429                 : JSBool
     430               0 : jsd_GetErrorReporter(JSDContext*        jsdc, 
     431                 :                      JSD_ErrorReporter* reporter, 
     432                 :                      void**             callerdata)
     433                 : {
     434               0 :     JSD_LOCK();
     435               0 :     if( reporter )
     436               0 :         *reporter = jsdc->errorReporter;
     437               0 :     if( callerdata )
     438               0 :         *callerdata = jsdc->errorReporterData;
     439               0 :     JSD_UNLOCK();
     440               0 :     return JS_TRUE;
     441                 : }

Generated by: LCOV version 1.7