2001-09-20 04:02:59 +04:00
|
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
1998-03-28 05:44:41 +03:00
|
|
|
*
|
2001-09-20 04:02:59 +04:00
|
|
|
* The contents of this file are subject to the Netscape Public
|
1999-11-06 05:47:15 +03:00
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
2001-09-20 04:02:59 +04:00
|
|
|
* the License at http://www.mozilla.org/NPL/
|
1998-03-28 05:44:41 +03:00
|
|
|
*
|
1999-11-06 05:47:15 +03:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1998-03-28 05:44:41 +03:00
|
|
|
*
|
1999-11-06 05:47:15 +03:00
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
2001-09-20 04:02:59 +04:00
|
|
|
* The Initial Developer of the Original Code is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
1999-11-06 05:47:15 +03:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
2001-09-20 04:02:59 +04:00
|
|
|
* Contributor(s):
|
|
|
|
*/
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
/*
|
1998-11-05 11:57:24 +03:00
|
|
|
* JavaScript Debugging support - Script support
|
|
|
|
*/
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
#include "jsd.h"
|
|
|
|
|
|
|
|
/* Comment this out to disable (NT specific) dumping as we go */
|
|
|
|
/*
|
|
|
|
** #ifdef DEBUG
|
|
|
|
** #define JSD_DUMP 1
|
|
|
|
** #endif
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define NOT_SET_YET -1
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
1998-11-05 11:57:24 +03:00
|
|
|
void JSD_ASSERT_VALID_SCRIPT(JSDScript* jsdscript)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_ASSERT(jsdscript);
|
|
|
|
JS_ASSERT(jsdscript->script);
|
1998-03-28 05:44:41 +03:00
|
|
|
}
|
1998-11-05 11:57:24 +03:00
|
|
|
void JSD_ASSERT_VALID_EXEC_HOOK(JSDExecHook* jsdhook)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_ASSERT(jsdhook);
|
|
|
|
JS_ASSERT(jsdhook->hook);
|
1998-03-28 05:44:41 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
#ifdef LIVEWIRE
|
|
|
|
static JSBool
|
|
|
|
HasFileExtention(const char* name, const char* ext)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int len = strlen(ext);
|
|
|
|
const char* p = strrchr(name,'.');
|
|
|
|
if( !p )
|
|
|
|
return JS_FALSE;
|
|
|
|
p++;
|
|
|
|
for(i = 0; i < len; i++ )
|
|
|
|
{
|
|
|
|
JS_ASSERT(islower(ext[i]));
|
|
|
|
if( 0 == p[i] || tolower(p[i]) != ext[i] )
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
if( 0 != p[i] )
|
|
|
|
return JS_FALSE;
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
#endif /* LIVEWIRE */
|
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
static JSDScript*
|
1998-11-05 11:57:24 +03:00
|
|
|
_newJSDScript(JSDContext* jsdc,
|
1998-03-28 05:44:41 +03:00
|
|
|
JSContext *cx,
|
|
|
|
JSScript *script,
|
1998-11-05 11:57:24 +03:00
|
|
|
JSFunction* function)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
|
|
|
JSDScript* jsdscript;
|
1998-11-05 11:57:24 +03:00
|
|
|
uintN lineno;
|
|
|
|
const char* raw_filename;
|
|
|
|
|
|
|
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
/* these are inlined javascript: urls and we can't handle them now */
|
1998-11-05 11:57:24 +03:00
|
|
|
lineno = (uintN) JS_GetScriptBaseLineNumber(cx, script);
|
1998-03-28 05:44:41 +03:00
|
|
|
if( lineno == 0 )
|
|
|
|
return NULL;
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
jsdscript = (JSDScript*) calloc(1, sizeof(JSDScript));
|
1998-03-28 05:44:41 +03:00
|
|
|
if( ! jsdscript )
|
|
|
|
return NULL;
|
1998-11-05 11:57:24 +03:00
|
|
|
|
|
|
|
raw_filename = JS_GetScriptFilename(cx,script);
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_APPEND_LINK(&jsdscript->links, &jsdc->scripts);
|
1998-03-28 05:44:41 +03:00
|
|
|
jsdscript->jsdc = jsdc;
|
|
|
|
jsdscript->script = script;
|
|
|
|
jsdscript->function = function;
|
|
|
|
jsdscript->lineBase = lineno;
|
1998-11-05 11:57:24 +03:00
|
|
|
jsdscript->lineExtent = (uintN)NOT_SET_YET;
|
2001-04-20 07:45:39 +04:00
|
|
|
jsdscript->data = NULL;
|
1998-11-05 11:57:24 +03:00
|
|
|
#ifndef LIVEWIRE
|
|
|
|
jsdscript->url = (char*) jsd_BuildNormalizedURL(raw_filename);
|
|
|
|
#else
|
|
|
|
jsdscript->app = LWDBG_GetCurrentApp();
|
|
|
|
if( jsdscript->app && raw_filename )
|
|
|
|
{
|
|
|
|
jsdscript->url = jsdlw_BuildAppRelativeFilename(jsdscript->app, raw_filename);
|
|
|
|
if( function )
|
|
|
|
{
|
|
|
|
jsdscript->lwscript =
|
|
|
|
LWDBG_GetScriptOfFunction(jsdscript->app,
|
|
|
|
JS_GetFunctionName(function));
|
|
|
|
|
|
|
|
/* also, make sure this file is added to filelist if is .js file */
|
|
|
|
if( HasFileExtention(raw_filename,"js") ||
|
|
|
|
HasFileExtention(raw_filename,"sjs") )
|
|
|
|
{
|
|
|
|
jsdlw_PreLoadSource(jsdc, jsdscript->app, raw_filename, JS_FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
jsdscript->lwscript = LWDBG_GetCurrentTopLevelScript();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_INIT_CLIST(&jsdscript->hooks);
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
return jsdscript;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-11-05 11:57:24 +03:00
|
|
|
_destroyJSDScript(JSDContext* jsdc,
|
|
|
|
JSDScript* jsdscript)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
/* destroy all hooks */
|
|
|
|
jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_REMOVE_LINK(&jsdscript->links);
|
|
|
|
if(jsdscript->url)
|
|
|
|
free(jsdscript->url);
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
if(jsdscript)
|
|
|
|
free(jsdscript);
|
1998-03-28 05:44:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
|
|
|
|
#ifdef JSD_DUMP
|
2001-04-14 22:57:00 +04:00
|
|
|
#ifndef XP_WIN
|
|
|
|
void
|
|
|
|
OutputDebugString (char *buf)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "%s", buf);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
static void
|
1998-11-05 11:57:24 +03:00
|
|
|
_dumpJSDScript(JSDContext* jsdc, JSDScript* jsdscript, const char* leadingtext)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
|
|
|
const char* name;
|
|
|
|
const char* fun;
|
1998-11-05 11:57:24 +03:00
|
|
|
uintN base;
|
|
|
|
uintN extent;
|
1998-03-28 05:44:41 +03:00
|
|
|
char Buf[256];
|
|
|
|
|
|
|
|
name = jsd_GetScriptFilename(jsdc, jsdscript);
|
|
|
|
fun = jsd_GetScriptFunctionName(jsdc, jsdscript);
|
|
|
|
base = jsd_GetScriptBaseLineNumber(jsdc, jsdscript);
|
|
|
|
extent = jsd_GetScriptLineExtent(jsdc, jsdscript);
|
|
|
|
|
|
|
|
sprintf( Buf, "%sscript=%08X, %s, %s, %d-%d\n",
|
|
|
|
leadingtext,
|
|
|
|
(unsigned) jsdscript->script,
|
|
|
|
name ? name : "no URL",
|
|
|
|
fun ? fun : "no fun",
|
|
|
|
base, base + extent - 1 );
|
|
|
|
OutputDebugString( Buf );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1998-11-05 11:57:24 +03:00
|
|
|
_dumpJSDScriptList( JSDContext* jsdc )
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
|
|
|
JSDScript* iterp = NULL;
|
|
|
|
JSDScript* jsdscript = NULL;
|
|
|
|
|
|
|
|
OutputDebugString( "*** JSDScriptDump\n" );
|
|
|
|
while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
|
1998-11-05 11:57:24 +03:00
|
|
|
_dumpJSDScript( jsdc, jsdscript, " script: " );
|
1998-03-28 05:44:41 +03:00
|
|
|
}
|
|
|
|
#endif /* JSD_DUMP */
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
void
|
|
|
|
jsd_DestroyAllJSDScripts( JSDContext* jsdc )
|
|
|
|
{
|
|
|
|
JSDScript *jsdscript;
|
|
|
|
JSDScript *next;
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
|
|
|
|
|
|
|
for( jsdscript = (JSDScript*)jsdc->scripts.next;
|
|
|
|
jsdscript != (JSDScript*)&jsdc->scripts;
|
|
|
|
jsdscript = next )
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
|
|
|
next = (JSDScript*)jsdscript->links.next;
|
1998-11-05 11:57:24 +03:00
|
|
|
_destroyJSDScript( jsdc, jsdscript );
|
1998-03-28 05:44:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
JSDScript*
|
|
|
|
jsd_FindJSDScript( JSDContext* jsdc,
|
|
|
|
JSScript *script )
|
|
|
|
{
|
|
|
|
JSDScript *jsdscript;
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
|
|
|
|
|
|
|
for( jsdscript = (JSDScript *)jsdc->scripts.next;
|
|
|
|
jsdscript != (JSDScript *)&jsdc->scripts;
|
|
|
|
jsdscript = (JSDScript *)jsdscript->links.next )
|
|
|
|
{
|
1998-03-28 05:44:41 +03:00
|
|
|
if (jsdscript->script == script)
|
|
|
|
return jsdscript;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSDScript*
|
|
|
|
jsd_IterateScripts(JSDContext* jsdc, JSDScript **iterp)
|
|
|
|
{
|
|
|
|
JSDScript *jsdscript = *iterp;
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
|
|
|
|
|
|
|
if( !jsdscript )
|
|
|
|
jsdscript = (JSDScript *)jsdc->scripts.next;
|
|
|
|
if( jsdscript == (JSDScript *)&jsdc->scripts )
|
1998-03-28 05:44:41 +03:00
|
|
|
return NULL;
|
1998-11-05 11:57:24 +03:00
|
|
|
*iterp = (JSDScript*) jsdscript->links.next;
|
1998-03-28 05:44:41 +03:00
|
|
|
return jsdscript;
|
|
|
|
}
|
|
|
|
|
2001-04-20 07:45:39 +04:00
|
|
|
void *
|
|
|
|
jsd_SetScriptPrivate(JSDScript *jsdscript, void *data)
|
|
|
|
{
|
|
|
|
void *rval = jsdscript->data;
|
|
|
|
jsdscript->data = data;
|
|
|
|
return rval;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
jsd_GetScriptPrivate(JSDScript *jsdscript)
|
|
|
|
{
|
|
|
|
return jsdscript->data;
|
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JSBool
|
|
|
|
jsd_IsActiveScript(JSDContext* jsdc, JSDScript *jsdscript)
|
|
|
|
{
|
|
|
|
JSDScript *current;
|
|
|
|
|
|
|
|
JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc));
|
|
|
|
|
|
|
|
for( current = (JSDScript *)jsdc->scripts.next;
|
|
|
|
current != (JSDScript *)&jsdc->scripts;
|
|
|
|
current = (JSDScript *)current->links.next )
|
|
|
|
{
|
|
|
|
if(jsdscript == current)
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
const char*
|
|
|
|
jsd_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript)
|
|
|
|
{
|
|
|
|
return jsdscript->url;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char*
|
|
|
|
jsd_GetScriptFunctionName(JSDContext* jsdc, JSDScript *jsdscript)
|
|
|
|
{
|
|
|
|
if( ! jsdscript->function )
|
|
|
|
return NULL;
|
|
|
|
return JS_GetFunctionName(jsdscript->function);
|
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
uintN
|
1998-03-28 05:44:41 +03:00
|
|
|
jsd_GetScriptBaseLineNumber(JSDContext* jsdc, JSDScript *jsdscript)
|
|
|
|
{
|
|
|
|
return jsdscript->lineBase;
|
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
uintN
|
1998-03-28 05:44:41 +03:00
|
|
|
jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript)
|
|
|
|
{
|
2001-04-20 07:45:39 +04:00
|
|
|
if( NOT_SET_YET == (int)jsdscript->lineExtent )
|
1998-03-28 05:44:41 +03:00
|
|
|
jsdscript->lineExtent = JS_GetScriptLineExtent(jsdc->dumbContext, jsdscript->script);
|
|
|
|
return jsdscript->lineExtent;
|
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
jsuword
|
|
|
|
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, uintN line)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
#ifdef LIVEWIRE
|
|
|
|
if( jsdscript && jsdscript->lwscript )
|
|
|
|
{
|
|
|
|
uintN newline;
|
|
|
|
jsdlw_RawToProcessedLineNumber(jsdc, jsdscript, line, &newline);
|
|
|
|
if( line != newline )
|
|
|
|
line = newline;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return (jsuword) JS_LineNumberToPC(jsdc->dumbContext,
|
1998-03-28 05:44:41 +03:00
|
|
|
jsdscript->script, line );
|
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
uintN
|
|
|
|
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
uintN first = jsdscript->lineBase;
|
|
|
|
uintN last = first + jsd_GetScriptLineExtent(jsdc, jsdscript) - 1;
|
|
|
|
uintN line = JS_PCToLineNumber(jsdc->dumbContext,
|
1998-03-28 05:44:41 +03:00
|
|
|
jsdscript->script, (jsbytecode*)pc);
|
|
|
|
|
|
|
|
if( line < first )
|
|
|
|
return first;
|
|
|
|
if( line > last )
|
|
|
|
return last;
|
1998-11-05 11:57:24 +03:00
|
|
|
|
|
|
|
#ifdef LIVEWIRE
|
|
|
|
if( jsdscript && jsdscript->lwscript )
|
|
|
|
{
|
|
|
|
uintN newline;
|
|
|
|
jsdlw_ProcessedToRawLineNumber(jsdc, jsdscript, line, &newline);
|
|
|
|
line = newline;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
return line;
|
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JSBool
|
1998-03-28 05:44:41 +03:00
|
|
|
jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata)
|
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK();
|
1998-03-28 05:44:41 +03:00
|
|
|
jsdc->scriptHook = hook;
|
|
|
|
jsdc->scriptHookData = callerdata;
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_UNLOCK();
|
|
|
|
return JS_TRUE;
|
1998-03-28 05:44:41 +03:00
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JSBool
|
|
|
|
jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK();
|
|
|
|
if( hook )
|
|
|
|
*hook = jsdc->scriptHook;
|
|
|
|
if( callerdata )
|
|
|
|
*callerdata = jsdc->scriptHookData;
|
|
|
|
JSD_UNLOCK();
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
void JS_DLL_CALLBACK
|
1998-03-28 05:44:41 +03:00
|
|
|
jsd_NewScriptHookProc(
|
|
|
|
JSContext *cx,
|
|
|
|
const char *filename, /* URL this script loads from */
|
1998-11-05 11:57:24 +03:00
|
|
|
uintN lineno, /* line where this script starts */
|
1998-03-28 05:44:41 +03:00
|
|
|
JSScript *script,
|
|
|
|
JSFunction *fun,
|
|
|
|
void* callerdata )
|
|
|
|
{
|
|
|
|
JSDScript* jsdscript = NULL;
|
|
|
|
JSDContext* jsdc = (JSDContext*) callerdata;
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_ScriptHookProc hook;
|
|
|
|
void* hookData;
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
|
|
|
return;
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
#ifdef LIVEWIRE
|
|
|
|
if( 1 == lineno )
|
|
|
|
jsdlw_PreLoadSource(jsdc, LWDBG_GetCurrentApp(), filename, JS_TRUE );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
JSD_LOCK_SCRIPTS(jsdc);
|
|
|
|
jsdscript = _newJSDScript(jsdc, cx, script, fun);
|
|
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
1998-03-28 05:44:41 +03:00
|
|
|
if( ! jsdscript )
|
|
|
|
return;
|
1998-11-05 11:57:24 +03:00
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
#ifdef JSD_DUMP
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK_SCRIPTS(jsdc);
|
|
|
|
_dumpJSDScript(jsdc, jsdscript, "***NEW Script: ");
|
|
|
|
_dumpJSDScriptList( jsdc );
|
|
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
1998-03-28 05:44:41 +03:00
|
|
|
#endif /* JSD_DUMP */
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
/* local in case jsdc->scriptHook gets cleared on another thread */
|
|
|
|
JSD_LOCK();
|
|
|
|
hook = jsdc->scriptHook;
|
|
|
|
hookData = jsdc->scriptHookData;
|
|
|
|
JSD_UNLOCK();
|
|
|
|
|
|
|
|
if( hook )
|
|
|
|
hook(jsdc, jsdscript, JS_TRUE, hookData);
|
1998-03-28 05:44:41 +03:00
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
void JS_DLL_CALLBACK
|
1998-03-28 05:44:41 +03:00
|
|
|
jsd_DestroyScriptHookProc(
|
|
|
|
JSContext *cx,
|
|
|
|
JSScript *script,
|
|
|
|
void* callerdata )
|
|
|
|
{
|
|
|
|
JSDScript* jsdscript = NULL;
|
|
|
|
JSDContext* jsdc = (JSDContext*) callerdata;
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_ScriptHookProc hook;
|
|
|
|
void* hookData;
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
JSD_ASSERT_VALID_CONTEXT(jsdc);
|
1998-11-05 11:57:24 +03:00
|
|
|
|
|
|
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
|
|
|
return;
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK_SCRIPTS(jsdc);
|
|
|
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
|
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
if( ! jsdscript )
|
|
|
|
return;
|
1998-11-05 11:57:24 +03:00
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
#ifdef JSD_DUMP
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK_SCRIPTS(jsdc);
|
|
|
|
_dumpJSDScript(jsdc, jsdscript, "***DESTROY Script: ");
|
|
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
1998-03-28 05:44:41 +03:00
|
|
|
#endif /* JSD_DUMP */
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
/* local in case hook gets cleared on another thread */
|
|
|
|
JSD_LOCK();
|
|
|
|
hook = jsdc->scriptHook;
|
|
|
|
hookData = jsdc->scriptHookData;
|
|
|
|
JSD_UNLOCK();
|
|
|
|
|
|
|
|
if( hook )
|
|
|
|
hook(jsdc, jsdscript, JS_FALSE, hookData);
|
|
|
|
|
|
|
|
JSD_LOCK_SCRIPTS(jsdc);
|
|
|
|
_destroyJSDScript(jsdc, jsdscript);
|
|
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
#ifdef JSD_DUMP
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK_SCRIPTS(jsdc);
|
|
|
|
_dumpJSDScriptList(jsdc);
|
|
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
1998-03-28 05:44:41 +03:00
|
|
|
#endif /* JSD_DUMP */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************/
|
|
|
|
|
|
|
|
static JSDExecHook*
|
1998-11-05 11:57:24 +03:00
|
|
|
_findHook(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
|
|
|
JSDExecHook* jsdhook;
|
1998-11-05 11:57:24 +03:00
|
|
|
JSCList* list = &jsdscript->hooks;
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
for( jsdhook = (JSDExecHook*)list->next;
|
1998-03-28 05:44:41 +03:00
|
|
|
jsdhook != (JSDExecHook*)list;
|
1998-11-05 11:57:24 +03:00
|
|
|
jsdhook = (JSDExecHook*)jsdhook->links.next )
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
|
|
|
if (jsdhook->pc == pc)
|
|
|
|
return jsdhook;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
static JSBool
|
|
|
|
_isActiveHook(JSDContext* jsdc, JSScript *script, JSDExecHook* jsdhook)
|
|
|
|
{
|
|
|
|
JSDExecHook* current;
|
|
|
|
JSCList* list;
|
|
|
|
JSDScript* jsdscript;
|
|
|
|
|
|
|
|
JSD_LOCK_SCRIPTS(jsdc);
|
|
|
|
jsdscript = jsd_FindJSDScript(jsdc, script);
|
|
|
|
if( ! jsdscript)
|
|
|
|
{
|
|
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
list = &jsdscript->hooks;
|
|
|
|
|
|
|
|
for( current = (JSDExecHook*)list->next;
|
|
|
|
current != (JSDExecHook*)list;
|
|
|
|
current = (JSDExecHook*)current->links.next )
|
|
|
|
{
|
|
|
|
if(current == jsdhook)
|
|
|
|
{
|
|
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
JSD_UNLOCK_SCRIPTS(jsdc);
|
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
JSTrapStatus JS_DLL_CALLBACK
|
1998-03-28 05:44:41 +03:00
|
|
|
jsd_TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
|
|
|
void *closure)
|
|
|
|
{
|
2001-05-14 01:07:03 +04:00
|
|
|
JSDExecHook* jsdhook = (JSDExecHook*) JSVAL_TO_PRIVATE(((jsval)closure));
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_ExecutionHookProc hook;
|
|
|
|
void* hookData;
|
1998-03-28 05:44:41 +03:00
|
|
|
JSDContext* jsdc;
|
1998-11-05 11:57:24 +03:00
|
|
|
JSDScript* jsdscript;
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK();
|
|
|
|
|
|
|
|
if( NULL == (jsdc = jsd_JSDContextForJSContext(cx)) ||
|
|
|
|
! _isActiveHook(jsdc, script, jsdhook) )
|
|
|
|
{
|
|
|
|
JSD_UNLOCK();
|
1998-03-28 05:44:41 +03:00
|
|
|
return JSTRAP_CONTINUE;
|
1998-11-05 11:57:24 +03:00
|
|
|
}
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
JSD_ASSERT_VALID_EXEC_HOOK(jsdhook);
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_ASSERT(jsdhook->pc == (jsuword)pc);
|
|
|
|
JS_ASSERT(jsdhook->jsdscript->script == script);
|
|
|
|
JS_ASSERT(jsdhook->jsdscript->jsdc == jsdc);
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
hook = jsdhook->hook;
|
|
|
|
hookData = jsdhook->callerdata;
|
|
|
|
jsdscript = jsdhook->jsdscript;
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
/* do not use jsdhook-> after this point */
|
|
|
|
JSD_UNLOCK();
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
if( ! jsdc || ! jsdc->inited )
|
|
|
|
return JSTRAP_CONTINUE;
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
if( JSD_IS_DANGEROUS_THREAD(jsdc) )
|
|
|
|
return JSTRAP_CONTINUE;
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
#ifdef LIVEWIRE
|
|
|
|
if( ! jsdlw_UserCodeAtPC(jsdc, jsdscript, (jsuword)pc) )
|
|
|
|
return JSTRAP_CONTINUE;
|
|
|
|
#endif
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
return jsd_CallExecutionHook(jsdc, cx, JSD_HOOK_BREAKPOINT,
|
|
|
|
hook, hookData, rval);
|
1998-03-28 05:44:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JSBool
|
|
|
|
jsd_SetExecutionHook(JSDContext* jsdc,
|
|
|
|
JSDScript* jsdscript,
|
1998-11-05 11:57:24 +03:00
|
|
|
jsuword pc,
|
1998-03-28 05:44:41 +03:00
|
|
|
JSD_ExecutionHookProc hook,
|
|
|
|
void* callerdata)
|
|
|
|
{
|
|
|
|
JSDExecHook* jsdhook;
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK();
|
1998-03-28 05:44:41 +03:00
|
|
|
if( ! hook )
|
1998-11-05 11:57:24 +03:00
|
|
|
{
|
|
|
|
jsd_ClearExecutionHook(jsdc, jsdscript, pc);
|
|
|
|
JSD_UNLOCK();
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
jsdhook = _findHook(jsdc, jsdscript, pc);
|
1998-03-28 05:44:41 +03:00
|
|
|
if( jsdhook )
|
|
|
|
{
|
|
|
|
jsdhook->hook = hook;
|
|
|
|
jsdhook->callerdata = callerdata;
|
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
/* else... */
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
jsdhook = (JSDExecHook*)calloc(1, sizeof(JSDExecHook));
|
1998-03-28 05:44:41 +03:00
|
|
|
if( ! jsdhook )
|
|
|
|
return JS_FALSE;
|
|
|
|
jsdhook->jsdscript = jsdscript;
|
|
|
|
jsdhook->pc = pc;
|
|
|
|
jsdhook->hook = hook;
|
|
|
|
jsdhook->callerdata = callerdata;
|
|
|
|
|
|
|
|
if( ! JS_SetTrap(jsdc->dumbContext, jsdscript->script,
|
2001-05-14 01:07:03 +04:00
|
|
|
(jsbytecode*)pc, jsd_TrapHandler,
|
|
|
|
(void*) PRIVATE_TO_JSVAL(jsdhook)) )
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
free(jsdhook);
|
1998-03-28 05:44:41 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_APPEND_LINK(&jsdhook->links, &jsdscript->hooks);
|
|
|
|
JSD_UNLOCK();
|
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool
|
|
|
|
jsd_ClearExecutionHook(JSDContext* jsdc,
|
|
|
|
JSDScript* jsdscript,
|
1998-11-05 11:57:24 +03:00
|
|
|
jsuword pc)
|
1998-03-28 05:44:41 +03:00
|
|
|
{
|
|
|
|
JSDExecHook* jsdhook;
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK();
|
|
|
|
|
|
|
|
jsdhook = _findHook(jsdc, jsdscript, pc);
|
1998-03-28 05:44:41 +03:00
|
|
|
if( ! jsdhook )
|
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_ASSERT(0);
|
|
|
|
JSD_UNLOCK();
|
1998-03-28 05:44:41 +03:00
|
|
|
return JS_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JS_ClearTrap(jsdc->dumbContext, jsdscript->script,
|
|
|
|
(jsbytecode*)pc, NULL, NULL );
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_REMOVE_LINK(&jsdhook->links);
|
|
|
|
free(jsdhook);
|
1998-03-28 05:44:41 +03:00
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_UNLOCK();
|
1998-03-28 05:44:41 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool
|
|
|
|
jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript)
|
|
|
|
{
|
|
|
|
JSDExecHook* jsdhook;
|
1998-11-05 11:57:24 +03:00
|
|
|
JSCList* list = &jsdscript->hooks;
|
|
|
|
|
|
|
|
JSD_LOCK();
|
1998-03-28 05:44:41 +03:00
|
|
|
|
|
|
|
while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) )
|
|
|
|
{
|
1998-11-05 11:57:24 +03:00
|
|
|
JS_REMOVE_LINK(&jsdhook->links);
|
|
|
|
free(jsdhook);
|
1998-03-28 05:44:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script);
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_UNLOCK();
|
|
|
|
|
1998-03-28 05:44:41 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
JSBool
|
|
|
|
jsd_ClearAllExecutionHooks(JSDContext* jsdc)
|
|
|
|
{
|
|
|
|
JSDScript* jsdscript;
|
|
|
|
JSDScript* iterp = NULL;
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_LOCK();
|
1998-03-28 05:44:41 +03:00
|
|
|
while( NULL != (jsdscript = jsd_IterateScripts(jsdc, &iterp)) )
|
|
|
|
jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript);
|
1998-11-05 11:57:24 +03:00
|
|
|
JSD_UNLOCK();
|
1998-03-28 05:44:41 +03:00
|
|
|
return JS_TRUE;
|
|
|
|
}
|
|
|
|
|
1998-11-05 11:57:24 +03:00
|
|
|
void
|
|
|
|
jsd_ScriptCreated(JSDContext* jsdc,
|
|
|
|
JSContext *cx,
|
|
|
|
const char *filename, /* URL this script loads from */
|
|
|
|
uintN lineno, /* line where this script starts */
|
|
|
|
JSScript *script,
|
|
|
|
JSFunction *fun)
|
|
|
|
{
|
|
|
|
jsd_NewScriptHookProc(cx, filename, lineno, script, fun, jsdc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
jsd_ScriptDestroyed(JSDContext* jsdc,
|
|
|
|
JSContext *cx,
|
|
|
|
JSScript *script)
|
|
|
|
{
|
|
|
|
jsd_DestroyScriptHookProc(cx, script, jsdc);
|
|
|
|
}
|