1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
39 * JavaScript Debugging support - Call stack support
45 void JSD_ASSERT_VALID_THREAD_STATE(JSDThreadState
* jsdthreadstate
)
47 JS_ASSERT(jsdthreadstate
);
48 JS_ASSERT(jsdthreadstate
->stackDepth
> 0);
51 void JSD_ASSERT_VALID_STACK_FRAME(JSDStackFrameInfo
* jsdframe
)
54 JS_ASSERT(jsdframe
->jsdthreadstate
);
58 static JSDStackFrameInfo
*
59 _addNewFrame(JSDContext
* jsdc
,
60 JSDThreadState
* jsdthreadstate
,
65 JSDStackFrameInfo
* jsdframe
;
66 JSDScript
* jsdscript
= NULL
;
68 if (!JS_IsNativeFrame(jsdthreadstate
->context
, fp
))
70 JSD_LOCK_SCRIPTS(jsdc
);
71 jsdscript
= jsd_FindJSDScript(jsdc
, script
);
72 JSD_UNLOCK_SCRIPTS(jsdc
);
73 if (!jsdscript
|| (jsdc
->flags
& JSD_HIDE_DISABLED_FRAMES
&&
74 !JSD_IS_DEBUG_ENABLED(jsdc
, jsdscript
)))
79 if (!JSD_IS_DEBUG_ENABLED(jsdc
, jsdscript
))
80 jsdthreadstate
->flags
|= TS_HAS_DISABLED_FRAME
;
83 jsdframe
= (JSDStackFrameInfo
*) calloc(1, sizeof(JSDStackFrameInfo
));
87 jsdframe
->jsdthreadstate
= jsdthreadstate
;
88 jsdframe
->jsdscript
= jsdscript
;
92 JS_APPEND_LINK(&jsdframe
->links
, &jsdthreadstate
->stack
);
93 jsdthreadstate
->stackDepth
++;
99 _destroyFrame(JSDStackFrameInfo
* jsdframe
)
101 /* kill any alloc'd objects in frame here... */
108 jsd_NewThreadState(JSDContext
* jsdc
, JSContext
*cx
)
110 JSDThreadState
* jsdthreadstate
;
111 JSStackFrame
* iter
= NULL
;
114 jsdthreadstate
= (JSDThreadState
*)calloc(1, sizeof(JSDThreadState
));
115 if( ! jsdthreadstate
)
118 jsdthreadstate
->context
= cx
;
119 jsdthreadstate
->thread
= JSD_CURRENT_THREAD();
120 JS_INIT_CLIST(&jsdthreadstate
->stack
);
121 jsdthreadstate
->stackDepth
= 0;
123 while( NULL
!= (fp
= JS_FrameIterator(cx
, &iter
)) )
125 JSScript
* script
= JS_GetFrameScript(cx
, fp
);
126 jsuword pc
= (jsuword
) JS_GetFramePC(cx
, fp
);
129 * don't construct a JSDStackFrame for dummy frames (those without a
130 * |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
133 if (JS_GetFrameThis(cx
, fp
) &&
134 ((jsdc
->flags
& JSD_INCLUDE_NATIVE_FRAMES
) ||
135 !JS_IsNativeFrame(cx
, fp
)))
137 JSDStackFrameInfo
*frame
;
139 frame
= _addNewFrame( jsdc
, jsdthreadstate
, script
, pc
, fp
);
141 if ((jsdthreadstate
->stackDepth
== 0 && !frame
) ||
142 (jsdthreadstate
->stackDepth
== 1 && frame
&&
143 frame
->jsdscript
&& !JSD_IS_DEBUG_ENABLED(jsdc
, frame
->jsdscript
)))
146 * if we failed to create the first frame, or the top frame
147 * is not enabled for debugging, fail the entire thread state.
149 JS_INIT_CLIST(&jsdthreadstate
->links
);
150 jsd_DestroyThreadState(jsdc
, jsdthreadstate
);
156 if (jsdthreadstate
->stackDepth
== 0)
158 free(jsdthreadstate
);
162 JSD_LOCK_THREADSTATES(jsdc
);
163 JS_APPEND_LINK(&jsdthreadstate
->links
, &jsdc
->threadsStates
);
164 JSD_UNLOCK_THREADSTATES(jsdc
);
166 return jsdthreadstate
;
170 jsd_DestroyThreadState(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
172 JSDStackFrameInfo
* jsdframe
;
175 JS_ASSERT(jsdthreadstate
);
176 JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate
->thread
);
178 JSD_LOCK_THREADSTATES(jsdc
);
179 JS_REMOVE_LINK(&jsdthreadstate
->links
);
180 JSD_UNLOCK_THREADSTATES(jsdc
);
182 list
= &jsdthreadstate
->stack
;
183 while( (JSDStackFrameInfo
*)list
!= (jsdframe
= (JSDStackFrameInfo
*)list
->next
) )
185 JS_REMOVE_LINK(&jsdframe
->links
);
186 _destroyFrame(jsdframe
);
188 free(jsdthreadstate
);
192 jsd_GetCountOfStackFrames(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
196 JSD_LOCK_THREADSTATES(jsdc
);
198 if( jsd_IsValidThreadState(jsdc
, jsdthreadstate
) )
199 count
= jsdthreadstate
->stackDepth
;
201 JSD_UNLOCK_THREADSTATES(jsdc
);
207 jsd_GetStackFrame(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
209 JSDStackFrameInfo
* jsdframe
= NULL
;
211 JSD_LOCK_THREADSTATES(jsdc
);
213 if( jsd_IsValidThreadState(jsdc
, jsdthreadstate
) )
214 jsdframe
= (JSDStackFrameInfo
*) JS_LIST_HEAD(&jsdthreadstate
->stack
);
215 JSD_UNLOCK_THREADSTATES(jsdc
);
221 jsd_GetJSContext (JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
223 JSContext
* cx
= NULL
;
225 JSD_LOCK_THREADSTATES(jsdc
);
226 if( jsd_IsValidThreadState(jsdc
, jsdthreadstate
) )
227 cx
= jsdthreadstate
->context
;
228 JSD_UNLOCK_THREADSTATES(jsdc
);
234 jsd_GetCallingStackFrame(JSDContext
* jsdc
,
235 JSDThreadState
* jsdthreadstate
,
236 JSDStackFrameInfo
* jsdframe
)
238 JSDStackFrameInfo
* nextjsdframe
= NULL
;
240 JSD_LOCK_THREADSTATES(jsdc
);
242 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
243 if( JS_LIST_HEAD(&jsdframe
->links
) != &jsdframe
->jsdthreadstate
->stack
)
244 nextjsdframe
= (JSDStackFrameInfo
*) JS_LIST_HEAD(&jsdframe
->links
);
246 JSD_UNLOCK_THREADSTATES(jsdc
);
252 jsd_GetScriptForStackFrame(JSDContext
* jsdc
,
253 JSDThreadState
* jsdthreadstate
,
254 JSDStackFrameInfo
* jsdframe
)
256 JSDScript
* jsdscript
= NULL
;
258 JSD_LOCK_THREADSTATES(jsdc
);
260 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
261 jsdscript
= jsdframe
->jsdscript
;
263 JSD_UNLOCK_THREADSTATES(jsdc
);
269 jsd_GetPCForStackFrame(JSDContext
* jsdc
,
270 JSDThreadState
* jsdthreadstate
,
271 JSDStackFrameInfo
* jsdframe
)
275 JSD_LOCK_THREADSTATES(jsdc
);
277 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
280 JSD_UNLOCK_THREADSTATES(jsdc
);
286 jsd_GetCallObjectForStackFrame(JSDContext
* jsdc
,
287 JSDThreadState
* jsdthreadstate
,
288 JSDStackFrameInfo
* jsdframe
)
291 JSDValue
* jsdval
= NULL
;
293 JSD_LOCK_THREADSTATES(jsdc
);
295 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
297 obj
= JS_GetFrameCallObject(jsdthreadstate
->context
, jsdframe
->fp
);
299 jsdval
= JSD_NewValue(jsdc
, OBJECT_TO_JSVAL(obj
));
302 JSD_UNLOCK_THREADSTATES(jsdc
);
308 jsd_GetScopeChainForStackFrame(JSDContext
* jsdc
,
309 JSDThreadState
* jsdthreadstate
,
310 JSDStackFrameInfo
* jsdframe
)
313 JSDValue
* jsdval
= NULL
;
315 JSD_LOCK_THREADSTATES(jsdc
);
317 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
319 JS_BeginRequest(jsdthreadstate
->context
);
320 obj
= JS_GetFrameScopeChain(jsdthreadstate
->context
, jsdframe
->fp
);
321 JS_EndRequest(jsdthreadstate
->context
);
323 jsdval
= JSD_NewValue(jsdc
, OBJECT_TO_JSVAL(obj
));
326 JSD_UNLOCK_THREADSTATES(jsdc
);
332 jsd_GetThisForStackFrame(JSDContext
* jsdc
,
333 JSDThreadState
* jsdthreadstate
,
334 JSDStackFrameInfo
* jsdframe
)
337 JSDValue
* jsdval
= NULL
;
338 JSD_LOCK_THREADSTATES(jsdc
);
340 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
342 obj
= JS_GetFrameThis(jsdthreadstate
->context
, jsdframe
->fp
);
344 jsdval
= JSD_NewValue(jsdc
, OBJECT_TO_JSVAL(obj
));
347 JSD_UNLOCK_THREADSTATES(jsdc
);
352 jsd_GetNameForStackFrame(JSDContext
* jsdc
,
353 JSDThreadState
* jsdthreadstate
,
354 JSDStackFrameInfo
* jsdframe
)
356 const char *rv
= NULL
;
358 JSD_LOCK_THREADSTATES(jsdc
);
360 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
362 JSFunction
*fun
= JS_GetFrameFunction (jsdthreadstate
->context
,
365 rv
= JS_GetFunctionName (fun
);
368 JSD_UNLOCK_THREADSTATES(jsdc
);
373 jsd_IsStackFrameNative(JSDContext
* jsdc
,
374 JSDThreadState
* jsdthreadstate
,
375 JSDStackFrameInfo
* jsdframe
)
379 JSD_LOCK_THREADSTATES(jsdc
);
381 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
383 rv
= JS_IsNativeFrame(jsdthreadstate
->context
, jsdframe
->fp
);
390 JSD_UNLOCK_THREADSTATES(jsdc
);
395 jsd_IsStackFrameDebugger(JSDContext
* jsdc
,
396 JSDThreadState
* jsdthreadstate
,
397 JSDStackFrameInfo
* jsdframe
)
400 JSD_LOCK_THREADSTATES(jsdc
);
402 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
404 rv
= JS_IsDebuggerFrame(jsdthreadstate
->context
, jsdframe
->fp
);
407 JSD_UNLOCK_THREADSTATES(jsdc
);
412 jsd_IsStackFrameConstructing(JSDContext
* jsdc
,
413 JSDThreadState
* jsdthreadstate
,
414 JSDStackFrameInfo
* jsdframe
)
417 JSD_LOCK_THREADSTATES(jsdc
);
419 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
421 rv
= JS_IsConstructorFrame(jsdthreadstate
->context
, jsdframe
->fp
);
424 JSD_UNLOCK_THREADSTATES(jsdc
);
429 jsd_EvaluateUCScriptInStackFrame(JSDContext
* jsdc
,
430 JSDThreadState
* jsdthreadstate
,
431 JSDStackFrameInfo
* jsdframe
,
432 const jschar
*bytes
, uintN length
,
433 const char *filename
, uintN lineno
,
434 JSBool eatExceptions
, jsval
*rval
)
438 JSExceptionState
* exceptionState
= NULL
;
441 JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate
->thread
);
443 JSD_LOCK_THREADSTATES(jsdc
);
444 valid
= jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
);
445 JSD_UNLOCK_THREADSTATES(jsdc
);
450 cx
= jsdthreadstate
->context
;
454 exceptionState
= JS_SaveExceptionState(cx
);
455 JS_ClearPendingException(cx
);
456 jsd_StartingEvalUsingFilename(jsdc
, filename
);
457 retval
= JS_EvaluateUCInStackFrame(cx
, jsdframe
->fp
, bytes
, length
,
458 filename
, lineno
, rval
);
459 jsd_FinishedEvalUsingFilename(jsdc
, filename
);
461 JS_RestoreExceptionState(cx
, exceptionState
);
467 jsd_EvaluateScriptInStackFrame(JSDContext
* jsdc
,
468 JSDThreadState
* jsdthreadstate
,
469 JSDStackFrameInfo
* jsdframe
,
470 const char *bytes
, uintN length
,
471 const char *filename
, uintN lineno
,
472 JSBool eatExceptions
, jsval
*rval
)
476 JSExceptionState
* exceptionState
= NULL
;
479 JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate
->thread
);
481 JSD_LOCK_THREADSTATES(jsdc
);
482 valid
= jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
);
483 JSD_UNLOCK_THREADSTATES(jsdc
);
488 cx
= jsdthreadstate
->context
;
492 exceptionState
= JS_SaveExceptionState(cx
);
493 JS_ClearPendingException(cx
);
494 jsd_StartingEvalUsingFilename(jsdc
, filename
);
495 retval
= JS_EvaluateInStackFrame(cx
, jsdframe
->fp
, bytes
, length
,
496 filename
, lineno
, rval
);
497 jsd_FinishedEvalUsingFilename(jsdc
, filename
);
499 JS_RestoreExceptionState(cx
, exceptionState
);
505 jsd_ValToStringInStackFrame(JSDContext
* jsdc
,
506 JSDThreadState
* jsdthreadstate
,
507 JSDStackFrameInfo
* jsdframe
,
512 JSExceptionState
* exceptionState
;
515 JSD_LOCK_THREADSTATES(jsdc
);
516 valid
= jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
);
517 JSD_UNLOCK_THREADSTATES(jsdc
);
522 cx
= jsdthreadstate
->context
;
525 exceptionState
= JS_SaveExceptionState(cx
);
526 retval
= JS_ValueToString(cx
, val
);
527 JS_RestoreExceptionState(cx
, exceptionState
);
533 jsd_IsValidThreadState(JSDContext
* jsdc
,
534 JSDThreadState
* jsdthreadstate
)
538 JS_ASSERT( JSD_THREADSTATES_LOCKED(jsdc
) );
540 for( cur
= (JSDThreadState
*)jsdc
->threadsStates
.next
;
541 cur
!= (JSDThreadState
*)&jsdc
->threadsStates
;
542 cur
= (JSDThreadState
*)cur
->links
.next
)
544 if( cur
== jsdthreadstate
)
551 jsd_IsValidFrameInThreadState(JSDContext
* jsdc
,
552 JSDThreadState
* jsdthreadstate
,
553 JSDStackFrameInfo
* jsdframe
)
555 JS_ASSERT(JSD_THREADSTATES_LOCKED(jsdc
));
557 if( ! jsd_IsValidThreadState(jsdc
, jsdthreadstate
) )
559 if( jsdframe
->jsdthreadstate
!= jsdthreadstate
)
562 JSD_ASSERT_VALID_THREAD_STATE(jsdthreadstate
);
563 JSD_ASSERT_VALID_STACK_FRAME(jsdframe
);
569 _getContextForThreadState(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
572 JSD_LOCK_THREADSTATES(jsdc
);
573 valid
= jsd_IsValidThreadState(jsdc
, jsdthreadstate
);
574 JSD_UNLOCK_THREADSTATES(jsdc
);
576 return jsdthreadstate
->context
;
581 jsd_GetException(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
586 if(!(cx
= _getContextForThreadState(jsdc
, jsdthreadstate
)))
589 if(JS_GetPendingException(cx
, &val
))
590 return jsd_NewValue(jsdc
, val
);
595 jsd_SetException(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
,
600 if(!(cx
= _getContextForThreadState(jsdc
, jsdthreadstate
)))
604 JS_SetPendingException(cx
, JSD_GetValueWrappedJSVal(jsdc
, jsdval
));
606 JS_ClearPendingException(cx
);