jsd.h
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Header for JavaScript Debugging support - Internal ONLY declarations
*/
#ifndef jsd_h___
#define jsd_h___
/*
* NOTE: This is a *private* header file and should only be included by
* the sources in js/jsd. Defining EXPORT_JSD_API in an outside module
* using jsd would be bad.
*/
#define EXPORT_JSD_API 1 /* if used, must be set before include of jsdebug.h */
/*
* These can be controled by the makefile, but this allows a place to set
* the values always used in the mozilla client, but perhaps done differently
* in other embeddings.
*/
#ifdef MOZILLA_CLIENT
#define JSD_THREADSAFE 1
/* define JSD_HAS_DANGEROUS_THREAD 1 */
#define JSD_USE_NSPR_LOCKS 1
#endif /* MOZILLA_CLIENT */
#include "jsapi.h"
#include "jshash.h"
#include "jsclist.h"
#include "jsdebug.h"
#include "js/OldDebugAPI.h"
#include "jsd_lock.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define JSD_MAJOR_VERSION 1
#define JSD_MINOR_VERSION 1
/***************************************************************************/
/* handy macros */
#undef CHECK_BIT_FLAG
#define CHECK_BIT_FLAG(f,b) ((f)&(b))
#undef SET_BIT_FLAG
#define SET_BIT_FLAG(f,b) ((f)|=(b))
#undef CLEAR_BIT_FLAG
#define CLEAR_BIT_FLAG(f,b) ((f)&=(~(b)))
#define JSD_IS_DEBUG_ENABLED(jsdc,jsdscript) \
(!(((jsdc->flags & JSD_DEBUG_WHEN_SET) ? 1 : 0) ^ \
((jsdscript->flags & JSD_SCRIPT_DEBUG_BIT) ? 1 : 0)))
#define JSD_IS_PROFILE_ENABLED(jsdc,jsdscript) \
((jsdc->flags & JSD_COLLECT_PROFILE_DATA) && \
(!(((jsdc->flags & JSD_PROFILE_WHEN_SET) ? 1 : 0) ^ \
((jsdscript->flags & JSD_SCRIPT_PROFILE_BIT) ? 1 : 0))))
/***************************************************************************/
/* These are not exposed in jsdebug.h - typedef here for consistency */
typedef struct JSDExecHook JSDExecHook;
typedef struct JSDAtom JSDAtom;
typedef struct JSDProfileData JSDProfileData;
/***************************************************************************/
/* Our structures */
/*
* XXX What I'm calling a JSDContext is really more of a JSDTaskState.
*/
struct JSDContext
{
JSCList links; /* we are part of a JSCList */
bool inited;
void* data;
uint32_t flags;
JSD_ScriptHookProc scriptHook;
void* scriptHookData;
JSD_ExecutionHookProc interruptHook;
void* interruptHookData;
JSRuntime* jsrt;
JSD_ErrorReporter errorReporter;
void* errorReporterData;
JSCList threadsStates;
JSD_ExecutionHookProc debugBreakHook;
void* debugBreakHookData;
JSD_ExecutionHookProc debuggerHook;
void* debuggerHookData;
JSD_ExecutionHookProc throwHook;
void* throwHookData;
JSD_CallHookProc functionHook;
void* functionHookData;
JSD_CallHookProc toplevelHook;
void* toplevelHookData;
JSObject* glob;
JSD_UserCallbacks userCallbacks;
void* user;
JSCList scripts;
JSHashTable* scriptsTable;
JSCList sources;
JSCList removedSources;
unsigned sourceAlterCount;
JSHashTable* atoms;
JSCList objectsList;
JSHashTable* objectsTable;
JSDProfileData* callingFunctionPData;
int64_t lastReturnTime;
#ifdef JSD_THREADSAFE
JSDStaticLock* scriptsLock;
JSDStaticLock* sourceTextLock;
JSDStaticLock* objectsLock;
JSDStaticLock* atomsLock;
JSDStaticLock* threadStatesLock;
#endif /* JSD_THREADSAFE */
#ifdef JSD_HAS_DANGEROUS_THREAD
void* dangerousThread;
#endif /* JSD_HAS_DANGEROUS_THREAD */
};
struct JSDScript
{
JSCList links; /* we are part of a JSCList */
JSDContext* jsdc; /* JSDContext for this jsdscript */
JSScript* script; /* script we are wrapping */
unsigned lineBase; /* we cache this */
unsigned lineExtent; /* we cache this */
JSCList hooks; /* JSCList of JSDExecHooks for this script */
char* url;
uint32_t flags;
void* data;
JSDProfileData *profileData;
};
struct JSDProfileData
{
JSDProfileData* caller;
int64_t lastCallStart;
int64_t runningTime;
unsigned callCount;
unsigned recurseDepth;
unsigned maxRecurseDepth;
double minExecutionTime;
double maxExecutionTime;
double totalExecutionTime;
double minOwnExecutionTime;
double maxOwnExecutionTime;
double totalOwnExecutionTime;
};
struct JSDSourceText
{
JSCList links; /* we are part of a JSCList */
char* url;
char* text;
unsigned textLength;
unsigned textSpace;
bool dirty;
JSDSourceStatus status;
unsigned alterCount;
bool doingEval;
};
struct JSDExecHook
{
JSCList links; /* we are part of a JSCList */
JSDScript* jsdscript;
uintptr_t pc;
JSD_ExecutionHookProc hook;
void* callerdata;
};
#define TS_HAS_DISABLED_FRAME 0x01
struct JSDThreadState
{
JSCList links; /* we are part of a JSCList */
JSContext* context;
void* thread;
JSCList stack;
unsigned stackDepth;
unsigned flags;
};
struct JSDStackFrameInfo
{
JSCList links; /* we are part of a JSCList */
JSDThreadState* jsdthreadstate;
JSDScript* jsdscript;
uintptr_t pc;
bool isConstructing;
JSAbstractFramePtr frame;
};
#define GOT_PROTO ((short) (1 << 0))
#define GOT_PROPS ((short) (1 << 1))
#define GOT_PARENT ((short) (1 << 2))
#define GOT_CTOR ((short) (1 << 3))
struct JSDValue
{
jsval val;
int nref;
JSCList props;
JSString* string;
JSString* funName;
const char* className;
JSDValue* proto;
JSDValue* parent;
JSDValue* ctor;
unsigned flags;
};
struct JSDProperty
{
JSCList links; /* we are part of a JSCList */
int nref;
JSDValue* val;
JSDValue* name;
JSDValue* alias;
unsigned flags;
};
struct JSDAtom
{
char* str; /* must be first element in struct for compare */
int refcount;
};
struct JSDObject
{
JSCList links; /* we are part of a JSCList */
JSObject* obj;
JSDAtom* newURL;
unsigned newLineno;
JSDAtom* ctorURL;
unsigned ctorLineno;
JSDAtom* ctorName;
};
/***************************************************************************/
/* Code validation support */
#ifdef DEBUG
extern void JSD_ASSERT_VALID_CONTEXT(JSDContext* jsdc);
extern void JSD_ASSERT_VALID_SCRIPT(JSDScript* jsdscript);
extern void JSD_ASSERT_VALID_SOURCE_TEXT(JSDSourceText* jsdsrc);
extern void JSD_ASSERT_VALID_THREAD_STATE(JSDThreadState* jsdthreadstate);
extern void JSD_ASSERT_VALID_STACK_FRAME(JSDStackFrameInfo* jsdframe);
extern void JSD_ASSERT_VALID_EXEC_HOOK(JSDExecHook* jsdhook);
extern void JSD_ASSERT_VALID_VALUE(JSDValue* jsdval);
extern void JSD_ASSERT_VALID_PROPERTY(JSDProperty* jsdprop);
extern void JSD_ASSERT_VALID_OBJECT(JSDObject* jsdobj);
#else
#define JSD_ASSERT_VALID_CONTEXT(x) ((void)0)
#define JSD_ASSERT_VALID_SCRIPT(x) ((void)0)
#define JSD_ASSERT_VALID_SOURCE_TEXT(x) ((void)0)
#define JSD_ASSERT_VALID_THREAD_STATE(x)((void)0)
#define JSD_ASSERT_VALID_STACK_FRAME(x) ((void)0)
#define JSD_ASSERT_VALID_EXEC_HOOK(x) ((void)0)
#define JSD_ASSERT_VALID_VALUE(x) ((void)0)
#define JSD_ASSERT_VALID_PROPERTY(x) ((void)0)
#define JSD_ASSERT_VALID_OBJECT(x) ((void)0)
#endif
/***************************************************************************/
/* higher level functions */
extern JSDContext*
jsd_DebuggerOnForUser(JSRuntime* jsrt,
JSD_UserCallbacks* callbacks,
void* user,
JSObject* scopeobj);
extern JSDContext*
jsd_DebuggerOn(void);
extern void
jsd_DebuggerOff(JSDContext* jsdc);
extern void
jsd_DebuggerPause(JSDContext* jsdc, bool forceAllHooksOff);
extern void
jsd_DebuggerUnpause(JSDContext* jsdc);
extern void
jsd_SetUserCallbacks(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user);
extern JSDContext*
jsd_JSDContextForJSContext(JSContext* context);
extern void*
jsd_SetContextPrivate(JSDContext* jsdc, void *data);
extern void*
jsd_GetContextPrivate(JSDContext* jsdc);
extern void
jsd_ClearAllProfileData(JSDContext* jsdc);
extern bool
jsd_SetErrorReporter(JSDContext* jsdc,
JSD_ErrorReporter reporter,
void* callerdata);
extern bool
jsd_GetErrorReporter(JSDContext* jsdc,
JSD_ErrorReporter* reporter,
void** callerdata);
/***************************************************************************/
/* Script functions */
extern bool
jsd_InitScriptManager(JSDContext *jsdc);
extern void
jsd_DestroyScriptManager(JSDContext* jsdc);
extern JSDScript*
jsd_FindJSDScript(JSDContext* jsdc,
JSScript *script);
extern JSDScript*
jsd_FindOrCreateJSDScript(JSDContext *jsdc,
JSContext *cx,
JSScript *script,
JSAbstractFramePtr frame);
extern JSDProfileData*
jsd_GetScriptProfileData(JSDContext* jsdc, JSDScript *script);
extern uint32_t
jsd_GetScriptFlags(JSDContext *jsdc, JSDScript *script);
extern void
jsd_SetScriptFlags(JSDContext *jsdc, JSDScript *script, uint32_t flags);
extern unsigned
jsd_GetScriptCallCount(JSDContext* jsdc, JSDScript *script);
extern unsigned
jsd_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script);
extern double
jsd_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script);
extern double
jsd_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script);
extern double
jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script);
extern double
jsd_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
extern double
jsd_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
extern double
jsd_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
extern void
jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script);
extern JSScript *
jsd_GetJSScript (JSDContext *jsdc, JSDScript *script);
extern JSFunction *
jsd_GetJSFunction (JSDContext *jsdc, JSDScript *script);
extern JSDScript*
jsd_IterateScripts(JSDContext* jsdc, JSDScript **iterp);
extern void *
jsd_SetScriptPrivate (JSDScript *jsdscript, void *data);
extern void *
jsd_GetScriptPrivate (JSDScript *jsdscript);
extern bool
jsd_IsActiveScript(JSDContext* jsdc, JSDScript *jsdscript);
extern const char*
jsd_GetScriptFilename(JSDContext* jsdc, JSDScript *jsdscript);
extern JSString*
jsd_GetScriptFunctionId(JSDContext* jsdc, JSDScript *jsdscript);
extern unsigned
jsd_GetScriptBaseLineNumber(JSDContext* jsdc, JSDScript *jsdscript);
extern unsigned
jsd_GetScriptLineExtent(JSDContext* jsdc, JSDScript *jsdscript);
extern bool
jsd_SetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc hook, void* callerdata);
extern bool
jsd_GetScriptHook(JSDContext* jsdc, JSD_ScriptHookProc* hook, void** callerdata);
extern uintptr_t
jsd_GetClosestPC(JSDContext* jsdc, JSDScript* jsdscript, unsigned line);
extern unsigned
jsd_GetClosestLine(JSDContext* jsdc, JSDScript* jsdscript, uintptr_t pc);
extern bool
jsd_GetLinePCs(JSDContext* jsdc, JSDScript* jsdscript,
unsigned startLine, unsigned maxLines,
unsigned* count, unsigned** lines, uintptr_t** pcs);
extern void
jsd_NewScriptHookProc(
JSContext *cx,
const char *filename, /* URL this script loads from */
unsigned lineno, /* line where this script starts */
JSScript *script,
JSFunction *fun,
void* callerdata);
extern void
jsd_DestroyScriptHookProc(
JSFreeOp *fop,
JSScript *script,
void* callerdata);
/* Script execution hook functions */
extern bool
jsd_SetExecutionHook(JSDContext* jsdc,
JSDScript* jsdscript,
uintptr_t pc,
JSD_ExecutionHookProc hook,
void* callerdata);
extern bool
jsd_ClearExecutionHook(JSDContext* jsdc,
JSDScript* jsdscript,
uintptr_t pc);
extern bool
jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript);
extern bool
jsd_ClearAllExecutionHooks(JSDContext* jsdc);
extern void
jsd_ScriptCreated(JSDContext* jsdc,
JSContext *cx,
const char *filename, /* URL this script loads from */
unsigned lineno, /* line where this script starts */
JSScript *script,
JSFunction *fun);
extern void
jsd_ScriptDestroyed(JSDContext* jsdc,
JSFreeOp *fop,
JSScript *script);
/***************************************************************************/
/* Source Text functions */
extern JSDSourceText*
jsd_IterateSources(JSDContext* jsdc, JSDSourceText **iterp);
extern JSDSourceText*
jsd_FindSourceForURL(JSDContext* jsdc, const char* url);
extern const char*
jsd_GetSourceURL(JSDContext* jsdc, JSDSourceText* jsdsrc);
extern bool
jsd_GetSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc,
const char** ppBuf, int* pLen);
extern void
jsd_ClearSourceText(JSDContext* jsdc, JSDSourceText* jsdsrc);
extern JSDSourceStatus
jsd_GetSourceStatus(JSDContext* jsdc, JSDSourceText* jsdsrc);
extern bool
jsd_IsSourceDirty(JSDContext* jsdc, JSDSourceText* jsdsrc);
extern void
jsd_SetSourceDirty(JSDContext* jsdc, JSDSourceText* jsdsrc, bool dirty);
extern unsigned
jsd_GetSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc);
extern unsigned
jsd_IncrementSourceAlterCount(JSDContext* jsdc, JSDSourceText* jsdsrc);
extern JSDSourceText*
jsd_NewSourceText(JSDContext* jsdc, const char* url);
extern JSDSourceText*
jsd_AppendSourceText(JSDContext* jsdc,
JSDSourceText* jsdsrc,
const char* text, /* *not* zero terminated */
size_t length,
JSDSourceStatus status);
extern JSDSourceText*
jsd_AppendUCSourceText(JSDContext* jsdc,
JSDSourceText* jsdsrc,
const jschar* text, /* *not* zero terminated */
size_t length,
JSDSourceStatus status);
/* convienence function for adding complete source of url in one call */
extern bool
jsd_AddFullSourceText(JSDContext* jsdc,
const char* text, /* *not* zero terminated */
size_t length,
const char* url);
extern void
jsd_DestroyAllSources(JSDContext* jsdc);
extern char*
jsd_BuildNormalizedURL(const char* url_string);
extern void
jsd_StartingEvalUsingFilename(JSDContext* jsdc, const char* url);
extern void
jsd_FinishedEvalUsingFilename(JSDContext* jsdc, const char* url);
/***************************************************************************/
/* Interrupt Hook functions */
extern bool
jsd_SetInterruptHook(JSDContext* jsdc,
JSD_ExecutionHookProc hook,
void* callerdata);
extern bool
jsd_ClearInterruptHook(JSDContext* jsdc);
extern bool
jsd_EnableSingleStepInterrupts(JSDContext* jsdc,
JSDScript* jsdscript,
bool enable);
extern bool
jsd_SetDebugBreakHook(JSDContext* jsdc,
JSD_ExecutionHookProc hook,
void* callerdata);
extern bool
jsd_ClearDebugBreakHook(JSDContext* jsdc);
extern bool
jsd_SetDebuggerHook(JSDContext* jsdc,
JSD_ExecutionHookProc hook,
void* callerdata);
extern bool
jsd_ClearDebuggerHook(JSDContext* jsdc);
extern JSTrapStatus
jsd_CallExecutionHook(JSDContext* jsdc,
JSContext* cx,
unsigned type,
JSD_ExecutionHookProc hook,
void* hookData,
jsval* rval);
extern bool
jsd_CallCallHook (JSDContext* jsdc,
JSContext* cx,
unsigned type,
JSD_CallHookProc hook,
void* hookData);
extern bool
jsd_SetThrowHook(JSDContext* jsdc,
JSD_ExecutionHookProc hook,
void* callerdata);
extern bool
jsd_ClearThrowHook(JSDContext* jsdc);
extern JSTrapStatus
jsd_DebuggerHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
jsval *rval, void *closure);
extern JSTrapStatus
jsd_ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
jsval *rval, void *closure);
extern bool
jsd_SetFunctionHook(JSDContext* jsdc,
JSD_CallHookProc hook,
void* callerdata);
extern bool
jsd_ClearFunctionHook(JSDContext* jsdc);
extern bool
jsd_SetTopLevelHook(JSDContext* jsdc,
JSD_CallHookProc hook,
void* callerdata);
extern bool
jsd_ClearTopLevelHook(JSDContext* jsdc);
/***************************************************************************/
/* Stack Frame functions */
extern unsigned
jsd_GetCountOfStackFrames(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
extern JSDStackFrameInfo*
jsd_GetStackFrame(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
extern JSContext*
jsd_GetJSContext(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
extern JSDStackFrameInfo*
jsd_GetCallingStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSDScript*
jsd_GetScriptForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern uintptr_t
jsd_GetPCForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSDValue*
jsd_GetCallObjectForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSDValue*
jsd_GetScopeChainForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern bool
jsd_IsStackFrameDebugger(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern bool
jsd_IsStackFrameConstructing(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSDValue*
jsd_GetThisForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSString*
jsd_GetIdForStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSDThreadState*
jsd_NewThreadState(JSDContext* jsdc, JSContext *cx);
extern void
jsd_DestroyThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
extern bool
jsd_EvaluateUCScriptInStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe,
const jschar *bytes, unsigned length,
const char *filename, unsigned lineno,
bool eatExceptions, JS::MutableHandleValue rval);
extern bool
jsd_EvaluateScriptInStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe,
const char *bytes, unsigned length,
const char *filename, unsigned lineno,
bool eatExceptions, JS::MutableHandleValue rval);
extern JSString*
jsd_ValToStringInStackFrame(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe,
jsval val);
extern bool
jsd_IsValidThreadState(JSDContext* jsdc,
JSDThreadState* jsdthreadstate);
extern bool
jsd_IsValidFrameInThreadState(JSDContext* jsdc,
JSDThreadState* jsdthreadstate,
JSDStackFrameInfo* jsdframe);
extern JSDValue*
jsd_GetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate);
extern bool
jsd_SetException(JSDContext* jsdc, JSDThreadState* jsdthreadstate,
JSDValue* jsdval);
/***************************************************************************/
/* Locking support */
/* protos are in js_lock.h for:
* jsd_CreateLock
* jsd_Lock
* jsd_Unlock
* jsd_IsLocked
* jsd_CurrentThread
*/
#ifdef JSD_THREADSAFE
/* the system-wide lock */
extern JSDStaticLock* _jsd_global_lock;
#define JSD_LOCK() \
JS_BEGIN_MACRO \
if(!_jsd_global_lock) \
_jsd_global_lock = jsd_CreateLock(); \
JS_ASSERT(_jsd_global_lock); \
jsd_Lock(_jsd_global_lock); \
JS_END_MACRO
#define JSD_UNLOCK() \
JS_BEGIN_MACRO \
JS_ASSERT(_jsd_global_lock); \
jsd_Unlock(_jsd_global_lock); \
JS_END_MACRO
/* locks for the subsystems of a given context */
#define JSD_INIT_LOCKS(jsdc) \
( (nullptr != (jsdc->scriptsLock = jsd_CreateLock())) && \
(nullptr != (jsdc->sourceTextLock = jsd_CreateLock())) && \
(nullptr != (jsdc->atomsLock = jsd_CreateLock())) && \
(nullptr != (jsdc->objectsLock = jsd_CreateLock())) && \
(nullptr != (jsdc->threadStatesLock = jsd_CreateLock())) )
#define JSD_LOCK_SCRIPTS(jsdc) jsd_Lock(jsdc->scriptsLock)
#define JSD_UNLOCK_SCRIPTS(jsdc) jsd_Unlock(jsdc->scriptsLock)
#define JSD_LOCK_SOURCE_TEXT(jsdc) jsd_Lock(jsdc->sourceTextLock)
#define JSD_UNLOCK_SOURCE_TEXT(jsdc) jsd_Unlock(jsdc->sourceTextLock)
#define JSD_LOCK_ATOMS(jsdc) jsd_Lock(jsdc->atomsLock)
#define JSD_UNLOCK_ATOMS(jsdc) jsd_Unlock(jsdc->atomsLock)
#define JSD_LOCK_OBJECTS(jsdc) jsd_Lock(jsdc->objectsLock)
#define JSD_UNLOCK_OBJECTS(jsdc) jsd_Unlock(jsdc->objectsLock)
#define JSD_LOCK_THREADSTATES(jsdc) jsd_Lock(jsdc->threadStatesLock)
#define JSD_UNLOCK_THREADSTATES(jsdc) jsd_Unlock(jsdc->threadStatesLock)
#else /* !JSD_THREADSAFE */
#define JSD_LOCK() ((void)0)
#define JSD_UNLOCK() ((void)0)
#define JSD_INIT_LOCKS(jsdc) 1
#define JSD_LOCK_SCRIPTS(jsdc) ((void)0)
#define JSD_UNLOCK_SCRIPTS(jsdc) ((void)0)
#define JSD_LOCK_SOURCE_TEXT(jsdc) ((void)0)
#define JSD_UNLOCK_SOURCE_TEXT(jsdc) ((void)0)
#define JSD_LOCK_ATOMS(jsdc) ((void)0)
#define JSD_UNLOCK_ATOMS(jsdc) ((void)0)
#define JSD_LOCK_OBJECTS(jsdc) ((void)0)
#define JSD_UNLOCK_OBJECTS(jsdc) ((void)0)
#define JSD_LOCK_THREADSTATES(jsdc) ((void)0)
#define JSD_UNLOCK_THREADSTATES(jsdc) ((void)0)
#endif /* JSD_THREADSAFE */
/* NOTE: These are intended for ASSERTs. Thus we supply checks for both
* LOCKED and UNLOCKED (rather that just LOCKED and !LOCKED) so that in
* the DEBUG non-Threadsafe case we can have an ASSERT that always succeeds
* without having to special case things in the code.
*/
#if defined(JSD_THREADSAFE) && defined(DEBUG)
#define JSD_SCRIPTS_LOCKED(jsdc) (jsd_IsLocked(jsdc->scriptsLock))
#define JSD_SOURCE_TEXT_LOCKED(jsdc) (jsd_IsLocked(jsdc->sourceTextLock))
#define JSD_ATOMS_LOCKED(jsdc) (jsd_IsLocked(jsdc->atomsLock))
#define JSD_OBJECTS_LOCKED(jsdc) (jsd_IsLocked(jsdc->objectsLock))
#define JSD_THREADSTATES_LOCKED(jsdc) (jsd_IsLocked(jsdc->threadStatesLock))
#define JSD_SCRIPTS_UNLOCKED(jsdc) (!jsd_IsLocked(jsdc->scriptsLock))
#define JSD_SOURCE_TEXT_UNLOCKED(jsdc) (!jsd_IsLocked(jsdc->sourceTextLock))
#define JSD_ATOMS_UNLOCKED(jsdc) (!jsd_IsLocked(jsdc->atomsLock))
#define JSD_OBJECTS_UNLOCKED(jsdc) (!jsd_IsLocked(jsdc->objectsLock))
#define JSD_THREADSTATES_UNLOCKED(jsdc) (!jsd_IsLocked(jsdc->threadStatesLock))
#else
#define JSD_SCRIPTS_LOCKED(jsdc) 1
#define JSD_SOURCE_TEXT_LOCKED(jsdc) 1
#define JSD_ATOMS_LOCKED(jsdc) 1
#define JSD_OBJECTS_LOCKED(jsdc) 1
#define JSD_THREADSTATES_LOCKED(jsdc) 1
#define JSD_SCRIPTS_UNLOCKED(jsdc) 1
#define JSD_SOURCE_TEXT_UNLOCKED(jsdc) 1
#define JSD_ATOMS_UNLOCKED(jsdc) 1
#define JSD_OBJECTS_UNLOCKED(jsdc) 1
#define JSD_THREADSTATES_UNLOCKED(jsdc) 1
#endif /* defined(JSD_THREADSAFE) && defined(DEBUG) */
/***************************************************************************/
/* Threading support */
#ifdef JSD_THREADSAFE
#define JSD_CURRENT_THREAD() jsd_CurrentThread()
#else /* !JSD_THREADSAFE */
#define JSD_CURRENT_THREAD() ((void*)0)
#endif /* JSD_THREADSAFE */
/***************************************************************************/
/* Dangerous thread support */
#ifdef JSD_HAS_DANGEROUS_THREAD
#define JSD_IS_DANGEROUS_THREAD(jsdc) \
(JSD_CURRENT_THREAD() == jsdc->dangerousThread)
#else /* !JSD_HAS_DANGEROUS_THREAD */
#define JSD_IS_DANGEROUS_THREAD(jsdc) 0
#endif /* JSD_HAS_DANGEROUS_THREAD */
/***************************************************************************/
/* Value and Property Functions */
extern JSDValue*
jsd_NewValue(JSDContext* jsdc, jsval val);
extern void
jsd_DropValue(JSDContext* jsdc, JSDValue* jsdval);
extern jsval
jsd_GetValueWrappedJSVal(JSDContext* jsdc, JSDValue* jsdval);
extern void
jsd_RefreshValue(JSDContext* jsdc, JSDValue* jsdval);
/**************************************************/
extern bool
jsd_IsValueObject(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValueNumber(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValueInt(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValueDouble(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValueString(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValueBoolean(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValueNull(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValueVoid(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValuePrimitive(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValueFunction(JSDContext* jsdc, JSDValue* jsdval);
extern bool
jsd_IsValueNative(JSDContext* jsdc, JSDValue* jsdval);
/**************************************************/
extern bool
jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval);
extern int32_t
jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval);
extern double
jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval);
extern JSString*
jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval);
extern JSString*
jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval);
extern JSFunction*
jsd_GetValueFunction(JSDContext* jsdc, JSDValue* jsdval);
/**************************************************/
extern unsigned
jsd_GetCountOfProperties(JSDContext* jsdc, JSDValue* jsdval);
extern JSDProperty*
jsd_IterateProperties(JSDContext* jsdc, JSDValue* jsdval, JSDProperty **iterp);
extern JSDProperty*
jsd_GetValueProperty(JSDContext* jsdc, JSDValue* jsdval, JSString* name);
extern JSDValue*
jsd_GetValuePrototype(JSDContext* jsdc, JSDValue* jsdval);
extern JSDValue*
jsd_GetValueParent(JSDContext* jsdc, JSDValue* jsdval);
extern JSDValue*
jsd_GetValueConstructor(JSDContext* jsdc, JSDValue* jsdval);
extern const char*
jsd_GetValueClassName(JSDContext* jsdc, JSDValue* jsdval);
extern JSDScript*
jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval);
/**************************************************/
extern void
jsd_DropProperty(JSDContext* jsdc, JSDProperty* jsdprop);
extern JSDValue*
jsd_GetPropertyName(JSDContext* jsdc, JSDProperty* jsdprop);
extern JSDValue*
jsd_GetPropertyValue(JSDContext* jsdc, JSDProperty* jsdprop);
extern JSDValue*
jsd_GetPropertyAlias(JSDContext* jsdc, JSDProperty* jsdprop);
extern unsigned
jsd_GetPropertyFlags(JSDContext* jsdc, JSDProperty* jsdprop);
/**************************************************/
/* Stepping Functions */
extern void *
jsd_FunctionCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
bool before, bool *ok, void *closure);
extern void *
jsd_TopLevelCallHook(JSContext *cx, JSAbstractFramePtr frame, bool isConstructing,
bool before, bool *ok, void *closure);
/**************************************************/
/* Object Functions */
extern bool
jsd_InitObjectManager(JSDContext* jsdc);
extern void
jsd_DestroyObjectManager(JSDContext* jsdc);
extern void
jsd_DestroyObjects(JSDContext* jsdc);
extern void
jsd_Constructing(JSDContext* jsdc, JSContext *cx, JSObject *obj,
JSAbstractFramePtr frame);
extern JSDObject*
jsd_IterateObjects(JSDContext* jsdc, JSDObject** iterp);
extern JSObject*
jsd_GetWrappedObject(JSDContext* jsdc, JSDObject* jsdobj);
extern const char*
jsd_GetObjectNewURL(JSDContext* jsdc, JSDObject* jsdobj);
extern unsigned
jsd_GetObjectNewLineNumber(JSDContext* jsdc, JSDObject* jsdobj);
extern const char*
jsd_GetObjectConstructorURL(JSDContext* jsdc, JSDObject* jsdobj);
extern unsigned
jsd_GetObjectConstructorLineNumber(JSDContext* jsdc, JSDObject* jsdobj);
extern const char*
jsd_GetObjectConstructorName(JSDContext* jsdc, JSDObject* jsdobj);
extern JSDObject*
jsd_GetJSDObjectForJSObject(JSDContext* jsdc, JSObject* jsobj);
extern JSDObject*
jsd_GetObjectForValue(JSDContext* jsdc, JSDValue* jsdval);
/*
* returns new refcounted JSDValue
*/
extern JSDValue*
jsd_GetValueForObject(JSDContext* jsdc, JSDObject* jsdobj);
/**************************************************/
/* Atom Functions */
extern bool
jsd_CreateAtomTable(JSDContext* jsdc);
extern void
jsd_DestroyAtomTable(JSDContext* jsdc);
extern JSDAtom*
jsd_AddAtom(JSDContext* jsdc, const char* str);
extern JSDAtom*
jsd_CloneAtom(JSDContext* jsdc, JSDAtom* atom);
extern void
jsd_DropAtom(JSDContext* jsdc, JSDAtom* atom);
#define JSD_ATOM_TO_STRING(a) ((const char*)((a)->str))
struct AutoSaveExceptionState {
AutoSaveExceptionState(JSContext *cx) : mCx(cx) {
mState = JS_SaveExceptionState(cx);
}
~AutoSaveExceptionState() {
JS_RestoreExceptionState(mCx, mState);
}
JSContext *mCx;
JSExceptionState *mState;
};
#endif /* jsd_h___ */