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_IsScriptFrame(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 JS_BeginRequest(jsdthreadstate
->context
);
124 while( NULL
!= (fp
= JS_FrameIterator(cx
, &iter
)) )
126 JSScript
* script
= JS_GetFrameScript(cx
, fp
);
127 jsuword pc
= (jsuword
) JS_GetFramePC(cx
, fp
);
130 * don't construct a JSDStackFrame for dummy frames (those without a
131 * |this| object, or native frames, if JSD_INCLUDE_NATIVE_FRAMES
134 if (JS_GetFrameThis(cx
, fp
) &&
135 ((jsdc
->flags
& JSD_INCLUDE_NATIVE_FRAMES
) ||
136 JS_IsScriptFrame(cx
, fp
)))
138 JSDStackFrameInfo
*frame
;
140 frame
= _addNewFrame( jsdc
, jsdthreadstate
, script
, pc
, fp
);
142 if ((jsdthreadstate
->stackDepth
== 0 && !frame
) ||
143 (jsdthreadstate
->stackDepth
== 1 && frame
&&
144 frame
->jsdscript
&& !JSD_IS_DEBUG_ENABLED(jsdc
, frame
->jsdscript
)))
147 * if we failed to create the first frame, or the top frame
148 * is not enabled for debugging, fail the entire thread state.
150 JS_INIT_CLIST(&jsdthreadstate
->links
);
151 JS_EndRequest(jsdthreadstate
->context
);
152 jsd_DestroyThreadState(jsdc
, jsdthreadstate
);
157 JS_EndRequest(jsdthreadstate
->context
);
159 if (jsdthreadstate
->stackDepth
== 0)
161 free(jsdthreadstate
);
165 JSD_LOCK_THREADSTATES(jsdc
);
166 JS_APPEND_LINK(&jsdthreadstate
->links
, &jsdc
->threadsStates
);
167 JSD_UNLOCK_THREADSTATES(jsdc
);
169 return jsdthreadstate
;
173 jsd_DestroyThreadState(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
175 JSDStackFrameInfo
* jsdframe
;
178 JS_ASSERT(jsdthreadstate
);
179 JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate
->thread
);
181 JSD_LOCK_THREADSTATES(jsdc
);
182 JS_REMOVE_LINK(&jsdthreadstate
->links
);
183 JSD_UNLOCK_THREADSTATES(jsdc
);
185 list
= &jsdthreadstate
->stack
;
186 while( (JSDStackFrameInfo
*)list
!= (jsdframe
= (JSDStackFrameInfo
*)list
->next
) )
188 JS_REMOVE_LINK(&jsdframe
->links
);
189 _destroyFrame(jsdframe
);
191 free(jsdthreadstate
);
195 jsd_GetCountOfStackFrames(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
199 JSD_LOCK_THREADSTATES(jsdc
);
201 if( jsd_IsValidThreadState(jsdc
, jsdthreadstate
) )
202 count
= jsdthreadstate
->stackDepth
;
204 JSD_UNLOCK_THREADSTATES(jsdc
);
210 jsd_GetStackFrame(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
212 JSDStackFrameInfo
* jsdframe
= NULL
;
214 JSD_LOCK_THREADSTATES(jsdc
);
216 if( jsd_IsValidThreadState(jsdc
, jsdthreadstate
) )
217 jsdframe
= (JSDStackFrameInfo
*) JS_LIST_HEAD(&jsdthreadstate
->stack
);
218 JSD_UNLOCK_THREADSTATES(jsdc
);
224 jsd_GetJSContext (JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
226 JSContext
* cx
= NULL
;
228 JSD_LOCK_THREADSTATES(jsdc
);
229 if( jsd_IsValidThreadState(jsdc
, jsdthreadstate
) )
230 cx
= jsdthreadstate
->context
;
231 JSD_UNLOCK_THREADSTATES(jsdc
);
237 jsd_GetCallingStackFrame(JSDContext
* jsdc
,
238 JSDThreadState
* jsdthreadstate
,
239 JSDStackFrameInfo
* jsdframe
)
241 JSDStackFrameInfo
* nextjsdframe
= NULL
;
243 JSD_LOCK_THREADSTATES(jsdc
);
245 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
246 if( JS_LIST_HEAD(&jsdframe
->links
) != &jsdframe
->jsdthreadstate
->stack
)
247 nextjsdframe
= (JSDStackFrameInfo
*) JS_LIST_HEAD(&jsdframe
->links
);
249 JSD_UNLOCK_THREADSTATES(jsdc
);
255 jsd_GetScriptForStackFrame(JSDContext
* jsdc
,
256 JSDThreadState
* jsdthreadstate
,
257 JSDStackFrameInfo
* jsdframe
)
259 JSDScript
* jsdscript
= NULL
;
261 JSD_LOCK_THREADSTATES(jsdc
);
263 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
264 jsdscript
= jsdframe
->jsdscript
;
266 JSD_UNLOCK_THREADSTATES(jsdc
);
272 jsd_GetPCForStackFrame(JSDContext
* jsdc
,
273 JSDThreadState
* jsdthreadstate
,
274 JSDStackFrameInfo
* jsdframe
)
278 JSD_LOCK_THREADSTATES(jsdc
);
280 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
283 JSD_UNLOCK_THREADSTATES(jsdc
);
289 jsd_GetCallObjectForStackFrame(JSDContext
* jsdc
,
290 JSDThreadState
* jsdthreadstate
,
291 JSDStackFrameInfo
* jsdframe
)
294 JSDValue
* jsdval
= NULL
;
296 JSD_LOCK_THREADSTATES(jsdc
);
298 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
300 obj
= JS_GetFrameCallObject(jsdthreadstate
->context
, jsdframe
->fp
);
302 jsdval
= JSD_NewValue(jsdc
, OBJECT_TO_JSVAL(obj
));
305 JSD_UNLOCK_THREADSTATES(jsdc
);
311 jsd_GetScopeChainForStackFrame(JSDContext
* jsdc
,
312 JSDThreadState
* jsdthreadstate
,
313 JSDStackFrameInfo
* jsdframe
)
316 JSDValue
* jsdval
= NULL
;
318 JSD_LOCK_THREADSTATES(jsdc
);
320 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
322 JS_BeginRequest(jsdthreadstate
->context
);
323 obj
= JS_GetFrameScopeChain(jsdthreadstate
->context
, jsdframe
->fp
);
324 JS_EndRequest(jsdthreadstate
->context
);
326 jsdval
= JSD_NewValue(jsdc
, OBJECT_TO_JSVAL(obj
));
329 JSD_UNLOCK_THREADSTATES(jsdc
);
335 jsd_GetThisForStackFrame(JSDContext
* jsdc
,
336 JSDThreadState
* jsdthreadstate
,
337 JSDStackFrameInfo
* jsdframe
)
340 JSDValue
* jsdval
= NULL
;
341 JSD_LOCK_THREADSTATES(jsdc
);
343 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
345 JS_BeginRequest(jsdthreadstate
->context
);
346 obj
= JS_GetFrameThis(jsdthreadstate
->context
, jsdframe
->fp
);
347 JS_EndRequest(jsdthreadstate
->context
);
349 jsdval
= JSD_NewValue(jsdc
, OBJECT_TO_JSVAL(obj
));
352 JSD_UNLOCK_THREADSTATES(jsdc
);
357 jsd_GetNameForStackFrame(JSDContext
* jsdc
,
358 JSDThreadState
* jsdthreadstate
,
359 JSDStackFrameInfo
* jsdframe
)
361 const char *rv
= NULL
;
363 JSD_LOCK_THREADSTATES(jsdc
);
365 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
367 JSFunction
*fun
= JS_GetFrameFunction (jsdthreadstate
->context
,
370 rv
= JS_GetFunctionName (fun
);
373 JSD_UNLOCK_THREADSTATES(jsdc
);
378 jsd_IsStackFrameDebugger(JSDContext
* jsdc
,
379 JSDThreadState
* jsdthreadstate
,
380 JSDStackFrameInfo
* jsdframe
)
383 JSD_LOCK_THREADSTATES(jsdc
);
385 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
387 rv
= JS_IsDebuggerFrame(jsdthreadstate
->context
, jsdframe
->fp
);
390 JSD_UNLOCK_THREADSTATES(jsdc
);
395 jsd_IsStackFrameConstructing(JSDContext
* jsdc
,
396 JSDThreadState
* jsdthreadstate
,
397 JSDStackFrameInfo
* jsdframe
)
400 JSD_LOCK_THREADSTATES(jsdc
);
402 if( jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
) )
404 rv
= JS_IsConstructorFrame(jsdthreadstate
->context
, jsdframe
->fp
);
407 JSD_UNLOCK_THREADSTATES(jsdc
);
412 jsd_EvaluateUCScriptInStackFrame(JSDContext
* jsdc
,
413 JSDThreadState
* jsdthreadstate
,
414 JSDStackFrameInfo
* jsdframe
,
415 const jschar
*bytes
, uintN length
,
416 const char *filename
, uintN lineno
,
417 JSBool eatExceptions
, jsval
*rval
)
421 JSExceptionState
* exceptionState
= NULL
;
424 JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate
->thread
);
426 JSD_LOCK_THREADSTATES(jsdc
);
427 valid
= jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
);
428 JSD_UNLOCK_THREADSTATES(jsdc
);
433 cx
= jsdthreadstate
->context
;
437 exceptionState
= JS_SaveExceptionState(cx
);
438 JS_ClearPendingException(cx
);
439 jsd_StartingEvalUsingFilename(jsdc
, filename
);
440 retval
= JS_EvaluateUCInStackFrame(cx
, jsdframe
->fp
, bytes
, length
,
441 filename
, lineno
, rval
);
442 jsd_FinishedEvalUsingFilename(jsdc
, filename
);
444 JS_RestoreExceptionState(cx
, exceptionState
);
450 jsd_EvaluateScriptInStackFrame(JSDContext
* jsdc
,
451 JSDThreadState
* jsdthreadstate
,
452 JSDStackFrameInfo
* jsdframe
,
453 const char *bytes
, uintN length
,
454 const char *filename
, uintN lineno
,
455 JSBool eatExceptions
, jsval
*rval
)
459 JSExceptionState
* exceptionState
= NULL
;
462 JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate
->thread
);
464 JSD_LOCK_THREADSTATES(jsdc
);
465 valid
= jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
);
466 JSD_UNLOCK_THREADSTATES(jsdc
);
471 cx
= jsdthreadstate
->context
;
475 exceptionState
= JS_SaveExceptionState(cx
);
476 JS_ClearPendingException(cx
);
477 jsd_StartingEvalUsingFilename(jsdc
, filename
);
478 retval
= JS_EvaluateInStackFrame(cx
, jsdframe
->fp
, bytes
, length
,
479 filename
, lineno
, rval
);
480 jsd_FinishedEvalUsingFilename(jsdc
, filename
);
482 JS_RestoreExceptionState(cx
, exceptionState
);
488 jsd_ValToStringInStackFrame(JSDContext
* jsdc
,
489 JSDThreadState
* jsdthreadstate
,
490 JSDStackFrameInfo
* jsdframe
,
495 JSExceptionState
* exceptionState
;
498 JSD_LOCK_THREADSTATES(jsdc
);
499 valid
= jsd_IsValidFrameInThreadState(jsdc
, jsdthreadstate
, jsdframe
);
500 JSD_UNLOCK_THREADSTATES(jsdc
);
505 cx
= jsdthreadstate
->context
;
508 exceptionState
= JS_SaveExceptionState(cx
);
509 retval
= JS_ValueToString(cx
, val
);
510 JS_RestoreExceptionState(cx
, exceptionState
);
516 jsd_IsValidThreadState(JSDContext
* jsdc
,
517 JSDThreadState
* jsdthreadstate
)
521 JS_ASSERT( JSD_THREADSTATES_LOCKED(jsdc
) );
523 for( cur
= (JSDThreadState
*)jsdc
->threadsStates
.next
;
524 cur
!= (JSDThreadState
*)&jsdc
->threadsStates
;
525 cur
= (JSDThreadState
*)cur
->links
.next
)
527 if( cur
== jsdthreadstate
)
534 jsd_IsValidFrameInThreadState(JSDContext
* jsdc
,
535 JSDThreadState
* jsdthreadstate
,
536 JSDStackFrameInfo
* jsdframe
)
538 JS_ASSERT(JSD_THREADSTATES_LOCKED(jsdc
));
540 if( ! jsd_IsValidThreadState(jsdc
, jsdthreadstate
) )
542 if( jsdframe
->jsdthreadstate
!= jsdthreadstate
)
545 JSD_ASSERT_VALID_THREAD_STATE(jsdthreadstate
);
546 JSD_ASSERT_VALID_STACK_FRAME(jsdframe
);
552 _getContextForThreadState(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
555 JSD_LOCK_THREADSTATES(jsdc
);
556 valid
= jsd_IsValidThreadState(jsdc
, jsdthreadstate
);
557 JSD_UNLOCK_THREADSTATES(jsdc
);
559 return jsdthreadstate
->context
;
564 jsd_GetException(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
)
569 if(!(cx
= _getContextForThreadState(jsdc
, jsdthreadstate
)))
572 if(JS_GetPendingException(cx
, &val
))
573 return jsd_NewValue(jsdc
, val
);
578 jsd_SetException(JSDContext
* jsdc
, JSDThreadState
* jsdthreadstate
,
583 if(!(cx
= _getContextForThreadState(jsdc
, jsdthreadstate
)))
587 JS_SetPendingException(cx
, JSD_GetValueWrappedJSVal(jsdc
, jsdval
));
589 JS_ClearPendingException(cx
);