LCOV - code coverage report
Current view: directory - js/jsd - jsd_xpc.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1670 394 23.6 %
Date: 2012-06-02 Functions: 226 63 27.9 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  *
       3                 :  * ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Robert Ginda, <rginda@netscape.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "jsdbgapi.h"
      41                 : #include "jslock.h"
      42                 : #include "jsd_xpc.h"
      43                 : 
      44                 : #include "nsIXPConnect.h"
      45                 : #include "mozilla/ModuleUtils.h"
      46                 : #include "nsIServiceManager.h"
      47                 : #include "nsIScriptGlobalObject.h"
      48                 : #include "nsIObserver.h"
      49                 : #include "nsIObserverService.h"
      50                 : #include "nsICategoryManager.h"
      51                 : #include "nsIJSRuntimeService.h"
      52                 : #include "nsIThreadInternal.h"
      53                 : #include "nsThreadUtils.h"
      54                 : #include "nsMemory.h"
      55                 : #include "jsdebug.h"
      56                 : #include "nsReadableUtils.h"
      57                 : #include "nsCRT.h"
      58                 : 
      59                 : /* XXX DOM dependency */
      60                 : #include "nsIScriptContext.h"
      61                 : #include "nsIJSContextStack.h"
      62                 : 
      63                 : /*
      64                 :  * defining CAUTIOUS_SCRIPTHOOK makes jsds disable GC while calling out to the
      65                 :  * script hook.  This was a hack to avoid some js engine problems that should
      66                 :  * be fixed now (see Mozilla bug 77636).
      67                 :  */
      68                 : #undef CAUTIOUS_SCRIPTHOOK
      69                 : 
      70                 : #ifdef DEBUG_verbose
      71                 : #   define DEBUG_COUNT(name, count)                                             \
      72                 :         { if ((count % 10) == 0) printf (name ": %i\n", count); }
      73                 : #   define DEBUG_CREATE(name, count) {count++; DEBUG_COUNT ("+++++ "name,count)}
      74                 : #   define DEBUG_DESTROY(name, count) {count--; DEBUG_COUNT ("----- "name,count)}
      75                 : #else
      76                 : #   define DEBUG_CREATE(name, count) 
      77                 : #   define DEBUG_DESTROY(name, count)
      78                 : #endif
      79                 : 
      80                 : #define ASSERT_VALID_CONTEXT   { if (!mCx) return NS_ERROR_NOT_AVAILABLE; }
      81                 : #define ASSERT_VALID_EPHEMERAL { if (!mValid) return NS_ERROR_NOT_AVAILABLE; }
      82                 : 
      83                 : #define JSDSERVICE_CID                               \
      84                 : { /* f1299dc2-1dd1-11b2-a347-ee6b7660e048 */         \
      85                 :      0xf1299dc2,                                     \
      86                 :      0x1dd1,                                         \
      87                 :      0x11b2,                                         \
      88                 :     {0xa3, 0x47, 0xee, 0x6b, 0x76, 0x60, 0xe0, 0x48} \
      89                 : }
      90                 : 
      91                 : #define JSDASO_CID                                   \
      92                 : { /* 2fd6b7f6-eb8c-4f32-ad26-113f2c02d0fe */         \
      93                 :      0x2fd6b7f6,                                     \
      94                 :      0xeb8c,                                         \
      95                 :      0x4f32,                                         \
      96                 :     {0xad, 0x26, 0x11, 0x3f, 0x2c, 0x02, 0xd0, 0xfe} \
      97                 : }
      98                 : 
      99                 : #define JSDS_MAJOR_VERSION 1
     100                 : #define JSDS_MINOR_VERSION 2
     101                 : 
     102                 : #define NS_CATMAN_CTRID   "@mozilla.org/categorymanager;1"
     103                 : #define NS_JSRT_CTRID     "@mozilla.org/js/xpc/RuntimeService;1"
     104                 : 
     105                 : #define AUTOREG_CATEGORY  "xpcom-autoregistration"
     106                 : #define APPSTART_CATEGORY "app-startup"
     107                 : #define JSD_AUTOREG_ENTRY "JSDebugger Startup Observer"
     108                 : #define JSD_STARTUP_ENTRY "JSDebugger Startup Observer"
     109                 : 
     110                 : static void
     111                 : jsds_GCSliceCallbackProc (JSRuntime *rt, js::GCProgress progress, const js::GCDescription &desc);
     112                 : 
     113                 : /*******************************************************************************
     114                 :  * global vars
     115                 :  ******************************************************************************/
     116                 : 
     117                 : const char implementationString[] = "Mozilla JavaScript Debugger Service";
     118                 : 
     119                 : const char jsdServiceCtrID[] = "@mozilla.org/js/jsd/debugger-service;1";
     120                 : const char jsdARObserverCtrID[] = "@mozilla.org/js/jsd/app-start-observer;2";
     121                 : const char jsdASObserverCtrID[] = "service,@mozilla.org/js/jsd/app-start-observer;2";
     122                 : 
     123                 : #ifdef DEBUG_verbose
     124                 : PRUint32 gScriptCount   = 0;
     125                 : PRUint32 gValueCount    = 0;
     126                 : PRUint32 gPropertyCount = 0;
     127                 : PRUint32 gContextCount  = 0;
     128                 : PRUint32 gFrameCount  = 0;
     129                 : #endif
     130                 : 
     131                 : static jsdService          *gJsds               = 0;
     132                 : static js::GCSliceCallback gPrevGCSliceCallback = jsds_GCSliceCallbackProc;
     133                 : static bool                gGCRunning           = false;
     134                 : 
     135                 : static struct DeadScript {
     136                 :     PRCList     links;
     137                 :     JSDContext *jsdc;
     138                 :     jsdIScript *script;
     139                 : } *gDeadScripts = nsnull;
     140                 : 
     141                 : enum PatternType {
     142                 :     ptIgnore     = 0U,
     143                 :     ptStartsWith = 1U,
     144                 :     ptEndsWith   = 2U,
     145                 :     ptContains   = 3U,
     146                 :     ptEquals     = 4U
     147                 : };
     148                 : 
     149                 : static struct FilterRecord {
     150                 :     PRCList      links;
     151                 :     jsdIFilter  *filterObject;
     152                 :     void        *glob;
     153                 :     nsCString    urlPattern;
     154                 :     PatternType  patternType;
     155                 :     PRUint32     startLine;
     156                 :     PRUint32     endLine;
     157                 : } *gFilters = nsnull;
     158                 : 
     159                 : static struct LiveEphemeral *gLiveValues      = nsnull;
     160                 : static struct LiveEphemeral *gLiveProperties  = nsnull;
     161                 : static struct LiveEphemeral *gLiveContexts    = nsnull;
     162                 : static struct LiveEphemeral *gLiveStackFrames = nsnull;
     163                 : 
     164                 : /*******************************************************************************
     165                 :  * utility functions for ephemeral lists
     166                 :  *******************************************************************************/
     167                 : already_AddRefed<jsdIEphemeral>
     168               1 : jsds_FindEphemeral (LiveEphemeral **listHead, void *key)
     169                 : {
     170               1 :     if (!*listHead)
     171               1 :         return nsnull;
     172                 :     
     173                 :     LiveEphemeral *lv_record = 
     174                 :         reinterpret_cast<LiveEphemeral *>
     175               0 :                         (PR_NEXT_LINK(&(*listHead)->links));
     176               0 :     do
     177                 :     {
     178               0 :         if (lv_record->key == key)
     179                 :         {
     180               0 :             NS_IF_ADDREF(lv_record->value);
     181               0 :             return lv_record->value;
     182                 :         }
     183                 :         lv_record = reinterpret_cast<LiveEphemeral *>
     184               0 :                                     (PR_NEXT_LINK(&lv_record->links));
     185                 :     }
     186                 :     while (lv_record != *listHead);
     187                 : 
     188               0 :     return nsnull;
     189                 : }
     190                 : 
     191                 : void
     192               1 : jsds_InvalidateAllEphemerals (LiveEphemeral **listHead)
     193                 : {
     194                 :     LiveEphemeral *lv_record = 
     195                 :         reinterpret_cast<LiveEphemeral *>
     196               1 :                         (PR_NEXT_LINK(&(*listHead)->links));
     197               1 :     do
     198                 :     {
     199                 :         LiveEphemeral *next =
     200                 :             reinterpret_cast<LiveEphemeral *>
     201               1 :                             (PR_NEXT_LINK(&lv_record->links));
     202               1 :         lv_record->value->Invalidate();
     203               1 :         lv_record = next;
     204                 :     }
     205                 :     while (*listHead);
     206               1 : }
     207                 : 
     208                 : void
     209               3 : jsds_InsertEphemeral (LiveEphemeral **listHead, LiveEphemeral *item)
     210                 : {
     211               3 :     if (*listHead) {
     212                 :         /* if the list exists, add to it */
     213               1 :         PR_APPEND_LINK(&item->links, &(*listHead)->links);
     214                 :     } else {
     215                 :         /* otherwise create the list */
     216               2 :         PR_INIT_CLIST(&item->links);
     217               2 :         *listHead = item;
     218                 :     }
     219               3 : }
     220                 : 
     221                 : void
     222               3 : jsds_RemoveEphemeral (LiveEphemeral **listHead, LiveEphemeral *item)
     223                 : {
     224                 :     LiveEphemeral *next = reinterpret_cast<LiveEphemeral *>
     225               3 :                                           (PR_NEXT_LINK(&item->links));
     226                 : 
     227               3 :     if (next == item)
     228                 :     {
     229                 :         /* if the current item is also the next item, we're the only element,
     230                 :          * null out the list head */
     231               2 :         NS_ASSERTION (*listHead == item,
     232                 :                       "How could we not be the head of a one item list?");
     233               2 :         *listHead = nsnull;
     234                 :     }
     235               1 :     else if (item == *listHead)
     236                 :     {
     237                 :         /* otherwise, if we're currently the list head, change it */
     238               0 :         *listHead = next;
     239                 :     }
     240                 :     
     241               3 :     PR_REMOVE_AND_INIT_LINK(&item->links);
     242               3 : }
     243                 : 
     244                 : /*******************************************************************************
     245                 :  * utility functions for filters
     246                 :  *******************************************************************************/
     247                 : void
     248               0 : jsds_FreeFilter (FilterRecord *rec)
     249                 : {
     250               0 :     NS_IF_RELEASE (rec->filterObject);
     251               0 :     PR_Free (rec);
     252               0 : }
     253                 : 
     254                 : /* copies appropriate |filter| attributes into |rec|.
     255                 :  * False return indicates failure, the contents of |rec| will not be changed.
     256                 :  */
     257                 : bool
     258               0 : jsds_SyncFilter (FilterRecord *rec, jsdIFilter *filter)
     259                 : {
     260               0 :     NS_ASSERTION (rec, "jsds_SyncFilter without rec");
     261               0 :     NS_ASSERTION (filter, "jsds_SyncFilter without filter");
     262                 :     
     263               0 :     JSObject *glob_proper = nsnull;
     264               0 :     nsCOMPtr<nsISupports> glob;
     265               0 :     nsresult rv = filter->GetGlobalObject(getter_AddRefs(glob));
     266               0 :     if (NS_FAILED(rv))
     267               0 :         return false;
     268               0 :     if (glob) {
     269               0 :         nsCOMPtr<nsIScriptGlobalObject> nsiglob = do_QueryInterface(glob);
     270               0 :         if (nsiglob)
     271               0 :             glob_proper = nsiglob->GetGlobalJSObject();
     272                 :     }
     273                 :     
     274                 :     PRUint32 startLine;
     275               0 :     rv = filter->GetStartLine(&startLine);
     276               0 :     if (NS_FAILED(rv))
     277               0 :         return false;
     278                 : 
     279                 :     PRUint32 endLine;
     280               0 :     rv = filter->GetStartLine(&endLine);
     281               0 :     if (NS_FAILED(rv))
     282               0 :         return false;    
     283                 : 
     284               0 :     nsCAutoString urlPattern;
     285               0 :     rv = filter->GetUrlPattern (urlPattern);
     286               0 :     if (NS_FAILED(rv))
     287               0 :         return false;
     288                 :     
     289               0 :     PRUint32 len = urlPattern.Length();
     290               0 :     if (len) {
     291               0 :         if (urlPattern[0] == '*') {
     292                 :             /* pattern starts with a *, shift all chars once to the left,
     293                 :              * including the trailing null. */
     294               0 :             urlPattern = Substring(urlPattern, 1, len);
     295                 : 
     296               0 :             if (urlPattern[len - 2] == '*') {
     297                 :                 /* pattern is in the format "*foo*", overwrite the final * with
     298                 :                  * a null. */
     299               0 :                 urlPattern.Truncate(len - 2);
     300               0 :                 rec->patternType = ptContains;
     301                 :             } else {
     302                 :                 /* pattern is in the format "*foo", just make a note of the
     303                 :                  * new length. */
     304               0 :                 rec->patternType = ptEndsWith;
     305                 :             }
     306               0 :         } else if (urlPattern[len - 1] == '*') {
     307                 :             /* pattern is in the format "foo*", overwrite the final * with a 
     308                 :              * null. */
     309               0 :             urlPattern.Truncate(len - 1);
     310               0 :             rec->patternType = ptStartsWith;
     311                 :         } else {
     312                 :             /* pattern is in the format "foo". */
     313               0 :             rec->patternType = ptEquals;
     314                 :         }
     315                 :     } else {
     316               0 :         rec->patternType = ptIgnore;
     317                 :     }
     318                 : 
     319                 :     /* we got everything we need without failing, now copy it into rec. */
     320                 : 
     321               0 :     if (rec->filterObject != filter) {
     322               0 :         NS_IF_RELEASE(rec->filterObject);
     323               0 :         NS_ADDREF(filter);
     324               0 :         rec->filterObject = filter;
     325                 :     }
     326                 :     
     327               0 :     rec->glob = glob_proper;
     328                 :     
     329               0 :     rec->startLine     = startLine;
     330               0 :     rec->endLine       = endLine;
     331                 :     
     332               0 :     rec->urlPattern = urlPattern;
     333                 : 
     334               0 :     return true;
     335                 :             
     336                 : }
     337                 : 
     338                 : FilterRecord *
     339               0 : jsds_FindFilter (jsdIFilter *filter)
     340                 : {
     341               0 :     if (!gFilters)
     342               0 :         return nsnull;
     343                 :     
     344               0 :     FilterRecord *current = gFilters;
     345                 :     
     346               0 :     do {
     347               0 :         if (current->filterObject == filter)
     348               0 :             return current;
     349                 :         current = reinterpret_cast<FilterRecord *>
     350               0 :                                   (PR_NEXT_LINK(&current->links));
     351                 :     } while (current != gFilters);
     352                 :     
     353               0 :     return nsnull;
     354                 : }
     355                 : 
     356                 : /* returns true if the hook should be executed. */
     357                 : bool
     358               1 : jsds_FilterHook (JSDContext *jsdc, JSDThreadState *state)
     359                 : {
     360               1 :     JSContext *cx = JSD_GetJSContext (jsdc, state);
     361               1 :     void *glob = static_cast<void *>(JS_GetGlobalObject (cx));
     362                 : 
     363               1 :     if (!glob) {
     364               0 :         NS_WARNING("No global in threadstate");
     365               0 :         return false;
     366                 :     }
     367                 :     
     368               1 :     JSDStackFrameInfo *frame = JSD_GetStackFrame (jsdc, state);
     369                 : 
     370               1 :     if (!frame) {
     371               0 :         NS_WARNING("No frame in threadstate");
     372               0 :         return false;
     373                 :     }
     374                 : 
     375               1 :     JSDScript *script = JSD_GetScriptForStackFrame (jsdc, state, frame);
     376               1 :     if (!script)
     377               0 :         return true;
     378                 : 
     379               1 :     uintptr_t pc = JSD_GetPCForStackFrame (jsdc, state, frame);
     380                 : 
     381               2 :     nsCString url(JSD_GetScriptFilename (jsdc, script));
     382               1 :     if (url.IsEmpty()) {
     383               0 :         NS_WARNING ("Script with no filename");
     384               0 :         return false;
     385                 :     }
     386                 : 
     387               1 :     if (!gFilters)
     388               1 :         return true;    
     389                 : 
     390               0 :     PRUint32 currentLine = JSD_GetClosestLine (jsdc, script, pc);
     391               0 :     PRUint32 len = 0;
     392               0 :     FilterRecord *currentFilter = gFilters;
     393               0 :     do {
     394               0 :         PRUint32 flags = 0;
     395                 : 
     396                 : #ifdef DEBUG
     397                 :         nsresult rv =
     398                 : #endif
     399               0 :             currentFilter->filterObject->GetFlags(&flags);
     400               0 :         NS_ASSERTION(NS_SUCCEEDED(rv), "Error getting flags for filter");
     401                 : 
     402               0 :         if (flags & jsdIFilter::FLAG_ENABLED) {
     403                 :             /* if there is no glob, or the globs match */
     404               0 :             if ((!currentFilter->glob || currentFilter->glob == glob) &&
     405                 :                 /* and there is no start line, or the start line is before 
     406                 :                  * or equal to the current */
     407               0 :                 (!currentFilter->startLine || 
     408                 :                  currentFilter->startLine <= currentLine) &&
     409                 :                 /* and there is no end line, or the end line is after
     410                 :                  * or equal to the current */
     411               0 :                 (!currentFilter->endLine ||
     412                 :                  currentFilter->endLine >= currentLine)) {
     413                 :                 /* then we're going to have to compare the url. */
     414               0 :                 if (currentFilter->patternType == ptIgnore)
     415               0 :                     return !!(flags & jsdIFilter::FLAG_PASS);
     416                 : 
     417               0 :                 if (!len)
     418               0 :                     len = url.Length();
     419               0 :                 nsCString urlPattern = currentFilter->urlPattern;
     420               0 :                 PRUint32 patternLength = urlPattern.Length();
     421               0 :                 if (len >= patternLength) {
     422               0 :                     switch (currentFilter->patternType) {
     423                 :                         case ptEquals:
     424               0 :                             if (urlPattern.Equals(url))
     425               0 :                                 return !!(flags & jsdIFilter::FLAG_PASS);
     426               0 :                             break;
     427                 :                         case ptStartsWith:
     428               0 :                             if (urlPattern.Equals(Substring(url, 0, patternLength)))
     429               0 :                                 return !!(flags & jsdIFilter::FLAG_PASS);
     430               0 :                             break;
     431                 :                         case ptEndsWith:
     432               0 :                             if (urlPattern.Equals(Substring(url, len - patternLength)))
     433               0 :                                 return !!(flags & jsdIFilter::FLAG_PASS);
     434               0 :                             break;
     435                 :                         case ptContains:
     436                 :                             {
     437               0 :                                 nsACString::const_iterator start, end;
     438               0 :                                 url.BeginReading(start);
     439               0 :                                 url.EndReading(end);
     440               0 :                                 if (FindInReadable(currentFilter->urlPattern, start, end))
     441               0 :                                     return !!(flags & jsdIFilter::FLAG_PASS);
     442                 :                             }
     443               0 :                             break;
     444                 :                         default:
     445               0 :                             NS_ERROR("Invalid pattern type");
     446                 :                     }
     447                 :                 }                
     448                 :             }
     449                 :         }
     450                 :         currentFilter = reinterpret_cast<FilterRecord *>
     451               0 :                                         (PR_NEXT_LINK(&currentFilter->links));
     452                 :     } while (currentFilter != gFilters);
     453                 : 
     454               0 :     return true;
     455                 :     
     456                 : }
     457                 : 
     458                 : /*******************************************************************************
     459                 :  * c callbacks
     460                 :  *******************************************************************************/
     461                 : 
     462                 : static void
     463               1 : jsds_NotifyPendingDeadScripts (JSRuntime *rt)
     464                 : {
     465               1 :     jsdService *jsds = gJsds;
     466                 : 
     467               2 :     nsCOMPtr<jsdIScriptHook> hook;
     468               1 :     if (jsds) {
     469               1 :         NS_ADDREF(jsds);
     470               1 :         jsds->GetScriptHook (getter_AddRefs(hook));
     471               1 :         jsds->DoPause(nsnull, true);
     472                 :     }
     473                 : 
     474               1 :     DeadScript *deadScripts = gDeadScripts;
     475               1 :     gDeadScripts = nsnull;
     476               4 :     while (deadScripts) {
     477               2 :         DeadScript *ds = deadScripts;
     478                 :         /* get next deleted script */
     479                 :         deadScripts = reinterpret_cast<DeadScript *>
     480               2 :                                        (PR_NEXT_LINK(&ds->links));
     481               2 :         if (deadScripts == ds)
     482               1 :             deadScripts = nsnull;
     483                 : 
     484               2 :         if (hook)
     485                 :         {
     486                 :             /* tell the user this script has been destroyed */
     487                 : #ifdef CAUTIOUS_SCRIPTHOOK
     488                 :             JS_UNKEEP_ATOMS(rt);
     489                 : #endif
     490               0 :             hook->OnScriptDestroyed (ds->script);
     491                 : #ifdef CAUTIOUS_SCRIPTHOOK
     492                 :             JS_KEEP_ATOMS(rt);
     493                 : #endif
     494                 :         }
     495                 : 
     496                 :         /* take it out of the circular list */
     497               2 :         PR_REMOVE_LINK(&ds->links);
     498                 : 
     499                 :         /* addref came from the FromPtr call in jsds_ScriptHookProc */
     500               2 :         NS_RELEASE(ds->script);
     501                 :         /* free the struct! */
     502               2 :         PR_Free(ds);
     503                 :     }
     504                 : 
     505               1 :     if (jsds) {
     506               1 :         jsds->DoUnPause(nsnull, true);
     507               1 :         NS_RELEASE(jsds);
     508                 :     }
     509               1 : }
     510                 : 
     511                 : static void
     512            8096 : jsds_GCSliceCallbackProc (JSRuntime *rt, js::GCProgress progress, const js::GCDescription &desc)
     513                 : {
     514            8096 :     if (progress == js::GC_CYCLE_END || progress == js::GC_SLICE_END) {
     515            4048 :         NS_ASSERTION(gGCRunning, "GC slice callback was missed");
     516                 : 
     517            8097 :         while (gDeadScripts)
     518               1 :             jsds_NotifyPendingDeadScripts (rt);
     519                 : 
     520            4048 :         gGCRunning = false;
     521                 :     } else {
     522            4048 :         NS_ASSERTION(!gGCRunning, "should not re-enter GC");
     523            4048 :         gGCRunning = true;
     524                 :     }
     525                 : 
     526            8096 :     if (gPrevGCSliceCallback)
     527               0 :         (*gPrevGCSliceCallback)(rt, progress, desc);
     528            8096 : }
     529                 : 
     530                 : static unsigned
     531               0 : jsds_ErrorHookProc (JSDContext *jsdc, JSContext *cx, const char *message,
     532                 :                     JSErrorReport *report, void *callerdata)
     533                 : {
     534                 :     static bool running = false;
     535                 : 
     536               0 :     nsCOMPtr<jsdIErrorHook> hook;
     537               0 :     gJsds->GetErrorHook(getter_AddRefs(hook));
     538               0 :     if (!hook)
     539               0 :         return JSD_ERROR_REPORTER_PASS_ALONG;
     540                 : 
     541               0 :     if (running)
     542               0 :         return JSD_ERROR_REPORTER_PASS_ALONG;
     543                 :     
     544               0 :     running = true;
     545                 :     
     546               0 :     nsCOMPtr<jsdIValue> val;
     547               0 :     if (JS_IsExceptionPending(cx)) {
     548                 :         jsval jv;
     549               0 :         JS_GetPendingException(cx, &jv);
     550               0 :         JSDValue *jsdv = JSD_NewValue (jsdc, jv);
     551               0 :         val = getter_AddRefs(jsdValue::FromPtr(jsdc, jsdv));
     552                 :     }
     553                 :     
     554               0 :     nsCAutoString fileName;
     555                 :     PRUint32    line;
     556                 :     PRUint32    pos;
     557                 :     PRUint32    flags;
     558                 :     PRUint32    errnum;
     559                 :     bool        rval;
     560               0 :     if (report) {
     561               0 :         fileName.Assign(report->filename);
     562               0 :         line = report->lineno;
     563               0 :         pos = report->tokenptr - report->linebuf;
     564               0 :         flags = report->flags;
     565               0 :         errnum = report->errorNumber;
     566                 :     }
     567                 :     else
     568                 :     {
     569               0 :         line     = 0;
     570               0 :         pos      = 0;
     571               0 :         flags    = 0;
     572               0 :         errnum   = 0;
     573                 :     }
     574                 :     
     575               0 :     gJsds->DoPause(nsnull, true);
     576               0 :     hook->OnError (nsDependentCString(message), fileName, line, pos, flags, errnum, val, &rval);
     577               0 :     gJsds->DoUnPause(nsnull, true);
     578                 :     
     579               0 :     running = false;
     580               0 :     if (!rval)
     581               0 :         return JSD_ERROR_REPORTER_DEBUG;
     582                 :     
     583               0 :     return JSD_ERROR_REPORTER_PASS_ALONG;
     584                 : }
     585                 : 
     586                 : static JSBool
     587               0 : jsds_CallHookProc (JSDContext* jsdc, JSDThreadState* jsdthreadstate,
     588                 :                    unsigned type, void* callerdata)
     589                 : {
     590               0 :     nsCOMPtr<jsdICallHook> hook;
     591                 : 
     592               0 :     switch (type)
     593                 :     {
     594                 :         case JSD_HOOK_TOPLEVEL_START:
     595                 :         case JSD_HOOK_TOPLEVEL_END:
     596               0 :             gJsds->GetTopLevelHook(getter_AddRefs(hook));
     597               0 :             break;
     598                 :             
     599                 :         case JSD_HOOK_FUNCTION_CALL:
     600                 :         case JSD_HOOK_FUNCTION_RETURN:
     601               0 :             gJsds->GetFunctionHook(getter_AddRefs(hook));
     602               0 :             break;
     603                 : 
     604                 :         default:
     605               0 :             NS_ASSERTION (0, "Unknown hook type.");
     606                 :     }
     607                 :     
     608               0 :     if (!hook)
     609               0 :         return JS_TRUE;
     610                 : 
     611               0 :     if (!jsds_FilterHook (jsdc, jsdthreadstate))
     612               0 :         return JS_FALSE;
     613                 : 
     614               0 :     JSDStackFrameInfo *native_frame = JSD_GetStackFrame (jsdc, jsdthreadstate);
     615                 :     nsCOMPtr<jsdIStackFrame> frame =
     616                 :         getter_AddRefs(jsdStackFrame::FromPtr(jsdc, jsdthreadstate,
     617               0 :                                               native_frame));
     618               0 :     gJsds->DoPause(nsnull, true);
     619               0 :     hook->OnCall(frame, type);    
     620               0 :     gJsds->DoUnPause(nsnull, true);
     621               0 :     jsdStackFrame::InvalidateAll();
     622                 : 
     623               0 :     return JS_TRUE;
     624                 : }
     625                 : 
     626                 : static PRUint32
     627               5 : jsds_ExecutionHookProc (JSDContext* jsdc, JSDThreadState* jsdthreadstate,
     628                 :                         unsigned type, void* callerdata, jsval* rval)
     629                 : {
     630              10 :     nsCOMPtr<jsdIExecutionHook> hook(0);
     631               5 :     PRUint32 hook_rv = JSD_HOOK_RETURN_CONTINUE;
     632              10 :     nsCOMPtr<jsdIValue> js_rv;
     633                 : 
     634               5 :     switch (type)
     635                 :     {
     636                 :         case JSD_HOOK_INTERRUPTED:
     637               0 :             gJsds->GetInterruptHook(getter_AddRefs(hook));
     638               0 :             break;
     639                 :         case JSD_HOOK_DEBUG_REQUESTED:
     640               0 :             gJsds->GetDebugHook(getter_AddRefs(hook));
     641               0 :             break;
     642                 :         case JSD_HOOK_DEBUGGER_KEYWORD:
     643               0 :             gJsds->GetDebuggerHook(getter_AddRefs(hook));
     644               0 :             break;
     645                 :         case JSD_HOOK_BREAKPOINT:
     646                 :             {
     647                 :                 /* we can't pause breakpoints the way we pause the other
     648                 :                  * execution hooks (at least, not easily.)  Instead we bail
     649                 :                  * here if the service is paused. */
     650                 :                 PRUint32 level;
     651               5 :                 gJsds->GetPauseDepth(&level);
     652               5 :                 if (!level)
     653               4 :                     gJsds->GetBreakpointHook(getter_AddRefs(hook));
     654                 :             }
     655               5 :             break;
     656                 :         case JSD_HOOK_THROW:
     657                 :         {
     658               0 :             hook_rv = JSD_HOOK_RETURN_CONTINUE_THROW;
     659               0 :             gJsds->GetThrowHook(getter_AddRefs(hook));
     660               0 :             if (hook) {
     661               0 :                 JSDValue *jsdv = JSD_GetException (jsdc, jsdthreadstate);
     662               0 :                 js_rv = getter_AddRefs(jsdValue::FromPtr (jsdc, jsdv));
     663                 :             }
     664               0 :             break;
     665                 :         }
     666                 :         default:
     667               0 :             NS_ASSERTION (0, "Unknown hook type.");
     668                 :     }
     669                 : 
     670               5 :     if (!hook)
     671               4 :         return hook_rv;
     672                 :     
     673               1 :     if (!jsds_FilterHook (jsdc, jsdthreadstate))
     674               0 :         return JSD_HOOK_RETURN_CONTINUE;
     675                 :     
     676               1 :     JSDStackFrameInfo *native_frame = JSD_GetStackFrame (jsdc, jsdthreadstate);
     677                 :     nsCOMPtr<jsdIStackFrame> frame =
     678                 :         getter_AddRefs(jsdStackFrame::FromPtr(jsdc, jsdthreadstate,
     679               2 :                                               native_frame));
     680               1 :     gJsds->DoPause(nsnull, true);
     681               1 :     jsdIValue *inout_rv = js_rv;
     682               1 :     NS_IF_ADDREF(inout_rv);
     683               1 :     hook->OnExecute (frame, type, &inout_rv, &hook_rv);
     684               1 :     js_rv = inout_rv;
     685               1 :     NS_IF_RELEASE(inout_rv);
     686               1 :     gJsds->DoUnPause(nsnull, true);
     687               1 :     jsdStackFrame::InvalidateAll();
     688                 :         
     689               1 :     if (hook_rv == JSD_HOOK_RETURN_RET_WITH_VAL ||
     690                 :         hook_rv == JSD_HOOK_RETURN_THROW_WITH_VAL) {
     691               0 :         *rval = JSVAL_VOID;
     692               0 :         if (js_rv) {
     693                 :             JSDValue *jsdv;
     694               0 :             if (NS_SUCCEEDED(js_rv->GetJSDValue (&jsdv)))
     695               0 :                 *rval = JSD_GetValueWrappedJSVal(jsdc, jsdv);
     696                 :         }
     697                 :     }
     698                 :     
     699               1 :     return hook_rv;
     700                 : }
     701                 : 
     702                 : static void
     703          261799 : jsds_ScriptHookProc (JSDContext* jsdc, JSDScript* jsdscript, JSBool creating,
     704                 :                      void* callerdata)
     705                 : {
     706                 : #ifdef CAUTIOUS_SCRIPTHOOK
     707                 :     JSContext *cx = JSD_GetDefaultJSContext(jsdc);
     708                 :     JSRuntime *rt = JS_GetRuntime(cx);
     709                 : #endif
     710                 : 
     711          261799 :     if (creating) {
     712          413146 :         nsCOMPtr<jsdIScriptHook> hook;
     713          206573 :         gJsds->GetScriptHook(getter_AddRefs(hook));
     714                 : 
     715                 :         /* a script is being created */
     716          206573 :         if (!hook) {
     717                 :             /* nobody cares, just exit */
     718                 :             return;
     719                 :         }
     720                 :             
     721                 :         nsCOMPtr<jsdIScript> script = 
     722               0 :             getter_AddRefs(jsdScript::FromPtr(jsdc, jsdscript));
     723                 : #ifdef CAUTIOUS_SCRIPTHOOK
     724                 :         JS_UNKEEP_ATOMS(rt);
     725                 : #endif
     726               0 :         gJsds->DoPause(nsnull, true);
     727               0 :         hook->OnScriptCreated (script);
     728               0 :         gJsds->DoUnPause(nsnull, true);
     729                 : #ifdef CAUTIOUS_SCRIPTHOOK
     730                 :         JS_KEEP_ATOMS(rt);
     731                 : #endif
     732                 :     } else {
     733                 :         /* a script is being destroyed.  even if there is no registered hook
     734                 :          * we'll still need to invalidate the jsdIScript record, in order
     735                 :          * to remove the reference held in the JSDScript private data. */
     736                 :         nsCOMPtr<jsdIScript> jsdis = 
     737          110452 :             static_cast<jsdIScript *>(JSD_GetScriptPrivate(jsdscript));
     738           55226 :         if (!jsdis)
     739                 :             return;
     740                 : 
     741               2 :         jsdis->Invalidate();
     742                 : 
     743               2 :         if (!gGCRunning) {
     744               0 :             nsCOMPtr<jsdIScriptHook> hook;
     745               0 :             gJsds->GetScriptHook(getter_AddRefs(hook));
     746               0 :             if (!hook)
     747                 :                 return;
     748                 : 
     749                 :             /* if GC *isn't* running, we can tell the user about the script
     750                 :              * delete now. */
     751                 : #ifdef CAUTIOUS_SCRIPTHOOK
     752                 :             JS_UNKEEP_ATOMS(rt);
     753                 : #endif
     754                 :                 
     755               0 :             gJsds->DoPause(nsnull, true);
     756               0 :             hook->OnScriptDestroyed (jsdis);
     757               0 :             gJsds->DoUnPause(nsnull, true);
     758                 : #ifdef CAUTIOUS_SCRIPTHOOK
     759                 :             JS_KEEP_ATOMS(rt);
     760                 : #endif
     761                 :         } else {
     762                 :             /* if a GC *is* running, we've got to wait until it's done before
     763                 :              * we can execute any JS, so we queue the notification in a PRCList
     764                 :              * until GC tells us it's done. See jsds_GCCallbackProc(). */
     765               2 :             DeadScript *ds = PR_NEW(DeadScript);
     766               2 :             if (!ds)
     767                 :                 return; /* NS_ERROR_OUT_OF_MEMORY */
     768                 :         
     769               2 :             ds->jsdc = jsdc;
     770               2 :             ds->script = jsdis;
     771               2 :             NS_ADDREF(ds->script);
     772               2 :             if (gDeadScripts)
     773                 :                 /* if the queue exists, add to it */
     774               1 :                 PR_APPEND_LINK(&ds->links, &gDeadScripts->links);
     775                 :             else {
     776                 :                 /* otherwise create the queue */
     777               1 :                 PR_INIT_CLIST(&ds->links);
     778               1 :                 gDeadScripts = ds;
     779                 :             }
     780                 :         }
     781                 :     }            
     782                 : }
     783                 : 
     784                 : /*******************************************************************************
     785                 :  * reflected jsd data structures
     786                 :  *******************************************************************************/
     787                 : 
     788                 : /* Contexts */
     789                 : /*
     790                 : NS_IMPL_THREADSAFE_ISUPPORTS2(jsdContext, jsdIContext, jsdIEphemeral);
     791                 : 
     792                 : NS_IMETHODIMP
     793                 : jsdContext::GetJSDContext(JSDContext **_rval)
     794                 : {
     795                 :     *_rval = mCx;
     796                 :     return NS_OK;
     797                 : }
     798                 : */
     799                 : 
     800                 : /* Objects */
     801               0 : NS_IMPL_THREADSAFE_ISUPPORTS1(jsdObject, jsdIObject)
     802                 : 
     803                 : NS_IMETHODIMP
     804               0 : jsdObject::GetJSDContext(JSDContext **_rval)
     805                 : {
     806               0 :     *_rval = mCx;
     807               0 :     return NS_OK;
     808                 : }
     809                 : 
     810                 : NS_IMETHODIMP
     811               0 : jsdObject::GetJSDObject(JSDObject **_rval)
     812                 : {
     813               0 :     *_rval = mObject;
     814               0 :     return NS_OK;
     815                 : }
     816                 : 
     817                 : NS_IMETHODIMP
     818               0 : jsdObject::GetCreatorURL(nsACString &_rval)
     819                 : {
     820               0 :     _rval.Assign(JSD_GetObjectNewURL(mCx, mObject));
     821               0 :     return NS_OK;
     822                 : }
     823                 : 
     824                 : NS_IMETHODIMP
     825               0 : jsdObject::GetCreatorLine(PRUint32 *_rval)
     826                 : {
     827               0 :     *_rval = JSD_GetObjectNewLineNumber(mCx, mObject);
     828               0 :     return NS_OK;
     829                 : }
     830                 : 
     831                 : NS_IMETHODIMP
     832               0 : jsdObject::GetConstructorURL(nsACString &_rval)
     833                 : {
     834               0 :     _rval.Assign(JSD_GetObjectConstructorURL(mCx, mObject));
     835               0 :     return NS_OK;
     836                 : }
     837                 : 
     838                 : NS_IMETHODIMP
     839               0 : jsdObject::GetConstructorLine(PRUint32 *_rval)
     840                 : {
     841               0 :     *_rval = JSD_GetObjectConstructorLineNumber(mCx, mObject);
     842               0 :     return NS_OK;
     843                 : }
     844                 : 
     845                 : NS_IMETHODIMP
     846               0 : jsdObject::GetValue(jsdIValue **_rval)
     847                 : {
     848               0 :     JSDValue *jsdv = JSD_GetValueForObject (mCx, mObject);
     849                 :     
     850               0 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
     851               0 :     return NS_OK;
     852                 : }
     853                 : 
     854                 : /* Properties */
     855               0 : NS_IMPL_THREADSAFE_ISUPPORTS2(jsdProperty, jsdIProperty, jsdIEphemeral)
     856                 : 
     857               0 : jsdProperty::jsdProperty (JSDContext *aCx, JSDProperty *aProperty) :
     858               0 :     mCx(aCx), mProperty(aProperty)
     859                 : {
     860                 :     DEBUG_CREATE ("jsdProperty", gPropertyCount);
     861               0 :     mValid = (aCx && aProperty);
     862               0 :     mLiveListEntry.value = this;
     863               0 :     jsds_InsertEphemeral (&gLiveProperties, &mLiveListEntry);
     864               0 : }
     865                 : 
     866               0 : jsdProperty::~jsdProperty () 
     867                 : {
     868                 :     DEBUG_DESTROY ("jsdProperty", gPropertyCount);
     869               0 :     if (mValid)
     870               0 :         Invalidate();
     871               0 : }
     872                 : 
     873                 : NS_IMETHODIMP
     874               0 : jsdProperty::Invalidate()
     875                 : {
     876               0 :     ASSERT_VALID_EPHEMERAL;
     877               0 :     mValid = false;
     878               0 :     jsds_RemoveEphemeral (&gLiveProperties, &mLiveListEntry);
     879               0 :     JSD_DropProperty (mCx, mProperty);
     880               0 :     return NS_OK;
     881                 : }
     882                 : 
     883                 : void
     884             280 : jsdProperty::InvalidateAll()
     885                 : {
     886             280 :     if (gLiveProperties)
     887               0 :         jsds_InvalidateAllEphemerals (&gLiveProperties);
     888             280 : }
     889                 : 
     890                 : NS_IMETHODIMP
     891               0 : jsdProperty::GetJSDContext(JSDContext **_rval)
     892                 : {
     893               0 :     *_rval = mCx;
     894               0 :     return NS_OK;
     895                 : }
     896                 : 
     897                 : NS_IMETHODIMP
     898               0 : jsdProperty::GetJSDProperty(JSDProperty **_rval)
     899                 : {
     900               0 :     *_rval = mProperty;
     901               0 :     return NS_OK;
     902                 : }
     903                 : 
     904                 : NS_IMETHODIMP
     905               0 : jsdProperty::GetIsValid(bool *_rval)
     906                 : {
     907               0 :     *_rval = mValid;
     908               0 :     return NS_OK;
     909                 : }
     910                 : 
     911                 : NS_IMETHODIMP
     912               0 : jsdProperty::GetAlias(jsdIValue **_rval)
     913                 : {
     914               0 :     JSDValue *jsdv = JSD_GetPropertyValue (mCx, mProperty);
     915                 :     
     916               0 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
     917               0 :     return NS_OK;
     918                 : }
     919                 : 
     920                 : NS_IMETHODIMP
     921               0 : jsdProperty::GetFlags(PRUint32 *_rval)
     922                 : {
     923               0 :     *_rval = JSD_GetPropertyFlags (mCx, mProperty);
     924               0 :     return NS_OK;
     925                 : }
     926                 : 
     927                 : NS_IMETHODIMP
     928               0 : jsdProperty::GetName(jsdIValue **_rval)
     929                 : {
     930               0 :     JSDValue *jsdv = JSD_GetPropertyName (mCx, mProperty);
     931                 :     
     932               0 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
     933               0 :     return NS_OK;
     934                 : }
     935                 : 
     936                 : NS_IMETHODIMP
     937               0 : jsdProperty::GetValue(jsdIValue **_rval)
     938                 : {
     939               0 :     JSDValue *jsdv = JSD_GetPropertyValue (mCx, mProperty);
     940                 :     
     941               0 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
     942               0 :     return NS_OK;
     943                 : }
     944                 : 
     945                 : NS_IMETHODIMP
     946               0 : jsdProperty::GetVarArgSlot(PRUint32 *_rval)
     947                 : {
     948               0 :     *_rval = JSD_GetPropertyVarArgSlot (mCx, mProperty);
     949               0 :     return NS_OK;
     950                 : }
     951                 : 
     952                 : /* Scripts */
     953             148 : NS_IMPL_THREADSAFE_ISUPPORTS2(jsdScript, jsdIScript, jsdIEphemeral)
     954                 : 
     955                 : static NS_IMETHODIMP
     956               4 : AssignToJSString(nsACString *x, JSString *str)
     957                 : {
     958               4 :     if (!str) {
     959               0 :         x->SetLength(0);
     960               0 :         return NS_OK;
     961                 :     }
     962               4 :     size_t length = JS_GetStringEncodingLength(NULL, str);
     963               4 :     if (length == size_t(-1))
     964               0 :         return NS_ERROR_FAILURE;
     965               4 :     x->SetLength(PRUint32(length));
     966               4 :     if (x->Length() != PRUint32(length))
     967               0 :         return NS_ERROR_OUT_OF_MEMORY;
     968               4 :     JS_EncodeStringToBuffer(str, x->BeginWriting(), length);
     969               4 :     return NS_OK;
     970                 : }
     971                 : 
     972               6 : jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(false),
     973                 :                                                              mTag(0),
     974                 :                                                              mCx(aCx),
     975                 :                                                              mScript(aScript),
     976                 :                                                              mFileName(0), 
     977                 :                                                              mFunctionName(0),
     978                 :                                                              mBaseLineNumber(0),
     979                 :                                                              mLineExtent(0),
     980                 :                                                              mPPLineMap(0),
     981               6 :                                                              mFirstPC(0)
     982                 : {
     983                 :     DEBUG_CREATE ("jsdScript", gScriptCount);
     984                 : 
     985               6 :     if (mScript) {
     986                 :         /* copy the script's information now, so we have it later, when it
     987                 :          * gets destroyed. */
     988               6 :         JSD_LockScriptSubsystem(mCx);
     989              12 :         mFileName = new nsCString(JSD_GetScriptFilename(mCx, mScript));
     990               6 :         mFunctionName = new nsCString();
     991               6 :         if (mFunctionName) {
     992               6 :             JSString *str = JSD_GetScriptFunctionId(mCx, mScript);
     993               6 :             if (str)
     994               4 :                 AssignToJSString(mFunctionName, str);
     995                 :         }
     996               6 :         mBaseLineNumber = JSD_GetScriptBaseLineNumber(mCx, mScript);
     997               6 :         mLineExtent = JSD_GetScriptLineExtent(mCx, mScript);
     998               6 :         mFirstPC = JSD_GetClosestPC(mCx, mScript, 0);
     999               6 :         JSD_UnlockScriptSubsystem(mCx);
    1000                 :         
    1001               6 :         mValid = true;
    1002                 :     }
    1003               6 : }
    1004                 : 
    1005              12 : jsdScript::~jsdScript () 
    1006                 : {
    1007                 :     DEBUG_DESTROY ("jsdScript", gScriptCount);
    1008               6 :     delete mFileName;
    1009               6 :     delete mFunctionName;
    1010                 : 
    1011               6 :     if (mPPLineMap)
    1012               0 :         PR_Free(mPPLineMap);
    1013                 : 
    1014                 :     /* Invalidate() needs to be called to release an owning reference to
    1015                 :      * ourselves, so if we got here without being invalidated, something
    1016                 :      * has gone wrong with our ref count. */
    1017               6 :     NS_ASSERTION (!mValid, "Script destroyed without being invalidated.");
    1018              24 : }
    1019                 : 
    1020                 : /*
    1021                 :  * This method populates a line <-> pc map for a pretty printed version of this
    1022                 :  * script.  It does this by decompiling, and then recompiling the script.  The
    1023                 :  * resulting script is scanned for the line map, and then left as GC fodder.
    1024                 :  */
    1025                 : PCMapEntry *
    1026               0 : jsdScript::CreatePPLineMap()
    1027                 : {    
    1028               0 :     JSContext  *cx  = JSD_GetDefaultJSContext (mCx);
    1029               0 :     JSAutoRequest ar(cx);
    1030               0 :     JSObject   *obj = JS_NewObject(cx, NULL, NULL, NULL);
    1031               0 :     JSFunction *fun = JSD_GetJSFunction (mCx, mScript);
    1032                 :     JSScript   *script; /* In JSD compartment */
    1033                 :     PRUint32    baseLine;
    1034                 :     JSString   *jsstr;
    1035                 :     size_t      length;
    1036                 :     const jschar *chars;
    1037                 :     
    1038               0 :     if (fun) {
    1039                 :         unsigned nargs;
    1040                 : 
    1041                 :         {
    1042               0 :             JSAutoEnterCompartment ac;
    1043               0 :             if (!ac.enter(cx, JS_GetFunctionObject(fun)))
    1044               0 :                 return nsnull;
    1045                 : 
    1046               0 :             nargs = JS_GetFunctionArgumentCount(cx, fun);
    1047               0 :             if (nargs > 12)
    1048               0 :                 return nsnull;
    1049               0 :             jsstr = JS_DecompileFunctionBody (cx, fun, 4);
    1050               0 :             if (!jsstr)
    1051               0 :                 return nsnull;
    1052                 : 
    1053               0 :             if (!(chars = JS_GetStringCharsAndLength(cx, jsstr, &length)))
    1054               0 :                 return nsnull;
    1055                 :         }
    1056                 : 
    1057               0 :         JS::Anchor<JSString *> kungFuDeathGrip(jsstr);
    1058                 :         const char *argnames[] = {"arg1", "arg2", "arg3", "arg4", 
    1059                 :                                   "arg5", "arg6", "arg7", "arg8",
    1060               0 :                                   "arg9", "arg10", "arg11", "arg12" };
    1061                 :         fun = JS_CompileUCFunction (cx, obj, "ppfun", nargs, argnames, chars,
    1062               0 :                                     length, "x-jsd:ppbuffer?type=function", 3);
    1063               0 :         if (!fun || !(script = JS_GetFunctionScript(cx, fun)))
    1064               0 :             return nsnull;
    1065               0 :         baseLine = 3;
    1066                 :     } else {
    1067               0 :         script = JSD_GetJSScript(mCx, mScript);
    1068                 :         JSString *jsstr;
    1069                 : 
    1070                 :         {
    1071               0 :             JS::AutoEnterScriptCompartment ac;
    1072               0 :             if (!ac.enter(cx, script))
    1073               0 :                 return nsnull;
    1074                 : 
    1075               0 :             jsstr = JS_DecompileScript (cx, script, "ppscript", 4);
    1076               0 :             if (!jsstr)
    1077               0 :                 return nsnull;
    1078                 : 
    1079               0 :             if (!(chars = JS_GetStringCharsAndLength(cx, jsstr, &length)))
    1080               0 :                 return nsnull;
    1081                 :         }
    1082                 : 
    1083               0 :         JS::Anchor<JSString *> kungFuDeathGrip(jsstr);
    1084               0 :         script = JS_CompileUCScript (cx, obj, chars, length, "x-jsd:ppbuffer?type=script", 1);
    1085               0 :         if (!script)
    1086               0 :             return nsnull;
    1087               0 :         baseLine = 1;
    1088                 :     }
    1089                 : 
    1090               0 :     PRUint32 scriptExtent = JS_GetScriptLineExtent (cx, script);
    1091               0 :     jsbytecode* firstPC = JS_LineNumberToPC (cx, script, 0);
    1092                 :     /* allocate worst case size of map (number of lines in script + 1
    1093                 :      * for our 0 record), we'll shrink it with a realloc later. */
    1094                 :     PCMapEntry *lineMap =
    1095                 :         static_cast<PCMapEntry *>
    1096               0 :                    (PR_Malloc((scriptExtent + 1) * sizeof (PCMapEntry)));
    1097               0 :     PRUint32 lineMapSize = 0;
    1098                 : 
    1099               0 :     if (lineMap) {
    1100               0 :         for (PRUint32 line = baseLine; line < scriptExtent + baseLine; ++line) {
    1101               0 :             jsbytecode* pc = JS_LineNumberToPC (cx, script, line);
    1102               0 :             if (line == JS_PCToLineNumber (cx, script, pc)) {
    1103               0 :                 lineMap[lineMapSize].line = line;
    1104               0 :                 lineMap[lineMapSize].pc = pc - firstPC;
    1105               0 :                 ++lineMapSize;
    1106                 :             }
    1107                 :         }
    1108               0 :         if (scriptExtent != lineMapSize) {
    1109                 :             lineMap =
    1110                 :                 static_cast<PCMapEntry *>
    1111                 :                            (PR_Realloc(mPPLineMap = lineMap,
    1112               0 :                                        lineMapSize * sizeof(PCMapEntry)));
    1113               0 :             if (!lineMap) {
    1114               0 :                 PR_Free(mPPLineMap);
    1115               0 :                 lineMapSize = 0;
    1116                 :             }
    1117                 :         }
    1118                 :     }
    1119                 : 
    1120               0 :     mPCMapSize = lineMapSize;
    1121               0 :     return mPPLineMap = lineMap;
    1122                 : }
    1123                 : 
    1124                 : PRUint32
    1125               0 : jsdScript::PPPcToLine (PRUint32 aPC)
    1126                 : {
    1127               0 :     if (!mPPLineMap && !CreatePPLineMap())
    1128               0 :         return 0;
    1129                 :     PRUint32 i;
    1130               0 :     for (i = 1; i < mPCMapSize; ++i) {
    1131               0 :         if (mPPLineMap[i].pc > aPC)
    1132               0 :             return mPPLineMap[i - 1].line;            
    1133                 :     }
    1134                 : 
    1135               0 :     return mPPLineMap[mPCMapSize - 1].line;
    1136                 : }
    1137                 : 
    1138                 : PRUint32
    1139               0 : jsdScript::PPLineToPc (PRUint32 aLine)
    1140                 : {
    1141               0 :     if (!mPPLineMap && !CreatePPLineMap())
    1142               0 :         return 0;
    1143                 :     PRUint32 i;
    1144               0 :     for (i = 1; i < mPCMapSize; ++i) {
    1145               0 :         if (mPPLineMap[i].line > aLine)
    1146               0 :             return mPPLineMap[i - 1].pc;
    1147                 :     }
    1148                 : 
    1149               0 :     return mPPLineMap[mPCMapSize - 1].pc;
    1150                 : }
    1151                 : 
    1152                 : NS_IMETHODIMP
    1153               0 : jsdScript::GetJSDContext(JSDContext **_rval)
    1154                 : {
    1155               0 :     ASSERT_VALID_EPHEMERAL;
    1156               0 :     *_rval = mCx;
    1157               0 :     return NS_OK;
    1158                 : }
    1159                 : 
    1160                 : NS_IMETHODIMP
    1161               0 : jsdScript::GetJSDScript(JSDScript **_rval)
    1162                 : {
    1163               0 :     ASSERT_VALID_EPHEMERAL;
    1164               0 :     *_rval = mScript;
    1165               0 :     return NS_OK;
    1166                 : }
    1167                 : 
    1168                 : NS_IMETHODIMP
    1169               0 : jsdScript::GetVersion (PRInt32 *_rval)
    1170                 : {
    1171               0 :     ASSERT_VALID_EPHEMERAL;
    1172               0 :     JSContext *cx = JSD_GetDefaultJSContext (mCx);
    1173               0 :     JSScript *script = JSD_GetJSScript(mCx, mScript);
    1174               0 :     JS::AutoEnterScriptCompartment ac;
    1175               0 :     if (!ac.enter(cx, script))
    1176               0 :         return NS_ERROR_FAILURE;
    1177               0 :     *_rval = static_cast<PRInt32>(JS_GetScriptVersion(cx, script));
    1178               0 :     return NS_OK;
    1179                 : }
    1180                 : 
    1181                 : NS_IMETHODIMP
    1182               0 : jsdScript::GetTag(PRUint32 *_rval)
    1183                 : {
    1184               0 :     if (!mTag)
    1185               0 :         mTag = ++jsdScript::LastTag;
    1186                 :     
    1187               0 :     *_rval = mTag;
    1188               0 :     return NS_OK;
    1189                 : }
    1190                 : 
    1191                 : NS_IMETHODIMP
    1192               6 : jsdScript::Invalidate()
    1193                 : {
    1194               6 :     ASSERT_VALID_EPHEMERAL;
    1195               6 :     mValid = false;
    1196                 :     
    1197                 :     /* release the addref we do in FromPtr */
    1198                 :     jsdIScript *script = static_cast<jsdIScript *>
    1199               6 :                                     (JSD_GetScriptPrivate(mScript));
    1200               6 :     NS_ASSERTION (script == this, "That's not my script!");
    1201               6 :     NS_RELEASE(script);
    1202               6 :     JSD_SetScriptPrivate(mScript, NULL);
    1203               6 :     return NS_OK;
    1204                 : }
    1205                 : 
    1206                 : void
    1207             280 : jsdScript::InvalidateAll ()
    1208                 : {
    1209                 :     JSDContext *cx;
    1210             280 :     if (NS_FAILED(gJsds->GetJSDContext (&cx)))
    1211               0 :         return;
    1212                 : 
    1213                 :     JSDScript *script;
    1214             280 :     JSDScript *iter = NULL;
    1215                 :     
    1216             280 :     JSD_LockScriptSubsystem(cx);
    1217          151907 :     while((script = JSD_IterateScripts(cx, &iter)) != NULL) {
    1218                 :         nsCOMPtr<jsdIScript> jsdis = 
    1219          302694 :             static_cast<jsdIScript *>(JSD_GetScriptPrivate(script));
    1220          151347 :         if (jsdis)
    1221               4 :             jsdis->Invalidate();
    1222                 :     }
    1223             280 :     JSD_UnlockScriptSubsystem(cx);
    1224                 : }
    1225                 : 
    1226                 : NS_IMETHODIMP
    1227               0 : jsdScript::GetIsValid(bool *_rval)
    1228                 : {
    1229               0 :     *_rval = mValid;
    1230               0 :     return NS_OK;
    1231                 : }
    1232                 : 
    1233                 : NS_IMETHODIMP
    1234               0 : jsdScript::SetFlags(PRUint32 flags)
    1235                 : {
    1236               0 :     ASSERT_VALID_EPHEMERAL;
    1237               0 :     JSD_SetScriptFlags(mCx, mScript, flags);
    1238               0 :     return NS_OK;
    1239                 : }
    1240                 : 
    1241                 : NS_IMETHODIMP
    1242               0 : jsdScript::GetFlags(PRUint32 *_rval)
    1243                 : {
    1244               0 :     ASSERT_VALID_EPHEMERAL;
    1245               0 :     *_rval = JSD_GetScriptFlags(mCx, mScript);
    1246               0 :     return NS_OK;
    1247                 : }
    1248                 : 
    1249                 : NS_IMETHODIMP
    1250               0 : jsdScript::GetFileName(nsACString &_rval)
    1251                 : {
    1252               0 :     _rval.Assign(*mFileName);
    1253               0 :     return NS_OK;
    1254                 : }
    1255                 : 
    1256                 : NS_IMETHODIMP
    1257               0 : jsdScript::GetFunctionName(nsACString &_rval)
    1258                 : {
    1259               0 :     _rval.Assign(*mFunctionName);
    1260               0 :     return NS_OK;
    1261                 : }
    1262                 : 
    1263                 : NS_IMETHODIMP
    1264               0 : jsdScript::GetParameterNames(PRUint32* count, PRUnichar*** paramNames)
    1265                 : {
    1266               0 :     ASSERT_VALID_EPHEMERAL;
    1267               0 :     JSContext *cx = JSD_GetDefaultJSContext (mCx);
    1268               0 :     if (!cx) {
    1269               0 :         NS_WARNING("No default context !?");
    1270               0 :         return NS_ERROR_FAILURE;
    1271                 :     }
    1272               0 :     JSFunction *fun = JSD_GetJSFunction (mCx, mScript);
    1273               0 :     if (!fun) {
    1274               0 :         *count = 0;
    1275               0 :         *paramNames = nsnull;
    1276               0 :         return NS_OK;
    1277                 :     }
    1278                 : 
    1279               0 :     JSAutoRequest ar(cx);
    1280               0 :     JSAutoEnterCompartment ac;
    1281               0 :     if (!ac.enter(cx, JS_GetFunctionObject(fun)))
    1282               0 :         return NS_ERROR_FAILURE;
    1283                 : 
    1284                 :     unsigned nargs;
    1285               0 :     if (!JS_FunctionHasLocalNames(cx, fun) ||
    1286                 :         (nargs = JS_GetFunctionArgumentCount(cx, fun)) == 0) {
    1287               0 :         *count = 0;
    1288               0 :         *paramNames = nsnull;
    1289               0 :         return NS_OK;
    1290                 :     }
    1291                 : 
    1292                 :     PRUnichar **ret =
    1293               0 :         static_cast<PRUnichar**>(NS_Alloc(nargs * sizeof(PRUnichar*)));
    1294               0 :     if (!ret)
    1295               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1296                 : 
    1297                 :     void *mark;
    1298               0 :     uintptr_t *names = JS_GetFunctionLocalNameArray(cx, fun, &mark);
    1299               0 :     if (!names) {
    1300               0 :         NS_Free(ret);
    1301               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1302                 :     }
    1303                 : 
    1304               0 :     nsresult rv = NS_OK;
    1305               0 :     for (unsigned i = 0; i < nargs; ++i) {
    1306               0 :         JSAtom *atom = JS_LocalNameToAtom(names[i]);
    1307               0 :         if (!atom) {
    1308               0 :             ret[i] = 0;
    1309                 :         } else {
    1310               0 :             JSString *str = JS_AtomKey(atom);
    1311               0 :             ret[i] = NS_strndup(JS_GetInternedStringChars(str), JS_GetStringLength(str));
    1312               0 :             if (!ret[i]) {
    1313               0 :                 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, ret);
    1314               0 :                 rv = NS_ERROR_OUT_OF_MEMORY;
    1315               0 :                 break;
    1316                 :             }
    1317                 :         }
    1318                 :     }
    1319               0 :     JS_ReleaseFunctionLocalNameArray(cx, mark);
    1320               0 :     if (NS_FAILED(rv))
    1321               0 :         return rv;
    1322               0 :     *count = nargs;
    1323               0 :     *paramNames = ret;
    1324               0 :     return NS_OK;
    1325                 : }
    1326                 : 
    1327                 : NS_IMETHODIMP
    1328               0 : jsdScript::GetFunctionObject(jsdIValue **_rval)
    1329                 : {
    1330               0 :     JSFunction *fun = JSD_GetJSFunction(mCx, mScript);
    1331               0 :     if (!fun)
    1332               0 :         return NS_ERROR_NOT_AVAILABLE;
    1333                 :     
    1334               0 :     JSObject *obj = JS_GetFunctionObject(fun);
    1335               0 :     if (!obj)
    1336               0 :         return NS_ERROR_FAILURE;
    1337                 : 
    1338                 :     JSDContext *cx;
    1339               0 :     if (NS_FAILED(gJsds->GetJSDContext (&cx)))
    1340               0 :         return NS_ERROR_NOT_INITIALIZED;
    1341                 : 
    1342               0 :     JSDValue *jsdv = JSD_NewValue(cx, OBJECT_TO_JSVAL(obj));
    1343               0 :     if (!jsdv)
    1344               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1345                 : 
    1346               0 :     *_rval = jsdValue::FromPtr(cx, jsdv);
    1347               0 :     if (!*_rval) {
    1348               0 :         JSD_DropValue(cx, jsdv);
    1349               0 :         return NS_ERROR_OUT_OF_MEMORY;
    1350                 :     }
    1351                 : 
    1352               0 :     return NS_OK;
    1353                 : }
    1354                 : 
    1355                 : NS_IMETHODIMP
    1356               0 : jsdScript::GetFunctionSource(nsAString & aFunctionSource)
    1357                 : {
    1358               0 :     ASSERT_VALID_EPHEMERAL;
    1359               0 :     JSContext *cx = JSD_GetDefaultJSContext (mCx);
    1360               0 :     if (!cx) {
    1361               0 :         NS_WARNING("No default context !?");
    1362               0 :         return NS_ERROR_FAILURE;
    1363                 :     }
    1364               0 :     JSFunction *fun = JSD_GetJSFunction (mCx, mScript);
    1365                 : 
    1366               0 :     JSAutoRequest ar(cx);
    1367                 : 
    1368                 :     JSString *jsstr;
    1369               0 :     JSAutoEnterCompartment ac;
    1370               0 :     JS::AutoEnterScriptCompartment asc;
    1371               0 :     if (fun) {
    1372               0 :         if (!ac.enter(cx, JS_GetFunctionObject(fun)))
    1373               0 :             return NS_ERROR_FAILURE;
    1374               0 :         jsstr = JS_DecompileFunction (cx, fun, 4);
    1375                 :     } else {
    1376               0 :         JSScript *script = JSD_GetJSScript (mCx, mScript);
    1377               0 :         if (!asc.enter(cx, script))
    1378               0 :             return NS_ERROR_FAILURE;
    1379               0 :         jsstr = JS_DecompileScript (cx, script, "ppscript", 4);
    1380                 :     }
    1381               0 :     if (!jsstr)
    1382               0 :         return NS_ERROR_FAILURE;
    1383                 : 
    1384                 :     size_t length;
    1385               0 :     const jschar *chars = JS_GetStringCharsZAndLength(cx, jsstr, &length);
    1386               0 :     if (!chars)
    1387               0 :         return NS_ERROR_FAILURE;
    1388                 : 
    1389               0 :     aFunctionSource = nsDependentString(chars, length);
    1390               0 :     return NS_OK;
    1391                 : }
    1392                 : 
    1393                 : NS_IMETHODIMP
    1394               0 : jsdScript::GetBaseLineNumber(PRUint32 *_rval)
    1395                 : {
    1396               0 :     *_rval = mBaseLineNumber;
    1397               0 :     return NS_OK;
    1398                 : }
    1399                 : 
    1400                 : NS_IMETHODIMP
    1401               0 : jsdScript::GetLineExtent(PRUint32 *_rval)
    1402                 : {
    1403               0 :     *_rval = mLineExtent;
    1404               0 :     return NS_OK;
    1405                 : }
    1406                 : 
    1407                 : NS_IMETHODIMP
    1408               0 : jsdScript::GetCallCount(PRUint32 *_rval)
    1409                 : {
    1410               0 :     ASSERT_VALID_EPHEMERAL;
    1411               0 :     *_rval = JSD_GetScriptCallCount (mCx, mScript);
    1412               0 :     return NS_OK;
    1413                 : }
    1414                 : 
    1415                 : NS_IMETHODIMP
    1416               0 : jsdScript::GetMaxRecurseDepth(PRUint32 *_rval)
    1417                 : {
    1418               0 :     ASSERT_VALID_EPHEMERAL;
    1419               0 :     *_rval = JSD_GetScriptMaxRecurseDepth (mCx, mScript);
    1420               0 :     return NS_OK;
    1421                 : }
    1422                 : 
    1423                 : NS_IMETHODIMP
    1424               0 : jsdScript::GetMinExecutionTime(double *_rval)
    1425                 : {
    1426               0 :     ASSERT_VALID_EPHEMERAL;
    1427               0 :     *_rval = JSD_GetScriptMinExecutionTime (mCx, mScript);
    1428               0 :     return NS_OK;
    1429                 : }
    1430                 : 
    1431                 : NS_IMETHODIMP
    1432               0 : jsdScript::GetMaxExecutionTime(double *_rval)
    1433                 : {
    1434               0 :     ASSERT_VALID_EPHEMERAL;
    1435               0 :     *_rval = JSD_GetScriptMaxExecutionTime (mCx, mScript);
    1436               0 :     return NS_OK;
    1437                 : }
    1438                 : 
    1439                 : NS_IMETHODIMP
    1440               0 : jsdScript::GetTotalExecutionTime(double *_rval)
    1441                 : {
    1442               0 :     ASSERT_VALID_EPHEMERAL;
    1443               0 :     *_rval = JSD_GetScriptTotalExecutionTime (mCx, mScript);
    1444               0 :     return NS_OK;
    1445                 : }
    1446                 : 
    1447                 : NS_IMETHODIMP
    1448               0 : jsdScript::GetMinOwnExecutionTime(double *_rval)
    1449                 : {
    1450               0 :     ASSERT_VALID_EPHEMERAL;
    1451               0 :     *_rval = JSD_GetScriptMinOwnExecutionTime (mCx, mScript);
    1452               0 :     return NS_OK;
    1453                 : }
    1454                 : 
    1455                 : NS_IMETHODIMP
    1456               0 : jsdScript::GetMaxOwnExecutionTime(double *_rval)
    1457                 : {
    1458               0 :     ASSERT_VALID_EPHEMERAL;
    1459               0 :     *_rval = JSD_GetScriptMaxOwnExecutionTime (mCx, mScript);
    1460               0 :     return NS_OK;
    1461                 : }
    1462                 : 
    1463                 : NS_IMETHODIMP
    1464               0 : jsdScript::GetTotalOwnExecutionTime(double *_rval)
    1465                 : {
    1466               0 :     ASSERT_VALID_EPHEMERAL;
    1467               0 :     *_rval = JSD_GetScriptTotalOwnExecutionTime (mCx, mScript);
    1468               0 :     return NS_OK;
    1469                 : }
    1470                 : 
    1471                 : NS_IMETHODIMP
    1472               0 : jsdScript::ClearProfileData()
    1473                 : {
    1474               0 :     ASSERT_VALID_EPHEMERAL;
    1475               0 :     JSD_ClearScriptProfileData(mCx, mScript);
    1476               0 :     return NS_OK;
    1477                 : }
    1478                 : 
    1479                 : NS_IMETHODIMP
    1480               0 : jsdScript::PcToLine(PRUint32 aPC, PRUint32 aPcmap, PRUint32 *_rval)
    1481                 : {
    1482               0 :     ASSERT_VALID_EPHEMERAL;
    1483               0 :     if (aPcmap == PCMAP_SOURCETEXT) {
    1484               0 :         *_rval = JSD_GetClosestLine (mCx, mScript, mFirstPC + aPC);
    1485               0 :     } else if (aPcmap == PCMAP_PRETTYPRINT) {
    1486               0 :         *_rval = PPPcToLine(aPC);
    1487                 :     } else {
    1488               0 :         return NS_ERROR_INVALID_ARG;
    1489                 :     }
    1490                 :     
    1491               0 :     return NS_OK;
    1492                 : }
    1493                 : 
    1494                 : NS_IMETHODIMP
    1495               0 : jsdScript::LineToPc(PRUint32 aLine, PRUint32 aPcmap, PRUint32 *_rval)
    1496                 : {
    1497               0 :     ASSERT_VALID_EPHEMERAL;
    1498               0 :     if (aPcmap == PCMAP_SOURCETEXT) {
    1499               0 :         uintptr_t pc = JSD_GetClosestPC (mCx, mScript, aLine);
    1500               0 :         *_rval = pc - mFirstPC;
    1501               0 :     } else if (aPcmap == PCMAP_PRETTYPRINT) {
    1502               0 :         *_rval = PPLineToPc(aLine);
    1503                 :     } else {
    1504               0 :         return NS_ERROR_INVALID_ARG;
    1505                 :     }
    1506                 : 
    1507               0 :     return NS_OK;
    1508                 : }
    1509                 : 
    1510                 : NS_IMETHODIMP
    1511               0 : jsdScript::EnableSingleStepInterrupts(bool enable)
    1512                 : {
    1513               0 :     ASSERT_VALID_EPHEMERAL;
    1514                 : 
    1515                 :     /* Must have set interrupt hook before enabling */
    1516               0 :     if (enable && !jsdService::GetService()->CheckInterruptHook())
    1517               0 :         return NS_ERROR_NOT_INITIALIZED;
    1518                 : 
    1519               0 :     return (JSD_EnableSingleStepInterrupts(mCx, mScript, enable) ? NS_OK : NS_ERROR_FAILURE);
    1520                 : }
    1521                 : 
    1522                 : NS_IMETHODIMP
    1523               0 : jsdScript::GetExecutableLines(PRUint32 aPcmap, PRUint32 aStartLine, PRUint32 aMaxLines,
    1524                 :                               PRUint32* aCount, PRUint32** aExecutableLines)
    1525                 : {
    1526               0 :     ASSERT_VALID_EPHEMERAL;
    1527               0 :     if (aPcmap == PCMAP_SOURCETEXT) {
    1528               0 :         uintptr_t start = JSD_GetClosestPC(mCx, mScript, 0);
    1529               0 :         unsigned lastLine = JSD_GetScriptBaseLineNumber(mCx, mScript)
    1530               0 :                        + JSD_GetScriptLineExtent(mCx, mScript) - 1;
    1531               0 :         uintptr_t end = JSD_GetClosestPC(mCx, mScript, lastLine + 1);
    1532                 : 
    1533               0 :         *aExecutableLines = static_cast<PRUint32*>(NS_Alloc((end - start + 1) * sizeof(PRUint32)));
    1534               0 :         if (!JSD_GetLinePCs(mCx, mScript, aStartLine, aMaxLines, aCount, aExecutableLines, NULL))
    1535               0 :             return NS_ERROR_OUT_OF_MEMORY;
    1536                 :         
    1537               0 :         return NS_OK;
    1538                 :     }
    1539                 : 
    1540               0 :     if (aPcmap == PCMAP_PRETTYPRINT) {
    1541               0 :         if (!mPPLineMap) {
    1542               0 :             if (!CreatePPLineMap())
    1543               0 :                 return NS_ERROR_OUT_OF_MEMORY;
    1544                 :         }
    1545                 : 
    1546               0 :         nsTArray<PRUint32> lines;
    1547                 :         PRUint32 i;
    1548                 : 
    1549               0 :         for (i = 0; i < mPCMapSize; ++i) {
    1550               0 :             if (mPPLineMap[i].line >= aStartLine)
    1551               0 :                 break;
    1552                 :         }
    1553                 : 
    1554               0 :         for (; i < mPCMapSize && lines.Length() < aMaxLines; ++i) {
    1555               0 :             lines.AppendElement(mPPLineMap[i].line);
    1556                 :         }
    1557                 : 
    1558               0 :         if (aCount)
    1559               0 :             *aCount = lines.Length();
    1560                 : 
    1561               0 :         *aExecutableLines = static_cast<PRUint32*>(NS_Alloc(lines.Length() * sizeof(PRUint32)));
    1562               0 :         if (!*aExecutableLines)
    1563               0 :             return NS_ERROR_OUT_OF_MEMORY;
    1564                 : 
    1565               0 :         for (i = 0; i < lines.Length(); ++i)
    1566               0 :             (*aExecutableLines)[i] = lines[i];
    1567                 : 
    1568               0 :         return NS_OK;
    1569                 :     }
    1570                 : 
    1571               0 :     return NS_ERROR_INVALID_ARG;
    1572                 : }
    1573                 : 
    1574                 : NS_IMETHODIMP
    1575               0 : jsdScript::IsLineExecutable(PRUint32 aLine, PRUint32 aPcmap, bool *_rval)
    1576                 : {
    1577               0 :     ASSERT_VALID_EPHEMERAL;
    1578               0 :     if (aPcmap == PCMAP_SOURCETEXT) {    
    1579               0 :         uintptr_t pc = JSD_GetClosestPC (mCx, mScript, aLine);
    1580               0 :         *_rval = (aLine == JSD_GetClosestLine (mCx, mScript, pc));
    1581               0 :     } else if (aPcmap == PCMAP_PRETTYPRINT) {
    1582               0 :         if (!mPPLineMap && !CreatePPLineMap())
    1583               0 :             return NS_ERROR_OUT_OF_MEMORY;
    1584               0 :         *_rval = false;
    1585               0 :         for (PRUint32 i = 0; i < mPCMapSize; ++i) {
    1586               0 :             if (mPPLineMap[i].line >= aLine) {
    1587               0 :                 *_rval = (mPPLineMap[i].line == aLine);
    1588               0 :                 break;
    1589                 :             }
    1590                 :         }
    1591                 :     } else {
    1592               0 :         return NS_ERROR_INVALID_ARG;
    1593                 :     }
    1594                 :     
    1595               0 :     return NS_OK;
    1596                 : }
    1597                 : 
    1598                 : NS_IMETHODIMP
    1599               6 : jsdScript::SetBreakpoint(PRUint32 aPC)
    1600                 : {
    1601               6 :     ASSERT_VALID_EPHEMERAL;
    1602               6 :     uintptr_t pc = mFirstPC + aPC;
    1603               6 :     JSD_SetExecutionHook (mCx, mScript, pc, jsds_ExecutionHookProc, NULL);
    1604               6 :     return NS_OK;
    1605                 : }
    1606                 : 
    1607                 : NS_IMETHODIMP
    1608               0 : jsdScript::ClearBreakpoint(PRUint32 aPC)
    1609                 : {
    1610               0 :     ASSERT_VALID_EPHEMERAL;    
    1611               0 :     uintptr_t pc = mFirstPC + aPC;
    1612               0 :     JSD_ClearExecutionHook (mCx, mScript, pc);
    1613               0 :     return NS_OK;
    1614                 : }
    1615                 : 
    1616                 : NS_IMETHODIMP
    1617               0 : jsdScript::ClearAllBreakpoints()
    1618                 : {
    1619               0 :     ASSERT_VALID_EPHEMERAL;
    1620               0 :     JSD_LockScriptSubsystem(mCx);
    1621               0 :     JSD_ClearAllExecutionHooksForScript (mCx, mScript);
    1622               0 :     JSD_UnlockScriptSubsystem(mCx);
    1623               0 :     return NS_OK;
    1624                 : }
    1625                 : 
    1626                 : /* Contexts */
    1627               0 : NS_IMPL_THREADSAFE_ISUPPORTS2(jsdContext, jsdIContext, jsdIEphemeral)
    1628                 : 
    1629                 : jsdIContext *
    1630               0 : jsdContext::FromPtr (JSDContext *aJSDCx, JSContext *aJSCx)
    1631                 : {
    1632               0 :     if (!aJSDCx || !aJSCx)
    1633               0 :         return nsnull;
    1634                 : 
    1635               0 :     nsCOMPtr<jsdIContext> jsdicx;
    1636                 :     nsCOMPtr<jsdIEphemeral> eph = 
    1637               0 :         jsds_FindEphemeral (&gLiveContexts, static_cast<void *>(aJSCx));
    1638               0 :     if (eph)
    1639                 :     {
    1640               0 :         jsdicx = do_QueryInterface(eph);
    1641                 :     }
    1642                 :     else
    1643                 :     {
    1644               0 :         nsCOMPtr<nsISupports> iscx;
    1645               0 :         if (JS_GetOptions(aJSCx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)
    1646               0 :             iscx = static_cast<nsISupports *>(JS_GetContextPrivate(aJSCx));
    1647               0 :         jsdicx = new jsdContext (aJSDCx, aJSCx, iscx);
    1648                 :     }
    1649                 : 
    1650               0 :     jsdIContext *ctx = nsnull;
    1651               0 :     jsdicx.swap(ctx);
    1652               0 :     return ctx;
    1653                 : }
    1654                 : 
    1655               0 : jsdContext::jsdContext (JSDContext *aJSDCx, JSContext *aJSCx,
    1656                 :                         nsISupports *aISCx) : mValid(true), mTag(0),
    1657                 :                                               mJSDCx(aJSDCx),
    1658               0 :                                               mJSCx(aJSCx), mISCx(aISCx)
    1659                 : {
    1660                 :     DEBUG_CREATE ("jsdContext", gContextCount);
    1661               0 :     mLiveListEntry.value = this;
    1662               0 :     mLiveListEntry.key   = static_cast<void *>(aJSCx);
    1663               0 :     jsds_InsertEphemeral (&gLiveContexts, &mLiveListEntry);
    1664               0 : }
    1665                 : 
    1666               0 : jsdContext::~jsdContext() 
    1667                 : {
    1668                 :     DEBUG_DESTROY ("jsdContext", gContextCount);
    1669               0 :     if (mValid)
    1670                 :     {
    1671                 :         /* call Invalidate() to take ourselves out of the live list */
    1672               0 :         Invalidate();
    1673                 :     }
    1674               0 : }
    1675                 : 
    1676                 : NS_IMETHODIMP
    1677               0 : jsdContext::GetIsValid(bool *_rval)
    1678                 : {
    1679               0 :     *_rval = mValid;
    1680               0 :     return NS_OK;
    1681                 : }
    1682                 : 
    1683                 : NS_IMETHODIMP
    1684               0 : jsdContext::Invalidate()
    1685                 : {
    1686               0 :     ASSERT_VALID_EPHEMERAL;
    1687               0 :     mValid = false;
    1688               0 :     jsds_RemoveEphemeral (&gLiveContexts, &mLiveListEntry);
    1689               0 :     return NS_OK;
    1690                 : }
    1691                 : 
    1692                 : void
    1693             280 : jsdContext::InvalidateAll()
    1694                 : {
    1695             280 :     if (gLiveContexts)
    1696               0 :         jsds_InvalidateAllEphemerals (&gLiveContexts);
    1697             280 : }
    1698                 : 
    1699                 : NS_IMETHODIMP
    1700               0 : jsdContext::GetJSContext(JSContext **_rval)
    1701                 : {
    1702               0 :     ASSERT_VALID_EPHEMERAL;
    1703               0 :     *_rval = mJSCx;
    1704               0 :     return NS_OK;
    1705                 : }
    1706                 : 
    1707                 : NS_IMETHODIMP
    1708               0 : jsdContext::GetOptions(PRUint32 *_rval)
    1709                 : {
    1710               0 :     ASSERT_VALID_EPHEMERAL;
    1711               0 :     *_rval = JS_GetOptions(mJSCx);
    1712               0 :     return NS_OK;
    1713                 : }
    1714                 : 
    1715                 : NS_IMETHODIMP
    1716               0 : jsdContext::SetOptions(PRUint32 options)
    1717                 : {
    1718               0 :     ASSERT_VALID_EPHEMERAL;
    1719               0 :     PRUint32 lastOptions = JS_GetOptions(mJSCx);
    1720                 : 
    1721                 :     /* don't let users change this option, they'd just be shooting themselves
    1722                 :      * in the foot. */
    1723               0 :     if ((options ^ lastOptions) & JSOPTION_PRIVATE_IS_NSISUPPORTS)
    1724               0 :         return NS_ERROR_ILLEGAL_VALUE;
    1725                 : 
    1726               0 :     JS_SetOptions(mJSCx, options);
    1727               0 :     return NS_OK;
    1728                 : }
    1729                 : 
    1730                 : NS_IMETHODIMP
    1731               0 : jsdContext::GetPrivateData(nsISupports **_rval)
    1732                 : {
    1733               0 :     ASSERT_VALID_EPHEMERAL;
    1734               0 :     PRUint32 options = JS_GetOptions(mJSCx);
    1735               0 :     if (options & JSOPTION_PRIVATE_IS_NSISUPPORTS)
    1736                 :     {
    1737               0 :         *_rval = static_cast<nsISupports*>(JS_GetContextPrivate(mJSCx));
    1738               0 :         NS_IF_ADDREF(*_rval);
    1739                 :     }
    1740                 :     else
    1741                 :     {
    1742               0 :         *_rval = nsnull;
    1743                 :     }
    1744                 :     
    1745               0 :     return NS_OK;
    1746                 : }
    1747                 :         
    1748                 : NS_IMETHODIMP
    1749               0 : jsdContext::GetWrappedContext(nsISupports **_rval)
    1750                 : {
    1751               0 :     ASSERT_VALID_EPHEMERAL;
    1752               0 :     NS_IF_ADDREF(*_rval = mISCx);
    1753               0 :     return NS_OK;
    1754                 : }
    1755                 : 
    1756                 : NS_IMETHODIMP
    1757               0 : jsdContext::GetTag(PRUint32 *_rval)
    1758                 : {
    1759               0 :     ASSERT_VALID_EPHEMERAL;
    1760               0 :     if (!mTag)
    1761               0 :         mTag = ++jsdContext::LastTag;
    1762                 :     
    1763               0 :     *_rval = mTag;
    1764               0 :     return NS_OK;
    1765                 : }
    1766                 : 
    1767                 : NS_IMETHODIMP
    1768               0 : jsdContext::GetVersion (PRInt32 *_rval)
    1769                 : {
    1770               0 :     ASSERT_VALID_EPHEMERAL;
    1771               0 :     *_rval = static_cast<PRInt32>(JS_GetVersion(mJSCx));
    1772               0 :     return NS_OK;
    1773                 : }
    1774                 : 
    1775                 : NS_IMETHODIMP
    1776               0 : jsdContext::SetVersion (PRInt32 id)
    1777                 : {
    1778               0 :     ASSERT_VALID_EPHEMERAL;
    1779               0 :     JSVersion ver = static_cast<JSVersion>(id);
    1780               0 :     JS_SetVersion(mJSCx, ver);
    1781               0 :     return NS_OK;
    1782                 : }
    1783                 : 
    1784                 : NS_IMETHODIMP
    1785               0 : jsdContext::GetGlobalObject (jsdIValue **_rval)
    1786                 : {
    1787               0 :     ASSERT_VALID_EPHEMERAL;
    1788               0 :     JSObject *glob = JS_GetGlobalObject(mJSCx);
    1789               0 :     JSDValue *jsdv = JSD_NewValue (mJSDCx, OBJECT_TO_JSVAL(glob));
    1790               0 :     if (!jsdv)
    1791               0 :         return NS_ERROR_FAILURE;
    1792               0 :     *_rval = jsdValue::FromPtr (mJSDCx, jsdv);
    1793               0 :     if (!*_rval)
    1794               0 :         return NS_ERROR_FAILURE;
    1795               0 :     return NS_OK;
    1796                 : }
    1797                 : 
    1798                 : NS_IMETHODIMP
    1799               0 : jsdContext::GetScriptsEnabled (bool *_rval)
    1800                 : {
    1801               0 :     ASSERT_VALID_EPHEMERAL;
    1802               0 :     if (!mISCx) {
    1803               0 :         *_rval = true;
    1804               0 :         return NS_OK;
    1805                 :     }
    1806                 : 
    1807               0 :     nsCOMPtr<nsIScriptContext> context = do_QueryInterface(mISCx);
    1808               0 :     if (!context)
    1809               0 :         return NS_ERROR_NO_INTERFACE;
    1810                 : 
    1811               0 :     *_rval = context->GetScriptsEnabled();
    1812                 : 
    1813               0 :     return NS_OK;
    1814                 : }
    1815                 : 
    1816                 : NS_IMETHODIMP
    1817               0 : jsdContext::SetScriptsEnabled (bool _rval)
    1818                 : {
    1819               0 :     ASSERT_VALID_EPHEMERAL;
    1820               0 :     if (!mISCx) {
    1821               0 :         if (_rval)
    1822               0 :             return NS_OK;
    1823               0 :         return NS_ERROR_NO_INTERFACE;
    1824                 :     }
    1825                 : 
    1826               0 :     nsCOMPtr<nsIScriptContext> context = do_QueryInterface(mISCx);
    1827               0 :     if (!context)
    1828               0 :         return NS_ERROR_NO_INTERFACE;
    1829                 : 
    1830               0 :     context->SetScriptsEnabled(_rval, true);
    1831                 : 
    1832               0 :     return NS_OK;
    1833                 : }
    1834                 : 
    1835                 : /* Stack Frames */
    1836              17 : NS_IMPL_THREADSAFE_ISUPPORTS2(jsdStackFrame, jsdIStackFrame, jsdIEphemeral)
    1837                 : 
    1838               1 : jsdStackFrame::jsdStackFrame (JSDContext *aCx, JSDThreadState *aThreadState,
    1839                 :                               JSDStackFrameInfo *aStackFrameInfo) :
    1840               1 :     mCx(aCx), mThreadState(aThreadState), mStackFrameInfo(aStackFrameInfo)
    1841                 : {
    1842                 :     DEBUG_CREATE ("jsdStackFrame", gFrameCount);
    1843               1 :     mValid = (aCx && aThreadState && aStackFrameInfo);
    1844               1 :     if (mValid) {
    1845               1 :         mLiveListEntry.key = aStackFrameInfo;
    1846               1 :         mLiveListEntry.value = this;
    1847               1 :         jsds_InsertEphemeral (&gLiveStackFrames, &mLiveListEntry);
    1848                 :     }
    1849               1 : }
    1850                 : 
    1851               2 : jsdStackFrame::~jsdStackFrame() 
    1852                 : {
    1853                 :     DEBUG_DESTROY ("jsdStackFrame", gFrameCount);
    1854               1 :     if (mValid)
    1855                 :     {
    1856                 :         /* call Invalidate() to take ourselves out of the live list */
    1857               0 :         Invalidate();
    1858                 :     }
    1859               4 : }
    1860                 : 
    1861                 : jsdIStackFrame *
    1862               1 : jsdStackFrame::FromPtr (JSDContext *aCx, JSDThreadState *aThreadState,
    1863                 :                         JSDStackFrameInfo *aStackFrameInfo)
    1864                 : {
    1865               1 :     if (!aStackFrameInfo)
    1866               0 :         return nsnull;
    1867                 : 
    1868                 :     jsdIStackFrame *rv;
    1869               2 :     nsCOMPtr<jsdIStackFrame> frame;
    1870                 : 
    1871                 :     nsCOMPtr<jsdIEphemeral> eph =
    1872                 :         jsds_FindEphemeral (&gLiveStackFrames,
    1873               2 :                             reinterpret_cast<void *>(aStackFrameInfo));
    1874                 : 
    1875               1 :     if (eph)
    1876                 :     {
    1877               0 :         frame = do_QueryInterface(eph);
    1878               0 :         rv = frame;
    1879                 :     }
    1880                 :     else
    1881                 :     {
    1882               1 :         rv = new jsdStackFrame (aCx, aThreadState, aStackFrameInfo);
    1883                 :     }
    1884                 : 
    1885               1 :     NS_IF_ADDREF(rv);
    1886               1 :     return rv;
    1887                 : }
    1888                 : 
    1889                 : NS_IMETHODIMP
    1890               1 : jsdStackFrame::Invalidate()
    1891                 : {
    1892               1 :     ASSERT_VALID_EPHEMERAL;
    1893               1 :     mValid = false;
    1894               1 :     jsds_RemoveEphemeral (&gLiveStackFrames, &mLiveListEntry);
    1895               1 :     return NS_OK;
    1896                 : }
    1897                 : 
    1898                 : void
    1899             281 : jsdStackFrame::InvalidateAll()
    1900                 : {
    1901             281 :     if (gLiveStackFrames)
    1902               1 :         jsds_InvalidateAllEphemerals (&gLiveStackFrames);
    1903             281 : }
    1904                 : 
    1905                 : NS_IMETHODIMP
    1906               0 : jsdStackFrame::GetJSDContext(JSDContext **_rval)
    1907                 : {
    1908               0 :     ASSERT_VALID_EPHEMERAL;
    1909               0 :     *_rval = mCx;
    1910               0 :     return NS_OK;
    1911                 : }
    1912                 : 
    1913                 : NS_IMETHODIMP
    1914               0 : jsdStackFrame::GetJSDThreadState(JSDThreadState **_rval)
    1915                 : {
    1916               0 :     ASSERT_VALID_EPHEMERAL;
    1917               0 :     *_rval = mThreadState;
    1918               0 :     return NS_OK;
    1919                 : }
    1920                 : 
    1921                 : NS_IMETHODIMP
    1922               0 : jsdStackFrame::GetJSDStackFrameInfo(JSDStackFrameInfo **_rval)
    1923                 : {
    1924               0 :     ASSERT_VALID_EPHEMERAL;
    1925               0 :     *_rval = mStackFrameInfo;
    1926               0 :     return NS_OK;
    1927                 : }
    1928                 : 
    1929                 : NS_IMETHODIMP
    1930               0 : jsdStackFrame::GetIsValid(bool *_rval)
    1931                 : {
    1932               0 :     *_rval = mValid;
    1933               0 :     return NS_OK;
    1934                 : }
    1935                 : 
    1936                 : NS_IMETHODIMP
    1937               0 : jsdStackFrame::GetCallingFrame(jsdIStackFrame **_rval)
    1938                 : {
    1939               0 :     ASSERT_VALID_EPHEMERAL;
    1940                 :     JSDStackFrameInfo *sfi = JSD_GetCallingStackFrame (mCx, mThreadState,
    1941               0 :                                                        mStackFrameInfo);
    1942               0 :     *_rval = jsdStackFrame::FromPtr (mCx, mThreadState, sfi);
    1943               0 :     return NS_OK;
    1944                 : }
    1945                 : 
    1946                 : NS_IMETHODIMP
    1947               0 : jsdStackFrame::GetExecutionContext(jsdIContext **_rval)
    1948                 : {
    1949               0 :     ASSERT_VALID_EPHEMERAL;
    1950               0 :     JSContext *cx = JSD_GetJSContext (mCx, mThreadState);
    1951               0 :     *_rval = jsdContext::FromPtr (mCx, cx);
    1952               0 :     return NS_OK;
    1953                 : }
    1954                 : 
    1955                 : NS_IMETHODIMP
    1956               0 : jsdStackFrame::GetFunctionName(nsACString &_rval)
    1957                 : {
    1958               0 :     ASSERT_VALID_EPHEMERAL;
    1959               0 :     JSString *str = JSD_GetIdForStackFrame(mCx, mThreadState, mStackFrameInfo);
    1960               0 :     if (str)
    1961               0 :         return AssignToJSString(&_rval, str);
    1962                 :     
    1963               0 :     _rval.Assign("anonymous");
    1964               0 :     return NS_OK;
    1965                 : }
    1966                 : 
    1967                 : NS_IMETHODIMP
    1968               0 : jsdStackFrame::GetIsDebugger(bool *_rval)
    1969                 : {
    1970               0 :     ASSERT_VALID_EPHEMERAL;
    1971               0 :     *_rval = JSD_IsStackFrameDebugger (mCx, mThreadState, mStackFrameInfo);
    1972               0 :     return NS_OK;
    1973                 : }
    1974                 : 
    1975                 : NS_IMETHODIMP
    1976               0 : jsdStackFrame::GetIsConstructing(bool *_rval)
    1977                 : {
    1978               0 :     ASSERT_VALID_EPHEMERAL;
    1979               0 :     *_rval = JSD_IsStackFrameConstructing (mCx, mThreadState, mStackFrameInfo);
    1980               0 :     return NS_OK;
    1981                 : }
    1982                 : 
    1983                 : NS_IMETHODIMP
    1984               0 : jsdStackFrame::GetScript(jsdIScript **_rval)
    1985                 : {
    1986               0 :     ASSERT_VALID_EPHEMERAL;
    1987                 :     JSDScript *script = JSD_GetScriptForStackFrame (mCx, mThreadState,
    1988               0 :                                                     mStackFrameInfo);
    1989               0 :     *_rval = jsdScript::FromPtr (mCx, script);
    1990               0 :     return NS_OK;
    1991                 : }
    1992                 : 
    1993                 : NS_IMETHODIMP
    1994               0 : jsdStackFrame::GetPc(PRUint32 *_rval)
    1995                 : {
    1996               0 :     ASSERT_VALID_EPHEMERAL;
    1997                 :     JSDScript *script = JSD_GetScriptForStackFrame (mCx, mThreadState,
    1998               0 :                                                     mStackFrameInfo);
    1999               0 :     if (!script)
    2000               0 :         return NS_ERROR_FAILURE;
    2001               0 :     uintptr_t pcbase = JSD_GetClosestPC(mCx, script, 0);
    2002                 :     
    2003               0 :     uintptr_t pc = JSD_GetPCForStackFrame (mCx, mThreadState, mStackFrameInfo);
    2004               0 :     if (pc)
    2005               0 :         *_rval = pc - pcbase;
    2006                 :     else
    2007               0 :         *_rval = pcbase;
    2008               0 :     return NS_OK;
    2009                 : }
    2010                 : 
    2011                 : NS_IMETHODIMP
    2012               0 : jsdStackFrame::GetLine(PRUint32 *_rval)
    2013                 : {
    2014               0 :     ASSERT_VALID_EPHEMERAL;
    2015                 :     JSDScript *script = JSD_GetScriptForStackFrame (mCx, mThreadState,
    2016               0 :                                                     mStackFrameInfo);
    2017               0 :     if (script) {
    2018               0 :         uintptr_t pc = JSD_GetPCForStackFrame (mCx, mThreadState, mStackFrameInfo);
    2019               0 :         *_rval = JSD_GetClosestLine (mCx, script, pc);
    2020                 :     } else {
    2021               0 :         return NS_ERROR_FAILURE;
    2022                 :     }
    2023               0 :     return NS_OK;
    2024                 : }
    2025                 : 
    2026                 : NS_IMETHODIMP
    2027               0 : jsdStackFrame::GetCallee(jsdIValue **_rval)
    2028                 : {
    2029               0 :     ASSERT_VALID_EPHEMERAL;
    2030                 :     JSDValue *jsdv = JSD_GetCallObjectForStackFrame (mCx, mThreadState,
    2031               0 :                                                      mStackFrameInfo);
    2032                 :     
    2033               0 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
    2034               0 :     return NS_OK;
    2035                 : }
    2036                 : 
    2037                 : NS_IMETHODIMP
    2038               1 : jsdStackFrame::GetScope(jsdIValue **_rval)
    2039                 : {
    2040               1 :     ASSERT_VALID_EPHEMERAL;
    2041                 :     JSDValue *jsdv = JSD_GetScopeChainForStackFrame (mCx, mThreadState,
    2042               1 :                                                      mStackFrameInfo);
    2043                 :     
    2044               1 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
    2045               1 :     return NS_OK;
    2046                 : }
    2047                 : 
    2048                 : NS_IMETHODIMP
    2049               0 : jsdStackFrame::GetThisValue(jsdIValue **_rval)
    2050                 : {
    2051               0 :     ASSERT_VALID_EPHEMERAL;
    2052                 :     JSDValue *jsdv = JSD_GetThisForStackFrame (mCx, mThreadState,
    2053               0 :                                                mStackFrameInfo);
    2054                 :     
    2055               0 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
    2056               0 :     return NS_OK;
    2057                 : }
    2058                 : 
    2059                 : 
    2060                 : NS_IMETHODIMP
    2061               0 : jsdStackFrame::Eval (const nsAString &bytes, const nsACString &fileName,
    2062                 :                      PRUint32 line, jsdIValue **result, bool *_rval)
    2063                 : {
    2064               0 :     ASSERT_VALID_EPHEMERAL;
    2065                 : 
    2066               0 :     if (bytes.IsEmpty())
    2067               0 :         return NS_ERROR_INVALID_ARG;
    2068                 : 
    2069                 :     // get pointer to buffer contained in |bytes|
    2070               0 :     nsAString::const_iterator h;
    2071               0 :     bytes.BeginReading(h);
    2072               0 :     const jschar *char_bytes = reinterpret_cast<const jschar *>(h.get());
    2073                 : 
    2074               0 :     JSExceptionState *estate = 0;
    2075                 :     jsval jv;
    2076                 : 
    2077               0 :     JSContext *cx = JSD_GetJSContext (mCx, mThreadState);
    2078                 : 
    2079               0 :     JSAutoRequest ar(cx);
    2080                 : 
    2081               0 :     estate = JS_SaveExceptionState (cx);
    2082               0 :     JS_ClearPendingException (cx);
    2083                 : 
    2084                 :     nsresult rv;
    2085               0 :     nsCOMPtr<nsIJSContextStack> stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv);
    2086               0 :     if (NS_SUCCEEDED(rv))
    2087               0 :         rv = stack->Push(cx);
    2088               0 :     if (NS_FAILED(rv)) {
    2089               0 :         JS_RestoreExceptionState (cx, estate);
    2090               0 :         return rv;
    2091                 :     }
    2092                 : 
    2093                 :     *_rval = JSD_AttemptUCScriptInStackFrame (mCx, mThreadState,
    2094                 :                                               mStackFrameInfo,
    2095                 :                                               char_bytes, bytes.Length(),
    2096               0 :                                               PromiseFlatCString(fileName).get(),
    2097               0 :                                               line, &jv);
    2098               0 :     if (!*_rval) {
    2099               0 :         if (JS_IsExceptionPending(cx))
    2100               0 :             JS_GetPendingException (cx, &jv);
    2101                 :         else
    2102               0 :             jv = JSVAL_NULL;
    2103                 :     }
    2104                 : 
    2105               0 :     JS_RestoreExceptionState (cx, estate);
    2106                 : 
    2107                 : #ifdef DEBUG
    2108                 :     JSContext* poppedCX;
    2109               0 :     rv = stack->Pop(&poppedCX);
    2110               0 :     NS_ASSERTION(NS_SUCCEEDED(rv) && poppedCX == cx, "bad pop");
    2111                 : #else
    2112                 :     (void) stack->Pop(nsnull);
    2113                 : #endif
    2114                 : 
    2115               0 :     JSDValue *jsdv = JSD_NewValue (mCx, jv);
    2116               0 :     if (!jsdv)
    2117               0 :         return NS_ERROR_FAILURE;
    2118               0 :     *result = jsdValue::FromPtr (mCx, jsdv);
    2119               0 :     if (!*result)
    2120               0 :         return NS_ERROR_FAILURE;
    2121                 :     
    2122               0 :     return NS_OK;
    2123                 : }        
    2124                 : 
    2125                 : /* Values */
    2126              28 : NS_IMPL_THREADSAFE_ISUPPORTS2(jsdValue, jsdIValue, jsdIEphemeral)
    2127                 : jsdIValue *
    2128               2 : jsdValue::FromPtr (JSDContext *aCx, JSDValue *aValue)
    2129                 : {
    2130                 :     /* value will be dropped by te jsdValue destructor. */
    2131                 : 
    2132               2 :     if (!aValue)
    2133               0 :         return nsnull;
    2134                 :     
    2135               2 :     jsdIValue *rv = new jsdValue (aCx, aValue);
    2136               2 :     NS_IF_ADDREF(rv);
    2137               2 :     return rv;
    2138                 : }
    2139                 : 
    2140               2 : jsdValue::jsdValue (JSDContext *aCx, JSDValue *aValue) : mValid(true),
    2141                 :                                                          mCx(aCx), 
    2142               2 :                                                          mValue(aValue)
    2143                 : {
    2144                 :     DEBUG_CREATE ("jsdValue", gValueCount);
    2145               2 :     mLiveListEntry.value = this;
    2146               2 :     jsds_InsertEphemeral (&gLiveValues, &mLiveListEntry);
    2147               2 : }
    2148                 : 
    2149               4 : jsdValue::~jsdValue() 
    2150                 : {
    2151                 :     DEBUG_DESTROY ("jsdValue", gValueCount);
    2152               2 :     if (mValid)
    2153                 :         /* call Invalidate() to take ourselves out of the live list */
    2154               2 :         Invalidate();
    2155               8 : }   
    2156                 : 
    2157                 : NS_IMETHODIMP
    2158               0 : jsdValue::GetIsValid(bool *_rval)
    2159                 : {
    2160               0 :     *_rval = mValid;
    2161               0 :     return NS_OK;
    2162                 : }
    2163                 : 
    2164                 : NS_IMETHODIMP
    2165               2 : jsdValue::Invalidate()
    2166                 : {
    2167               2 :     ASSERT_VALID_EPHEMERAL;
    2168               2 :     mValid = false;
    2169               2 :     jsds_RemoveEphemeral (&gLiveValues, &mLiveListEntry);
    2170               2 :     JSD_DropValue (mCx, mValue);
    2171               2 :     return NS_OK;
    2172                 : }
    2173                 : 
    2174                 : void
    2175             280 : jsdValue::InvalidateAll()
    2176                 : {
    2177             280 :     if (gLiveValues)
    2178               0 :         jsds_InvalidateAllEphemerals (&gLiveValues);
    2179             280 : }
    2180                 : 
    2181                 : NS_IMETHODIMP
    2182               0 : jsdValue::GetJSDContext(JSDContext **_rval)
    2183                 : {
    2184               0 :     ASSERT_VALID_EPHEMERAL;
    2185               0 :     *_rval = mCx;
    2186               0 :     return NS_OK;
    2187                 : }
    2188                 : 
    2189                 : NS_IMETHODIMP
    2190               0 : jsdValue::GetJSDValue (JSDValue **_rval)
    2191                 : {
    2192               0 :     ASSERT_VALID_EPHEMERAL;
    2193               0 :     *_rval = mValue;
    2194               0 :     return NS_OK;
    2195                 : }
    2196                 : 
    2197                 : NS_IMETHODIMP
    2198               0 : jsdValue::GetIsNative (bool *_rval)
    2199                 : {
    2200               0 :     ASSERT_VALID_EPHEMERAL;
    2201               0 :     *_rval = JSD_IsValueNative (mCx, mValue);
    2202               0 :     return NS_OK;
    2203                 : }
    2204                 : 
    2205                 : NS_IMETHODIMP
    2206               0 : jsdValue::GetIsNumber (bool *_rval)
    2207                 : {
    2208               0 :     ASSERT_VALID_EPHEMERAL;
    2209               0 :     *_rval = JSD_IsValueNumber (mCx, mValue);
    2210               0 :     return NS_OK;
    2211                 : }
    2212                 : 
    2213                 : NS_IMETHODIMP
    2214               0 : jsdValue::GetIsPrimitive (bool *_rval)
    2215                 : {
    2216               0 :     ASSERT_VALID_EPHEMERAL;
    2217               0 :     *_rval = JSD_IsValuePrimitive (mCx, mValue);
    2218               0 :     return NS_OK;
    2219                 : }
    2220                 : 
    2221                 : NS_IMETHODIMP
    2222               0 : jsdValue::GetJsType (PRUint32 *_rval)
    2223                 : {
    2224               0 :     ASSERT_VALID_EPHEMERAL;
    2225                 :     jsval val;
    2226                 : 
    2227               0 :     val = JSD_GetValueWrappedJSVal (mCx, mValue);
    2228                 :     
    2229               0 :     if (JSVAL_IS_NULL(val))
    2230               0 :         *_rval = TYPE_NULL;
    2231               0 :     else if (JSVAL_IS_BOOLEAN(val))
    2232               0 :         *_rval = TYPE_BOOLEAN;
    2233               0 :     else if (JSVAL_IS_DOUBLE(val))
    2234               0 :         *_rval = TYPE_DOUBLE;
    2235               0 :     else if (JSVAL_IS_INT(val))
    2236               0 :         *_rval = TYPE_INT;
    2237               0 :     else if (JSVAL_IS_STRING(val))
    2238               0 :         *_rval = TYPE_STRING;
    2239               0 :     else if (JSVAL_IS_VOID(val))
    2240               0 :         *_rval = TYPE_VOID;
    2241               0 :     else if (JSD_IsValueFunction (mCx, mValue))
    2242               0 :         *_rval = TYPE_FUNCTION;
    2243               0 :     else if (JSVAL_IS_OBJECT(val))
    2244               0 :         *_rval = TYPE_OBJECT;
    2245                 :     else
    2246               0 :         NS_ASSERTION (0, "Value has no discernible type.");
    2247                 : 
    2248               0 :     return NS_OK;
    2249                 : }
    2250                 : 
    2251                 : NS_IMETHODIMP
    2252               0 : jsdValue::GetJsPrototype (jsdIValue **_rval)
    2253                 : {
    2254               0 :     ASSERT_VALID_EPHEMERAL;
    2255               0 :     JSDValue *jsdv = JSD_GetValuePrototype (mCx, mValue);
    2256               0 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
    2257               0 :     return NS_OK;
    2258                 : }
    2259                 : 
    2260                 : NS_IMETHODIMP
    2261               1 : jsdValue::GetJsParent (jsdIValue **_rval)
    2262                 : {
    2263               1 :     ASSERT_VALID_EPHEMERAL;
    2264               1 :     JSDValue *jsdv = JSD_GetValueParent (mCx, mValue);
    2265               1 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
    2266               1 :     return NS_OK;
    2267                 : }
    2268                 : 
    2269                 : NS_IMETHODIMP
    2270               0 : jsdValue::GetJsClassName(nsACString &_rval)
    2271                 : {
    2272               0 :     ASSERT_VALID_EPHEMERAL;
    2273               0 :     _rval.Assign(JSD_GetValueClassName(mCx, mValue));
    2274                 :     
    2275               0 :     return NS_OK;
    2276                 : }
    2277                 : 
    2278                 : NS_IMETHODIMP
    2279               0 : jsdValue::GetJsConstructor (jsdIValue **_rval)
    2280                 : {
    2281               0 :     ASSERT_VALID_EPHEMERAL;
    2282               0 :     JSDValue *jsdv = JSD_GetValueConstructor (mCx, mValue);
    2283               0 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
    2284               0 :     return NS_OK;
    2285                 : }
    2286                 : 
    2287                 : NS_IMETHODIMP
    2288               0 : jsdValue::GetJsFunctionName(nsACString &_rval)
    2289                 : {
    2290               0 :     ASSERT_VALID_EPHEMERAL;
    2291               0 :     return AssignToJSString(&_rval, JSD_GetValueFunctionId(mCx, mValue));
    2292                 : }
    2293                 : 
    2294                 : NS_IMETHODIMP
    2295               0 : jsdValue::GetBooleanValue(bool *_rval)
    2296                 : {
    2297               0 :     ASSERT_VALID_EPHEMERAL;
    2298               0 :     *_rval = JSD_GetValueBoolean (mCx, mValue);
    2299               0 :     return NS_OK;
    2300                 : }
    2301                 : 
    2302                 : NS_IMETHODIMP
    2303               0 : jsdValue::GetDoubleValue(double *_rval)
    2304                 : {
    2305               0 :     ASSERT_VALID_EPHEMERAL;
    2306               0 :     *_rval = JSD_GetValueDouble (mCx, mValue);
    2307               0 :     return NS_OK;
    2308                 : }
    2309                 : 
    2310                 : NS_IMETHODIMP
    2311               0 : jsdValue::GetIntValue(PRInt32 *_rval)
    2312                 : {
    2313               0 :     ASSERT_VALID_EPHEMERAL;
    2314               0 :     *_rval = JSD_GetValueInt (mCx, mValue);
    2315               0 :     return NS_OK;
    2316                 : }
    2317                 : 
    2318                 : NS_IMETHODIMP
    2319               0 : jsdValue::GetObjectValue(jsdIObject **_rval)
    2320                 : {
    2321               0 :     ASSERT_VALID_EPHEMERAL;
    2322                 :     JSDObject *obj;
    2323               0 :     obj = JSD_GetObjectForValue (mCx, mValue);
    2324               0 :     *_rval = jsdObject::FromPtr (mCx, obj);
    2325               0 :     if (!*_rval)
    2326               0 :         return NS_ERROR_FAILURE;
    2327               0 :     return NS_OK;
    2328                 : }
    2329                 :     
    2330                 : NS_IMETHODIMP
    2331               0 : jsdValue::GetStringValue(nsACString &_rval)
    2332                 : {
    2333               0 :     ASSERT_VALID_EPHEMERAL;
    2334               0 :     JSContext *cx = JSD_GetDefaultJSContext (mCx);
    2335               0 :     if (!cx) {
    2336               0 :         NS_WARNING("No default context !?");
    2337               0 :         return NS_ERROR_FAILURE;
    2338                 :     }
    2339               0 :     JSString *jstr_val = JSD_GetValueString(mCx, mValue);
    2340               0 :     if (jstr_val) {
    2341                 :         size_t length;
    2342               0 :         const jschar *chars = JS_GetStringCharsZAndLength(cx, jstr_val, &length);
    2343               0 :         if (!chars)
    2344               0 :             return NS_ERROR_FAILURE;
    2345               0 :         nsDependentString depStr(chars, length);
    2346               0 :         CopyUTF16toUTF8(depStr, _rval);
    2347                 :     } else {
    2348               0 :         _rval.Truncate();
    2349                 :     }
    2350               0 :     return NS_OK;
    2351                 : }
    2352                 : 
    2353                 : NS_IMETHODIMP
    2354               0 : jsdValue::GetPropertyCount (PRInt32 *_rval)
    2355                 : {
    2356               0 :     ASSERT_VALID_EPHEMERAL;
    2357               0 :     if (JSD_IsValueObject(mCx, mValue))
    2358               0 :         *_rval = JSD_GetCountOfProperties (mCx, mValue);
    2359                 :     else
    2360               0 :         *_rval = -1;
    2361               0 :     return NS_OK;
    2362                 : }
    2363                 : 
    2364                 : NS_IMETHODIMP
    2365               0 : jsdValue::GetProperties (jsdIProperty ***propArray, PRUint32 *length)
    2366                 : {
    2367               0 :     ASSERT_VALID_EPHEMERAL;
    2368               0 :     *propArray = nsnull;
    2369               0 :     if (length)
    2370               0 :         *length = 0;
    2371                 : 
    2372               0 :     PRUint32 prop_count = JSD_IsValueObject(mCx, mValue)
    2373               0 :         ? JSD_GetCountOfProperties (mCx, mValue)
    2374               0 :         : 0;
    2375               0 :     NS_ENSURE_TRUE(prop_count, NS_OK);
    2376                 : 
    2377                 :     jsdIProperty **pa_temp =
    2378                 :         static_cast<jsdIProperty **>
    2379                 :                    (nsMemory::Alloc(sizeof (jsdIProperty *) * 
    2380               0 :                                        prop_count));
    2381               0 :     NS_ENSURE_TRUE(pa_temp, NS_ERROR_OUT_OF_MEMORY);
    2382                 : 
    2383               0 :     PRUint32     i    = 0;
    2384               0 :     JSDProperty *iter = NULL;
    2385                 :     JSDProperty *prop;
    2386               0 :     while ((prop = JSD_IterateProperties (mCx, mValue, &iter))) {
    2387               0 :         pa_temp[i] = jsdProperty::FromPtr (mCx, prop);
    2388               0 :         ++i;
    2389                 :     }
    2390                 :     
    2391               0 :     NS_ASSERTION (prop_count == i, "property count mismatch");    
    2392                 : 
    2393                 :     /* if caller doesn't care about length, don't bother telling them */
    2394               0 :     *propArray = pa_temp;
    2395               0 :     if (length)
    2396               0 :         *length = prop_count;
    2397                 :     
    2398               0 :     return NS_OK;
    2399                 : }
    2400                 : 
    2401                 : NS_IMETHODIMP
    2402               0 : jsdValue::GetProperty (const nsACString &name, jsdIProperty **_rval)
    2403                 : {
    2404               0 :     ASSERT_VALID_EPHEMERAL;
    2405               0 :     JSContext *cx = JSD_GetDefaultJSContext (mCx);
    2406                 : 
    2407               0 :     JSAutoRequest ar(cx);
    2408                 : 
    2409                 :     /* not rooting this */
    2410               0 :     JSString *jstr_name = JS_NewStringCopyZ(cx, PromiseFlatCString(name).get());
    2411               0 :     if (!jstr_name)
    2412               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2413                 : 
    2414               0 :     JSDProperty *prop = JSD_GetValueProperty (mCx, mValue, jstr_name);
    2415                 :     
    2416               0 :     *_rval = jsdProperty::FromPtr (mCx, prop);
    2417               0 :     return NS_OK;
    2418                 : }
    2419                 : 
    2420                 : NS_IMETHODIMP
    2421               0 : jsdValue::Refresh()
    2422                 : {
    2423               0 :     ASSERT_VALID_EPHEMERAL;
    2424               0 :     JSD_RefreshValue (mCx, mValue);
    2425               0 :     return NS_OK;
    2426                 : }
    2427                 : 
    2428                 : NS_IMETHODIMP
    2429               1 : jsdValue::GetWrappedValue(JSContext* aCx, JS::Value* aRetval)
    2430                 : {
    2431               1 :     ASSERT_VALID_EPHEMERAL;
    2432                 : 
    2433               1 :     *aRetval = JSD_GetValueWrappedJSVal(mCx, mValue);
    2434               1 :     if (!JS_WrapValue(aCx, aRetval)) {
    2435               0 :         return NS_ERROR_FAILURE;
    2436                 :     }
    2437                 : 
    2438               1 :     return NS_OK;
    2439                 : }
    2440                 : 
    2441                 : NS_IMETHODIMP
    2442               0 : jsdValue::GetScript(jsdIScript **_rval)
    2443                 : {
    2444               0 :     ASSERT_VALID_EPHEMERAL;
    2445               0 :     JSDScript *script = JSD_GetScriptForValue(mCx, mValue);
    2446               0 :     *_rval = jsdScript::FromPtr(mCx, script);
    2447               0 :     return NS_OK;
    2448                 : }
    2449                 : 
    2450                 : /******************************************************************************
    2451                 :  * debugger service implementation
    2452                 :  ******************************************************************************/
    2453            2539 : NS_IMPL_THREADSAFE_ISUPPORTS1(jsdService, jsdIDebuggerService)
    2454                 : 
    2455                 : NS_IMETHODIMP
    2456             280 : jsdService::GetJSDContext(JSDContext **_rval)
    2457                 : {
    2458             280 :     *_rval = mCx;
    2459             280 :     return NS_OK;
    2460                 : }
    2461                 : 
    2462                 : NS_IMETHODIMP
    2463               0 : jsdService::GetFlags (PRUint32 *_rval)
    2464                 : {
    2465               0 :     ASSERT_VALID_CONTEXT;
    2466               0 :     *_rval = JSD_GetContextFlags (mCx);
    2467               0 :     return NS_OK;
    2468                 : }
    2469                 : 
    2470                 : NS_IMETHODIMP
    2471               0 : jsdService::SetFlags (PRUint32 flags)
    2472                 : {
    2473               0 :     ASSERT_VALID_CONTEXT;
    2474               0 :     JSD_SetContextFlags (mCx, flags);
    2475               0 :     return NS_OK;
    2476                 : }
    2477                 : 
    2478                 : NS_IMETHODIMP
    2479               0 : jsdService::GetImplementationString(nsACString &aImplementationString)
    2480                 : {
    2481               0 :     aImplementationString.AssignLiteral(implementationString);
    2482               0 :     return NS_OK;
    2483                 : }
    2484                 : 
    2485                 : NS_IMETHODIMP
    2486               0 : jsdService::GetImplementationMajor(PRUint32 *_rval)
    2487                 : {
    2488               0 :     *_rval = JSDS_MAJOR_VERSION;
    2489               0 :     return NS_OK;
    2490                 : }
    2491                 : 
    2492                 : NS_IMETHODIMP
    2493               0 : jsdService::GetImplementationMinor(PRUint32 *_rval)
    2494                 : {
    2495               0 :     *_rval = JSDS_MINOR_VERSION;
    2496               0 :     return NS_OK;
    2497                 : }
    2498                 : 
    2499                 : NS_IMETHODIMP
    2500               1 : jsdService::GetIsOn (bool *_rval)
    2501                 : {
    2502               1 :     *_rval = mOn;
    2503               1 :     return NS_OK;
    2504                 : }
    2505                 : 
    2506                 : NS_IMETHODIMP
    2507               0 : jsdService::On (void)
    2508                 : {
    2509               0 :     return NS_ERROR_NOT_IMPLEMENTED;
    2510                 : }
    2511                 : 
    2512                 : NS_IMETHODIMP
    2513               0 : jsdService::AsyncOn (jsdIActivationCallback *activationCallback)
    2514                 : {
    2515                 :     nsresult  rv;
    2516                 : 
    2517               0 :     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
    2518               0 :     if (NS_FAILED(rv)) return rv;
    2519                 : 
    2520               0 :     mActivationCallback = activationCallback;
    2521                 :     
    2522               0 :     return xpc->SetDebugModeWhenPossible(true, true);
    2523                 : }
    2524                 : 
    2525                 : NS_IMETHODIMP
    2526               0 : jsdService::RecompileForDebugMode (JSContext *cx, JSCompartment *comp, bool mode) {
    2527               0 :   NS_ASSERTION(NS_IsMainThread(), "wrong thread");
    2528                 :   /* XPConnect now does this work itself, so this IDL entry point is no longer used. */
    2529               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    2530                 : }
    2531                 : 
    2532                 : NS_IMETHODIMP
    2533             280 : jsdService::DeactivateDebugger ()
    2534                 : {
    2535             280 :     if (!mCx)
    2536               0 :         return NS_OK;
    2537                 : 
    2538             280 :     jsdContext::InvalidateAll();
    2539             280 :     jsdScript::InvalidateAll();
    2540             280 :     jsdValue::InvalidateAll();
    2541             280 :     jsdProperty::InvalidateAll();
    2542             280 :     jsdStackFrame::InvalidateAll();
    2543             280 :     ClearAllBreakpoints();
    2544                 : 
    2545             280 :     JSD_SetErrorReporter (mCx, NULL, NULL);
    2546             280 :     JSD_SetScriptHook (mCx, NULL, NULL);
    2547             280 :     JSD_ClearThrowHook (mCx);
    2548             280 :     JSD_ClearInterruptHook (mCx);
    2549             280 :     JSD_ClearDebuggerHook (mCx);
    2550             280 :     JSD_ClearDebugBreakHook (mCx);
    2551             280 :     JSD_ClearTopLevelHook (mCx);
    2552             280 :     JSD_ClearFunctionHook (mCx);
    2553                 :     
    2554             280 :     JSD_DebuggerOff (mCx);
    2555                 : 
    2556             280 :     mCx = nsnull;
    2557             280 :     mRuntime = nsnull;
    2558             280 :     mOn = false;
    2559                 : 
    2560             280 :     return NS_OK;
    2561                 : }
    2562                 : 
    2563                 : 
    2564                 : NS_IMETHODIMP
    2565             280 : jsdService::ActivateDebugger (JSRuntime *rt)
    2566                 : {
    2567             280 :     if (mOn)
    2568               0 :         return (rt == mRuntime) ? NS_OK : NS_ERROR_ALREADY_INITIALIZED;
    2569                 : 
    2570             280 :     mRuntime = rt;
    2571                 : 
    2572             280 :     if (gPrevGCSliceCallback == jsds_GCSliceCallbackProc)
    2573                 :         /* condition indicates that the callback proc has not been set yet */
    2574             280 :         gPrevGCSliceCallback = js::SetGCSliceCallback (rt, jsds_GCSliceCallbackProc);
    2575                 : 
    2576             280 :     mCx = JSD_DebuggerOnForUser (rt, NULL, NULL);
    2577             280 :     if (!mCx)
    2578               0 :         return NS_ERROR_FAILURE;
    2579                 : 
    2580             280 :     JSContext *cx   = JSD_GetDefaultJSContext (mCx);
    2581             280 :     JSObject  *glob = JS_GetGlobalObject (cx);
    2582                 : 
    2583                 :     /* init xpconnect on the debugger's context in case xpconnect tries to
    2584                 :      * use it for stuff. */
    2585                 :     nsresult rv;
    2586             560 :     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
    2587             280 :     if (NS_FAILED(rv))
    2588               0 :         return rv;
    2589                 :     
    2590             280 :     xpc->InitClasses (cx, glob);
    2591                 : 
    2592                 :     /* Start watching for script creation/destruction and manage jsdScript
    2593                 :      * objects accordingly
    2594                 :      */
    2595             280 :     JSD_SetScriptHook (mCx, jsds_ScriptHookProc, NULL);
    2596                 : 
    2597                 :     /* If any of these mFooHook objects are installed, do the required JSD
    2598                 :      * hookup now.   See also, jsdService::SetFooHook().
    2599                 :      */
    2600             280 :     if (mErrorHook)
    2601               0 :         JSD_SetErrorReporter (mCx, jsds_ErrorHookProc, NULL);
    2602             280 :     if (mThrowHook)
    2603               0 :         JSD_SetThrowHook (mCx, jsds_ExecutionHookProc, NULL);
    2604                 :     /* can't ignore script callbacks, as we need to |Release| the wrapper 
    2605                 :      * stored in private data when a script is deleted. */
    2606             280 :     if (mInterruptHook)
    2607               0 :         JSD_SetInterruptHook (mCx, jsds_ExecutionHookProc, NULL);
    2608             280 :     if (mDebuggerHook)
    2609               0 :         JSD_SetDebuggerHook (mCx, jsds_ExecutionHookProc, NULL);
    2610             280 :     if (mDebugHook)
    2611               0 :         JSD_SetDebugBreakHook (mCx, jsds_ExecutionHookProc, NULL);
    2612             280 :     if (mTopLevelHook)
    2613               0 :         JSD_SetTopLevelHook (mCx, jsds_CallHookProc, NULL);
    2614                 :     else
    2615             280 :         JSD_ClearTopLevelHook (mCx);
    2616             280 :     if (mFunctionHook)
    2617               0 :         JSD_SetFunctionHook (mCx, jsds_CallHookProc, NULL);
    2618                 :     else
    2619             280 :         JSD_ClearFunctionHook (mCx);
    2620             280 :     mOn = true;
    2621                 : 
    2622                 : #ifdef DEBUG
    2623             280 :     printf ("+++ JavaScript debugging hooks installed.\n");
    2624                 : #endif
    2625                 : 
    2626             560 :     nsCOMPtr<jsdIActivationCallback> activationCallback;
    2627             280 :     mActivationCallback.swap(activationCallback);
    2628             280 :     if (activationCallback)
    2629               0 :         return activationCallback->OnDebuggerActivated();
    2630                 : 
    2631             280 :     return NS_OK;
    2632                 : }
    2633                 : 
    2634                 : NS_IMETHODIMP
    2635             280 : jsdService::Off (void)
    2636                 : {
    2637             280 :     if (!mOn)
    2638               0 :         return NS_OK;
    2639                 :     
    2640             280 :     if (!mCx || !mRuntime)
    2641               0 :         return NS_ERROR_NOT_INITIALIZED;
    2642                 :     
    2643             280 :     if (gDeadScripts) {
    2644               0 :         if (gGCRunning)
    2645               0 :             return NS_ERROR_NOT_AVAILABLE;
    2646                 : 
    2647               0 :         JSContext *cx = JSD_GetDefaultJSContext(mCx);
    2648               0 :         while (gDeadScripts)
    2649               0 :             jsds_NotifyPendingDeadScripts (JS_GetRuntime(cx));
    2650                 :     }
    2651                 : 
    2652             280 :     DeactivateDebugger();
    2653                 : 
    2654                 : #ifdef DEBUG
    2655             280 :     printf ("+++ JavaScript debugging hooks removed.\n");
    2656                 : #endif
    2657                 : 
    2658                 :     nsresult rv;
    2659             560 :     nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
    2660             280 :     if (NS_FAILED(rv))
    2661             280 :         return rv;
    2662                 : 
    2663               0 :     xpc->SetDebugModeWhenPossible(false, true);
    2664                 : 
    2665               0 :     return NS_OK;
    2666                 : }
    2667                 : 
    2668                 : NS_IMETHODIMP
    2669               5 : jsdService::GetPauseDepth(PRUint32 *_rval)
    2670                 : {
    2671               5 :     NS_ENSURE_ARG_POINTER(_rval);
    2672               5 :     *_rval = mPauseLevel;
    2673               5 :     return NS_OK;
    2674                 : }
    2675                 :     
    2676                 : NS_IMETHODIMP
    2677               0 : jsdService::Pause(PRUint32 *_rval)
    2678                 : {
    2679               0 :     return DoPause(_rval, false);
    2680                 : }
    2681                 : 
    2682                 : nsresult
    2683               2 : jsdService::DoPause(PRUint32 *_rval, bool internalCall)
    2684                 : {
    2685               2 :     if (!mCx)
    2686               0 :         return NS_ERROR_NOT_INITIALIZED;
    2687                 : 
    2688               2 :     if (++mPauseLevel == 1) {
    2689               2 :         JSD_SetErrorReporter (mCx, NULL, NULL);
    2690               2 :         JSD_ClearThrowHook (mCx);
    2691               2 :         JSD_ClearInterruptHook (mCx);
    2692               2 :         JSD_ClearDebuggerHook (mCx);
    2693               2 :         JSD_ClearDebugBreakHook (mCx);
    2694               2 :         JSD_ClearTopLevelHook (mCx);
    2695               2 :         JSD_ClearFunctionHook (mCx);
    2696               2 :         JSD_DebuggerPause (mCx);
    2697                 : 
    2698                 :         nsresult rv;
    2699               4 :         nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
    2700               2 :         if (NS_FAILED(rv)) return rv;
    2701                 : 
    2702               2 :         if (!internalCall) {
    2703               0 :             rv = xpc->SetDebugModeWhenPossible(false, false);
    2704               0 :             NS_ENSURE_SUCCESS(rv, rv);
    2705                 :         }
    2706                 :     }
    2707                 : 
    2708               2 :     if (_rval)
    2709               0 :         *_rval = mPauseLevel;
    2710                 : 
    2711               2 :     return NS_OK;
    2712                 : }
    2713                 : 
    2714                 : NS_IMETHODIMP
    2715               0 : jsdService::UnPause(PRUint32 *_rval)
    2716                 : {
    2717               0 :     return DoUnPause(_rval, false);
    2718                 : }
    2719                 : 
    2720                 : nsresult
    2721               2 : jsdService::DoUnPause(PRUint32 *_rval, bool internalCall)
    2722                 : {
    2723               2 :     if (!mCx)
    2724               0 :         return NS_ERROR_NOT_INITIALIZED;
    2725                 : 
    2726               2 :     if (mPauseLevel == 0)
    2727               0 :         return NS_ERROR_NOT_AVAILABLE;
    2728                 : 
    2729                 :     /* check mOn before we muck with this stuff, it's possible the debugger
    2730                 :      * was turned off while we were paused.
    2731                 :      */
    2732               2 :     if (--mPauseLevel == 0 && mOn) {
    2733               2 :         JSD_DebuggerUnpause (mCx);
    2734               2 :         if (mErrorHook)
    2735               0 :             JSD_SetErrorReporter (mCx, jsds_ErrorHookProc, NULL);
    2736               2 :         if (mThrowHook)
    2737               0 :             JSD_SetThrowHook (mCx, jsds_ExecutionHookProc, NULL);
    2738               2 :         if (mInterruptHook)
    2739               0 :             JSD_SetInterruptHook (mCx, jsds_ExecutionHookProc, NULL);
    2740               2 :         if (mDebuggerHook)
    2741               0 :             JSD_SetDebuggerHook (mCx, jsds_ExecutionHookProc, NULL);
    2742               2 :         if (mDebugHook)
    2743               0 :             JSD_SetDebugBreakHook (mCx, jsds_ExecutionHookProc, NULL);
    2744               2 :         if (mTopLevelHook)
    2745               0 :             JSD_SetTopLevelHook (mCx, jsds_CallHookProc, NULL);
    2746                 :         else
    2747               2 :             JSD_ClearTopLevelHook (mCx);
    2748               2 :         if (mFunctionHook)
    2749               0 :             JSD_SetFunctionHook (mCx, jsds_CallHookProc, NULL);
    2750                 :         else
    2751               2 :             JSD_ClearFunctionHook (mCx);
    2752                 : 
    2753                 :         nsresult rv;
    2754               4 :         nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID(), &rv);
    2755               2 :         if (NS_FAILED(rv)) return rv;
    2756                 : 
    2757               2 :         if (!internalCall) {
    2758               0 :             rv = xpc->SetDebugModeWhenPossible(true, false);
    2759               0 :             NS_ENSURE_SUCCESS(rv, rv);
    2760                 :         }
    2761                 :     }
    2762                 :     
    2763               2 :     if (_rval)
    2764               0 :         *_rval = mPauseLevel;
    2765                 : 
    2766               2 :     return NS_OK;
    2767                 : }
    2768                 : 
    2769                 : NS_IMETHODIMP
    2770               0 : jsdService::EnumerateContexts (jsdIContextEnumerator *enumerator)
    2771                 : {
    2772               0 :     ASSERT_VALID_CONTEXT;
    2773                 :     
    2774               0 :     if (!enumerator)
    2775               0 :         return NS_OK;
    2776                 :     
    2777               0 :     JSContext *iter = NULL;
    2778                 :     JSContext *cx;
    2779                 : 
    2780               0 :     while ((cx = JS_ContextIterator (mRuntime, &iter)))
    2781                 :     {
    2782                 :         nsCOMPtr<jsdIContext> jsdicx = 
    2783               0 :             getter_AddRefs(jsdContext::FromPtr(mCx, cx));
    2784               0 :         if (jsdicx)
    2785                 :         {
    2786               0 :             if (NS_FAILED(enumerator->EnumerateContext(jsdicx)))
    2787                 :                 break;
    2788                 :         }
    2789                 :     }
    2790                 : 
    2791               0 :     return NS_OK;
    2792                 : }
    2793                 : 
    2794                 : NS_IMETHODIMP
    2795               1 : jsdService::EnumerateScripts (jsdIScriptEnumerator *enumerator)
    2796                 : {
    2797               1 :     ASSERT_VALID_CONTEXT;
    2798                 :     
    2799                 :     JSDScript *script;
    2800               1 :     JSDScript *iter = NULL;
    2801               1 :     nsresult rv = NS_OK;
    2802                 :     
    2803               1 :     JSD_LockScriptSubsystem(mCx);
    2804               8 :     while((script = JSD_IterateScripts(mCx, &iter))) {
    2805                 :         nsCOMPtr<jsdIScript> jsdis =
    2806              12 :             getter_AddRefs(jsdScript::FromPtr(mCx, script));
    2807               6 :         rv = enumerator->EnumerateScript (jsdis);
    2808               6 :         if (NS_FAILED(rv))
    2809                 :             break;
    2810                 :     }
    2811               1 :     JSD_UnlockScriptSubsystem(mCx);
    2812                 : 
    2813               1 :     return rv;
    2814                 : }
    2815                 : 
    2816                 : NS_IMETHODIMP
    2817               0 : jsdService::GC (void)
    2818                 : {
    2819               0 :     ASSERT_VALID_CONTEXT;
    2820               0 :     JSContext *cx = JSD_GetDefaultJSContext (mCx);
    2821               0 :     JS_GC(cx);
    2822               0 :     return NS_OK;
    2823                 : }
    2824                 :     
    2825                 : NS_IMETHODIMP
    2826               0 : jsdService::DumpHeap(const nsACString &fileName)
    2827                 : {
    2828               0 :     ASSERT_VALID_CONTEXT;
    2829                 : #ifndef DEBUG
    2830                 :     return NS_ERROR_NOT_IMPLEMENTED;
    2831                 : #else
    2832               0 :     nsresult rv = NS_OK;
    2833               0 :     FILE *file = !fileName.IsEmpty() ? fopen(PromiseFlatCString(fileName).get(), "w") : stdout;
    2834               0 :     if (!file) {
    2835               0 :         rv = NS_ERROR_FAILURE;
    2836                 :     } else {
    2837               0 :         JSContext *cx = JSD_GetDefaultJSContext (mCx);
    2838               0 :         if (!JS_DumpHeap(JS_GetRuntime(cx), file, NULL, JSTRACE_OBJECT, NULL, (size_t)-1, NULL))
    2839               0 :             rv = NS_ERROR_FAILURE;
    2840               0 :         if (file != stdout)
    2841               0 :             fclose(file);
    2842                 :     }
    2843               0 :     return rv;
    2844                 : #endif
    2845                 : }
    2846                 : 
    2847                 : NS_IMETHODIMP
    2848               0 : jsdService::ClearProfileData ()
    2849                 : {
    2850               0 :     ASSERT_VALID_CONTEXT;
    2851               0 :     JSD_ClearAllProfileData (mCx);
    2852               0 :     return NS_OK;
    2853                 : }
    2854                 : 
    2855                 : NS_IMETHODIMP
    2856               0 : jsdService::InsertFilter (jsdIFilter *filter, jsdIFilter *after)
    2857                 : {
    2858               0 :     NS_ENSURE_ARG_POINTER (filter);
    2859               0 :     if (jsds_FindFilter (filter))
    2860               0 :         return NS_ERROR_INVALID_ARG;
    2861                 : 
    2862               0 :     FilterRecord *rec = PR_NEWZAP (FilterRecord);
    2863               0 :     if (!rec)
    2864               0 :         return NS_ERROR_OUT_OF_MEMORY;
    2865                 : 
    2866               0 :     if (!jsds_SyncFilter (rec, filter)) {
    2867               0 :         PR_Free (rec);
    2868               0 :         return NS_ERROR_FAILURE;
    2869                 :     }
    2870                 :     
    2871               0 :     if (gFilters) {
    2872               0 :         if (!after) {
    2873                 :             /* insert at head of list */
    2874               0 :             PR_INSERT_LINK(&rec->links, &gFilters->links);
    2875               0 :             gFilters = rec;
    2876                 :         } else {
    2877                 :             /* insert somewhere in the list */
    2878               0 :             FilterRecord *afterRecord = jsds_FindFilter (after);
    2879               0 :             if (!afterRecord) {
    2880               0 :                 jsds_FreeFilter(rec);
    2881               0 :                 return NS_ERROR_INVALID_ARG;
    2882                 :             }
    2883               0 :             PR_INSERT_AFTER(&rec->links, &afterRecord->links);
    2884                 :         }
    2885                 :     } else {
    2886               0 :         if (after) {
    2887                 :             /* user asked to insert into the middle of an empty list, bail. */
    2888               0 :             jsds_FreeFilter(rec);
    2889               0 :             return NS_ERROR_NOT_INITIALIZED;
    2890                 :         }
    2891               0 :         PR_INIT_CLIST(&rec->links);
    2892               0 :         gFilters = rec;
    2893                 :     }
    2894                 :     
    2895               0 :     return NS_OK;
    2896                 : }
    2897                 : 
    2898                 : NS_IMETHODIMP
    2899               0 : jsdService::AppendFilter (jsdIFilter *filter)
    2900                 : {
    2901               0 :     NS_ENSURE_ARG_POINTER (filter);
    2902               0 :     if (jsds_FindFilter (filter))
    2903               0 :         return NS_ERROR_INVALID_ARG;
    2904               0 :     FilterRecord *rec = PR_NEWZAP (FilterRecord);
    2905                 : 
    2906               0 :     if (!jsds_SyncFilter (rec, filter)) {
    2907               0 :         PR_Free (rec);
    2908               0 :         return NS_ERROR_FAILURE;
    2909                 :     }
    2910                 :     
    2911               0 :     if (gFilters) {
    2912               0 :         PR_INSERT_BEFORE(&rec->links, &gFilters->links);
    2913                 :     } else {
    2914               0 :         PR_INIT_CLIST(&rec->links);
    2915               0 :         gFilters = rec;
    2916                 :     }
    2917                 :     
    2918               0 :     return NS_OK;
    2919                 : }
    2920                 : 
    2921                 : NS_IMETHODIMP
    2922               0 : jsdService::RemoveFilter (jsdIFilter *filter)
    2923                 : {
    2924               0 :     NS_ENSURE_ARG_POINTER(filter);
    2925               0 :     FilterRecord *rec = jsds_FindFilter (filter);
    2926               0 :     if (!rec)
    2927               0 :         return NS_ERROR_INVALID_ARG;
    2928                 :     
    2929               0 :     if (gFilters == rec) {
    2930                 :         gFilters = reinterpret_cast<FilterRecord *>
    2931               0 :                                    (PR_NEXT_LINK(&rec->links));
    2932                 :         /* If we're the only filter left, null out the list head. */
    2933               0 :         if (gFilters == rec)
    2934               0 :             gFilters = nsnull;
    2935                 :     }
    2936                 : 
    2937                 :     
    2938               0 :     PR_REMOVE_LINK(&rec->links);
    2939               0 :     jsds_FreeFilter (rec);
    2940                 :     
    2941               0 :     return NS_OK;
    2942                 : }
    2943                 : 
    2944                 : NS_IMETHODIMP
    2945               0 : jsdService::SwapFilters (jsdIFilter *filter_a, jsdIFilter *filter_b)
    2946                 : {
    2947               0 :     NS_ENSURE_ARG_POINTER(filter_a);
    2948               0 :     NS_ENSURE_ARG_POINTER(filter_b);
    2949                 :     
    2950               0 :     FilterRecord *rec_a = jsds_FindFilter (filter_a);
    2951               0 :     if (!rec_a)
    2952               0 :         return NS_ERROR_INVALID_ARG;
    2953                 :     
    2954               0 :     if (filter_a == filter_b) {
    2955                 :         /* just a refresh */
    2956               0 :         if (!jsds_SyncFilter (rec_a, filter_a))
    2957               0 :             return NS_ERROR_FAILURE;
    2958               0 :         return NS_OK;
    2959                 :     }
    2960                 :     
    2961               0 :     FilterRecord *rec_b = jsds_FindFilter (filter_b);
    2962               0 :     if (!rec_b) {
    2963                 :         /* filter_b is not in the list, replace filter_a with filter_b. */
    2964               0 :         if (!jsds_SyncFilter (rec_a, filter_b))
    2965               0 :             return NS_ERROR_FAILURE;
    2966                 :     } else {
    2967                 :         /* both filters are in the list, swap. */
    2968               0 :         if (!jsds_SyncFilter (rec_a, filter_b))
    2969               0 :             return NS_ERROR_FAILURE;
    2970               0 :         if (!jsds_SyncFilter (rec_b, filter_a))
    2971               0 :             return NS_ERROR_FAILURE;
    2972                 :     }
    2973                 :     
    2974               0 :     return NS_OK;
    2975                 : }
    2976                 : 
    2977                 : NS_IMETHODIMP
    2978               0 : jsdService::EnumerateFilters (jsdIFilterEnumerator *enumerator) 
    2979                 : {
    2980               0 :     if (!gFilters)
    2981               0 :         return NS_OK;
    2982                 :     
    2983               0 :     FilterRecord *current = gFilters;
    2984               0 :     do {
    2985               0 :         jsds_SyncFilter (current, current->filterObject);
    2986                 :         /* SyncFilter failure would be bad, but what would we do about it? */
    2987               0 :         if (enumerator) {
    2988               0 :             nsresult rv = enumerator->EnumerateFilter (current->filterObject);
    2989               0 :             if (NS_FAILED(rv))
    2990               0 :                 return rv;
    2991                 :         }
    2992                 :         current = reinterpret_cast<FilterRecord *>
    2993               0 :                                   (PR_NEXT_LINK (&current->links));
    2994                 :     } while (current != gFilters);
    2995                 :     
    2996               0 :     return NS_OK;
    2997                 : }
    2998                 : 
    2999                 : NS_IMETHODIMP
    3000               0 : jsdService::RefreshFilters ()
    3001                 : {
    3002               0 :     return EnumerateFilters(nsnull);
    3003                 : }
    3004                 : 
    3005                 : NS_IMETHODIMP
    3006             280 : jsdService::ClearFilters ()
    3007                 : {
    3008             280 :     if (!gFilters)
    3009             280 :         return NS_OK;
    3010                 : 
    3011                 :     FilterRecord *current = reinterpret_cast<FilterRecord *>
    3012               0 :                                             (PR_NEXT_LINK (&gFilters->links));
    3013               0 :     do {
    3014                 :         FilterRecord *next = reinterpret_cast<FilterRecord *>
    3015               0 :                                              (PR_NEXT_LINK (&current->links));
    3016               0 :         PR_REMOVE_AND_INIT_LINK(&current->links);
    3017               0 :         jsds_FreeFilter(current);
    3018               0 :         current = next;
    3019                 :     } while (current != gFilters);
    3020                 :     
    3021               0 :     jsds_FreeFilter(current);
    3022               0 :     gFilters = nsnull;
    3023                 :     
    3024               0 :     return NS_OK;
    3025                 : }
    3026                 :         
    3027                 : NS_IMETHODIMP
    3028             280 : jsdService::ClearAllBreakpoints (void)
    3029                 : {
    3030             280 :     ASSERT_VALID_CONTEXT;
    3031                 : 
    3032             280 :     JSD_LockScriptSubsystem(mCx);
    3033             280 :     JSD_ClearAllExecutionHooks (mCx);
    3034             280 :     JSD_UnlockScriptSubsystem(mCx);
    3035             280 :     return NS_OK;
    3036                 : }
    3037                 : 
    3038                 : NS_IMETHODIMP
    3039               0 : jsdService::WrapValue(const JS::Value &value, jsdIValue **_rval)
    3040                 : {
    3041               0 :     ASSERT_VALID_CONTEXT;
    3042               0 :     JSDValue *jsdv = JSD_NewValue(mCx, value);
    3043               0 :     if (!jsdv)
    3044               0 :         return NS_ERROR_FAILURE;
    3045                 :     
    3046               0 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
    3047               0 :     return NS_OK;
    3048                 : }
    3049                 : 
    3050                 : 
    3051                 : NS_IMETHODIMP
    3052               0 : jsdService::EnterNestedEventLoop (jsdINestCallback *callback, PRUint32 *_rval)
    3053                 : {
    3054                 :     // Nesting event queues is a thing of the past.  Now, we just spin the
    3055                 :     // current event loop.
    3056                 :  
    3057                 :     nsresult rv;
    3058                 :     nsCOMPtr<nsIJSContextStack> 
    3059               0 :         stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv));
    3060               0 :     if (NS_FAILED(rv))
    3061               0 :         return rv;
    3062               0 :     PRUint32 nestLevel = ++mNestedLoopLevel;
    3063                 :     
    3064               0 :     nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
    3065                 : 
    3066               0 :     if (NS_SUCCEEDED(stack->Push(nsnull))) {
    3067               0 :         if (callback) {
    3068               0 :             DoPause(nsnull, true);
    3069               0 :             rv = callback->OnNest();
    3070               0 :             DoUnPause(nsnull, true);
    3071                 :         }
    3072                 :         
    3073               0 :         while (NS_SUCCEEDED(rv) && mNestedLoopLevel >= nestLevel) {
    3074               0 :             if (!NS_ProcessNextEvent(thread))
    3075               0 :                 rv = NS_ERROR_UNEXPECTED;
    3076                 :         }
    3077                 : 
    3078                 :         JSContext* cx;
    3079               0 :         stack->Pop(&cx);
    3080               0 :         NS_ASSERTION(cx == nsnull, "JSContextStack mismatch");
    3081                 :     }
    3082                 :     else
    3083               0 :         rv = NS_ERROR_FAILURE;
    3084                 :     
    3085               0 :     NS_ASSERTION (mNestedLoopLevel <= nestLevel,
    3086                 :                   "nested event didn't unwind properly");
    3087               0 :     if (mNestedLoopLevel == nestLevel)
    3088               0 :         --mNestedLoopLevel;
    3089                 : 
    3090               0 :     *_rval = mNestedLoopLevel;
    3091               0 :     return rv;
    3092                 : }
    3093                 : 
    3094                 : NS_IMETHODIMP
    3095               0 : jsdService::ExitNestedEventLoop (PRUint32 *_rval)
    3096                 : {
    3097               0 :     if (mNestedLoopLevel > 0)
    3098               0 :         --mNestedLoopLevel;
    3099                 :     else
    3100               0 :         return NS_ERROR_FAILURE;
    3101                 : 
    3102               0 :     *_rval = mNestedLoopLevel;    
    3103               0 :     return NS_OK;
    3104                 : }    
    3105                 : 
    3106                 : /* hook attribute get/set functions */
    3107                 : 
    3108                 : NS_IMETHODIMP
    3109               0 : jsdService::SetErrorHook (jsdIErrorHook *aHook)
    3110                 : {
    3111               0 :     mErrorHook = aHook;
    3112                 : 
    3113                 :     /* if the debugger isn't initialized, that's all we can do for now.  The
    3114                 :      * ActivateDebugger() method will do the rest when the coast is clear.
    3115                 :      */
    3116               0 :     if (!mCx || mPauseLevel)
    3117               0 :         return NS_OK;
    3118                 : 
    3119               0 :     if (aHook)
    3120               0 :         JSD_SetErrorReporter (mCx, jsds_ErrorHookProc, NULL);
    3121                 :     else
    3122               0 :         JSD_SetErrorReporter (mCx, NULL, NULL);
    3123                 : 
    3124               0 :     return NS_OK;
    3125                 : }
    3126                 : 
    3127                 : NS_IMETHODIMP
    3128               0 : jsdService::GetErrorHook (jsdIErrorHook **aHook)
    3129                 : {
    3130               0 :     *aHook = mErrorHook;
    3131               0 :     NS_IF_ADDREF(*aHook);
    3132                 :     
    3133               0 :     return NS_OK;
    3134                 : }
    3135                 : 
    3136                 : NS_IMETHODIMP
    3137               1 : jsdService::SetBreakpointHook (jsdIExecutionHook *aHook)
    3138                 : {    
    3139               1 :     mBreakpointHook = aHook;
    3140               1 :     return NS_OK;
    3141                 : }
    3142                 : 
    3143                 : NS_IMETHODIMP
    3144               4 : jsdService::GetBreakpointHook (jsdIExecutionHook **aHook)
    3145                 : {   
    3146               4 :     *aHook = mBreakpointHook;
    3147               4 :     NS_IF_ADDREF(*aHook);
    3148                 :     
    3149               4 :     return NS_OK;
    3150                 : }
    3151                 : 
    3152                 : NS_IMETHODIMP
    3153               0 : jsdService::SetDebugHook (jsdIExecutionHook *aHook)
    3154                 : {    
    3155               0 :     mDebugHook = aHook;
    3156                 : 
    3157                 :     /* if the debugger isn't initialized, that's all we can do for now.  The
    3158                 :      * ActivateDebugger() method will do the rest when the coast is clear.
    3159                 :      */
    3160               0 :     if (!mCx || mPauseLevel)
    3161               0 :         return NS_OK;
    3162                 : 
    3163               0 :     if (aHook)
    3164               0 :         JSD_SetDebugBreakHook (mCx, jsds_ExecutionHookProc, NULL);
    3165                 :     else
    3166               0 :         JSD_ClearDebugBreakHook (mCx);
    3167                 :     
    3168               0 :     return NS_OK;
    3169                 : }
    3170                 : 
    3171                 : NS_IMETHODIMP
    3172               0 : jsdService::GetDebugHook (jsdIExecutionHook **aHook)
    3173                 : {   
    3174               0 :     *aHook = mDebugHook;
    3175               0 :     NS_IF_ADDREF(*aHook);
    3176                 :     
    3177               0 :     return NS_OK;
    3178                 : }
    3179                 : 
    3180                 : NS_IMETHODIMP
    3181               0 : jsdService::SetDebuggerHook (jsdIExecutionHook *aHook)
    3182                 : {    
    3183               0 :     mDebuggerHook = aHook;
    3184                 : 
    3185                 :     /* if the debugger isn't initialized, that's all we can do for now.  The
    3186                 :      * ActivateDebugger() method will do the rest when the coast is clear.
    3187                 :      */
    3188               0 :     if (!mCx || mPauseLevel)
    3189               0 :         return NS_OK;
    3190                 : 
    3191               0 :     if (aHook)
    3192               0 :         JSD_SetDebuggerHook (mCx, jsds_ExecutionHookProc, NULL);
    3193                 :     else
    3194               0 :         JSD_ClearDebuggerHook (mCx);
    3195                 :     
    3196               0 :     return NS_OK;
    3197                 : }
    3198                 : 
    3199                 : NS_IMETHODIMP
    3200               0 : jsdService::GetDebuggerHook (jsdIExecutionHook **aHook)
    3201                 : {   
    3202               0 :     *aHook = mDebuggerHook;
    3203               0 :     NS_IF_ADDREF(*aHook);
    3204                 :     
    3205               0 :     return NS_OK;
    3206                 : }
    3207                 : 
    3208                 : NS_IMETHODIMP
    3209               0 : jsdService::SetInterruptHook (jsdIExecutionHook *aHook)
    3210                 : {    
    3211               0 :     mInterruptHook = aHook;
    3212                 : 
    3213                 :     /* if the debugger isn't initialized, that's all we can do for now.  The
    3214                 :      * ActivateDebugger() method will do the rest when the coast is clear.
    3215                 :      */
    3216               0 :     if (!mCx || mPauseLevel)
    3217               0 :         return NS_OK;
    3218                 : 
    3219               0 :     if (aHook)
    3220               0 :         JSD_SetInterruptHook (mCx, jsds_ExecutionHookProc, NULL);
    3221                 :     else
    3222               0 :         JSD_ClearInterruptHook (mCx);
    3223                 :     
    3224               0 :     return NS_OK;
    3225                 : }
    3226                 : 
    3227                 : NS_IMETHODIMP
    3228               0 : jsdService::GetInterruptHook (jsdIExecutionHook **aHook)
    3229                 : {   
    3230               0 :     *aHook = mInterruptHook;
    3231               0 :     NS_IF_ADDREF(*aHook);
    3232                 :     
    3233               0 :     return NS_OK;
    3234                 : }
    3235                 : 
    3236                 : NS_IMETHODIMP
    3237               0 : jsdService::SetScriptHook (jsdIScriptHook *aHook)
    3238                 : {    
    3239               0 :     mScriptHook = aHook;
    3240                 : 
    3241                 :     /* if the debugger isn't initialized, that's all we can do for now.  The
    3242                 :      * ActivateDebugger() method will do the rest when the coast is clear.
    3243                 :      */
    3244               0 :     if (!mCx || mPauseLevel)
    3245               0 :         return NS_OK;
    3246                 :     
    3247               0 :     if (aHook)
    3248               0 :         JSD_SetScriptHook (mCx, jsds_ScriptHookProc, NULL);
    3249                 :     /* we can't unset it if !aHook, because we still need to see script
    3250                 :      * deletes in order to Release the jsdIScripts held in JSDScript
    3251                 :      * private data. */
    3252               0 :     return NS_OK;
    3253                 : }
    3254                 : 
    3255                 : NS_IMETHODIMP
    3256          206574 : jsdService::GetScriptHook (jsdIScriptHook **aHook)
    3257                 : {   
    3258          206574 :     *aHook = mScriptHook;
    3259          206574 :     NS_IF_ADDREF(*aHook);
    3260                 :     
    3261          206574 :     return NS_OK;
    3262                 : }
    3263                 : 
    3264                 : NS_IMETHODIMP
    3265               0 : jsdService::SetThrowHook (jsdIExecutionHook *aHook)
    3266                 : {    
    3267               0 :     mThrowHook = aHook;
    3268                 : 
    3269                 :     /* if the debugger isn't initialized, that's all we can do for now.  The
    3270                 :      * ActivateDebugger() method will do the rest when the coast is clear.
    3271                 :      */
    3272               0 :     if (!mCx || mPauseLevel)
    3273               0 :         return NS_OK;
    3274                 : 
    3275               0 :     if (aHook)
    3276               0 :         JSD_SetThrowHook (mCx, jsds_ExecutionHookProc, NULL);
    3277                 :     else
    3278               0 :         JSD_ClearThrowHook (mCx);
    3279                 :     
    3280               0 :     return NS_OK;
    3281                 : }
    3282                 : 
    3283                 : NS_IMETHODIMP
    3284               0 : jsdService::GetThrowHook (jsdIExecutionHook **aHook)
    3285                 : {   
    3286               0 :     *aHook = mThrowHook;
    3287               0 :     NS_IF_ADDREF(*aHook);
    3288                 :     
    3289               0 :     return NS_OK;
    3290                 : }
    3291                 : 
    3292                 : NS_IMETHODIMP
    3293               0 : jsdService::SetTopLevelHook (jsdICallHook *aHook)
    3294                 : {    
    3295               0 :     mTopLevelHook = aHook;
    3296                 : 
    3297                 :     /* if the debugger isn't initialized, that's all we can do for now.  The
    3298                 :      * ActivateDebugger() method will do the rest when the coast is clear.
    3299                 :      */
    3300               0 :     if (!mCx || mPauseLevel)
    3301               0 :         return NS_OK;
    3302                 : 
    3303               0 :     if (aHook)
    3304               0 :         JSD_SetTopLevelHook (mCx, jsds_CallHookProc, NULL);
    3305                 :     else
    3306               0 :         JSD_ClearTopLevelHook (mCx);
    3307                 :     
    3308               0 :     return NS_OK;
    3309                 : }
    3310                 : 
    3311                 : NS_IMETHODIMP
    3312               0 : jsdService::GetTopLevelHook (jsdICallHook **aHook)
    3313                 : {   
    3314               0 :     *aHook = mTopLevelHook;
    3315               0 :     NS_IF_ADDREF(*aHook);
    3316                 :     
    3317               0 :     return NS_OK;
    3318                 : }
    3319                 : 
    3320                 : NS_IMETHODIMP
    3321               0 : jsdService::SetFunctionHook (jsdICallHook *aHook)
    3322                 : {    
    3323               0 :     mFunctionHook = aHook;
    3324                 : 
    3325                 :     /* if the debugger isn't initialized, that's all we can do for now.  The
    3326                 :      * ActivateDebugger() method will do the rest when the coast is clear.
    3327                 :      */
    3328               0 :     if (!mCx || mPauseLevel)
    3329               0 :         return NS_OK;
    3330                 : 
    3331               0 :     if (aHook)
    3332               0 :         JSD_SetFunctionHook (mCx, jsds_CallHookProc, NULL);
    3333                 :     else
    3334               0 :         JSD_ClearFunctionHook (mCx);
    3335                 :     
    3336               0 :     return NS_OK;
    3337                 : }
    3338                 : 
    3339                 : NS_IMETHODIMP
    3340               0 : jsdService::GetFunctionHook (jsdICallHook **aHook)
    3341                 : {   
    3342               0 :     *aHook = mFunctionHook;
    3343               0 :     NS_IF_ADDREF(*aHook);
    3344                 :     
    3345               0 :     return NS_OK;
    3346                 : }
    3347                 : 
    3348                 : /* virtual */
    3349             840 : jsdService::~jsdService()
    3350                 : {
    3351             280 :     ClearFilters();
    3352             280 :     mErrorHook = nsnull;
    3353             280 :     mBreakpointHook = nsnull;
    3354             280 :     mDebugHook = nsnull;
    3355             280 :     mDebuggerHook = nsnull;
    3356             280 :     mInterruptHook = nsnull;
    3357             280 :     mScriptHook = nsnull;
    3358             280 :     mThrowHook = nsnull;
    3359             280 :     mTopLevelHook = nsnull;
    3360             280 :     mFunctionHook = nsnull;
    3361             280 :     gGCRunning = false;
    3362             280 :     Off();
    3363             280 :     gJsds = nsnull;
    3364            1120 : }
    3365                 : 
    3366                 : jsdService *
    3367             280 : jsdService::GetService ()
    3368                 : {
    3369             280 :     if (!gJsds)
    3370             280 :         gJsds = new jsdService();
    3371                 :         
    3372             280 :     NS_IF_ADDREF(gJsds);
    3373             280 :     return gJsds;
    3374                 : }
    3375                 : 
    3376             280 : NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(jsdService, jsdService::GetService)
    3377                 : 
    3378                 : /* app-start observer.  turns on the debugger at app-start.  this is inserted
    3379                 :  * and/or removed from the app-start category by the jsdService::initAtStartup
    3380                 :  * property.
    3381                 :  */
    3382                 : class jsdASObserver : public nsIObserver 
    3383                 : {
    3384                 :   public:
    3385                 :     NS_DECL_ISUPPORTS
    3386                 :     NS_DECL_NSIOBSERVER
    3387                 : 
    3388               0 :     jsdASObserver () {}    
    3389                 : };
    3390                 : 
    3391               0 : NS_IMPL_THREADSAFE_ISUPPORTS1(jsdASObserver, nsIObserver)
    3392                 : 
    3393                 : NS_IMETHODIMP
    3394               0 : jsdASObserver::Observe (nsISupports *aSubject, const char *aTopic,
    3395                 :                         const PRUnichar *aData)
    3396                 : {
    3397                 :     nsresult rv;
    3398                 : 
    3399                 :     // Hmm.  Why is the app-startup observer called multiple times?
    3400                 :     //NS_ASSERTION(!gJsds, "app startup observer called twice");
    3401               0 :     nsCOMPtr<jsdIDebuggerService> jsds = do_GetService(jsdServiceCtrID, &rv);
    3402               0 :     if (NS_FAILED(rv))
    3403               0 :         return rv;
    3404                 : 
    3405                 :     bool on;
    3406               0 :     rv = jsds->GetIsOn(&on);
    3407               0 :     if (NS_FAILED(rv) || on)
    3408               0 :         return rv;
    3409                 :     
    3410               0 :     nsCOMPtr<nsIJSRuntimeService> rts = do_GetService(NS_JSRT_CTRID, &rv);
    3411               0 :     if (NS_FAILED(rv))
    3412               0 :         return rv;    
    3413                 : 
    3414                 :     JSRuntime *rt;
    3415               0 :     rts->GetRuntime (&rt);
    3416               0 :     if (NS_FAILED(rv))
    3417               0 :         return rv;
    3418                 : 
    3419               0 :     rv = jsds->ActivateDebugger(rt);
    3420               0 :     if (NS_FAILED(rv))
    3421               0 :         return rv;
    3422                 :     
    3423               0 :     return NS_OK;
    3424                 : }
    3425                 : 
    3426               0 : NS_GENERIC_FACTORY_CONSTRUCTOR(jsdASObserver)
    3427                 : NS_DEFINE_NAMED_CID(JSDSERVICE_CID);
    3428                 : NS_DEFINE_NAMED_CID(JSDASO_CID);
    3429                 : 
    3430                 : static const mozilla::Module::CIDEntry kJSDCIDs[] = {
    3431                 :     { &kJSDSERVICE_CID, false, NULL, jsdServiceConstructor },
    3432                 :     { &kJSDASO_CID, false, NULL, jsdASObserverConstructor },
    3433                 :     { NULL }
    3434                 : };
    3435                 : 
    3436                 : static const mozilla::Module::ContractIDEntry kJSDContracts[] = {
    3437                 :     { jsdServiceCtrID, &kJSDSERVICE_CID },
    3438                 :     { jsdARObserverCtrID, &kJSDASO_CID },
    3439                 :     { NULL }
    3440                 : };
    3441                 : 
    3442                 : static const mozilla::Module kJSDModule = {
    3443                 :     mozilla::Module::kVersion,
    3444                 :     kJSDCIDs,
    3445                 :     kJSDContracts
    3446                 : };
    3447                 : 
    3448                 : NSMODULE_DEFN(JavaScript_Debugger) = &kJSDModule;
    3449                 : 
    3450                 : /********************************************************************************
    3451                 :  ********************************************************************************
    3452                 :  * graveyard
    3453                 :  */
    3454                 : 
    3455                 : #if 0
    3456                 : /* Thread States */
    3457                 : NS_IMPL_THREADSAFE_ISUPPORTS1(jsdThreadState, jsdIThreadState); 
    3458                 : 
    3459                 : NS_IMETHODIMP
    3460                 : jsdThreadState::GetJSDContext(JSDContext **_rval)
    3461                 : {
    3462                 :     *_rval = mCx;
    3463                 :     return NS_OK;
    3464                 : }
    3465                 : 
    3466                 : NS_IMETHODIMP
    3467                 : jsdThreadState::GetJSDThreadState(JSDThreadState **_rval)
    3468                 : {
    3469                 :     *_rval = mThreadState;
    3470                 :     return NS_OK;
    3471                 : }
    3472                 : 
    3473                 : NS_IMETHODIMP
    3474                 : jsdThreadState::GetFrameCount (PRUint32 *_rval)
    3475                 : {
    3476                 :     *_rval = JSD_GetCountOfStackFrames (mCx, mThreadState);
    3477                 :     return NS_OK;
    3478                 : }
    3479                 : 
    3480                 : NS_IMETHODIMP
    3481                 : jsdThreadState::GetTopFrame (jsdIStackFrame **_rval)
    3482                 : {
    3483                 :     JSDStackFrameInfo *sfi = JSD_GetStackFrame (mCx, mThreadState);
    3484                 :     
    3485                 :     *_rval = jsdStackFrame::FromPtr (mCx, mThreadState, sfi);
    3486                 :     return NS_OK;
    3487                 : }
    3488                 : 
    3489                 : NS_IMETHODIMP
    3490                 : jsdThreadState::GetPendingException(jsdIValue **_rval)
    3491                 : {
    3492                 :     JSDValue *jsdv = JSD_GetException (mCx, mThreadState);
    3493                 :     
    3494                 :     *_rval = jsdValue::FromPtr (mCx, jsdv);
    3495                 :     return NS_OK;
    3496                 : }
    3497                 : 
    3498                 : NS_IMETHODIMP
    3499                 : jsdThreadState::SetPendingException(jsdIValue *aException)
    3500                 : {
    3501                 :     JSDValue *jsdv;
    3502                 :     
    3503                 :     nsresult rv = aException->GetJSDValue (&jsdv);
    3504                 :     if (NS_FAILED(rv))
    3505                 :         return NS_ERROR_FAILURE;
    3506                 :     
    3507                 :     if (!JSD_SetException (mCx, mThreadState, jsdv))
    3508                 :         return NS_ERROR_FAILURE;
    3509                 : 
    3510                 :     return NS_OK;
    3511                 : }
    3512                 : 
    3513                 : #endif

Generated by: LCOV version 1.7