1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=99:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
17 * The Original Code is Mozilla Communicator client code, released
20 * The Initial Developer of the Original Code is
21 * Netscape Communications Corporation.
22 * Portions created by the Initial Developer are Copyright (C) 1998
23 * the Initial Developer. All Rights Reserved.
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
47 #include "jsutil.h" /* Added by JSIFY */
51 #include "jsversion.h"
63 #include "jsstaticcheck.h"
66 #include "jsatominlines.h"
67 #include "jsobjinlines.h"
68 #include "jsscopeinlines.h"
70 #include "jsautooplen.h"
74 typedef struct JSTrap
{
79 JSTrapHandler handler
;
83 #define DBG_LOCK(rt) JS_ACQUIRE_LOCK((rt)->debuggerLock)
84 #define DBG_UNLOCK(rt) JS_RELEASE_LOCK((rt)->debuggerLock)
85 #define DBG_LOCK_EVAL(rt,expr) (DBG_LOCK(rt), (expr), DBG_UNLOCK(rt))
88 * NB: FindTrap must be called with rt->debuggerLock acquired.
91 FindTrap(JSRuntime
*rt
, JSScript
*script
, jsbytecode
*pc
)
95 for (trap
= (JSTrap
*)rt
->trapList
.next
;
96 &trap
->links
!= &rt
->trapList
;
97 trap
= (JSTrap
*)trap
->links
.next
) {
98 if (trap
->script
== script
&& trap
->pc
== pc
)
105 js_UntrapScriptCode(JSContext
*cx
, JSScript
*script
)
114 for (trap
= (JSTrap
*)rt
->trapList
.next
;
117 trap
= (JSTrap
*)trap
->links
.next
) {
118 if (trap
->script
== script
&&
119 (size_t)(trap
->pc
- script
->code
) < script
->length
) {
120 if (code
== script
->code
) {
121 jssrcnote
*sn
, *notes
;
124 nbytes
= script
->length
* sizeof(jsbytecode
);
125 notes
= script
->notes();
126 for (sn
= notes
; !SN_IS_TERMINATOR(sn
); sn
= SN_NEXT(sn
))
128 nbytes
+= (sn
- notes
+ 1) * sizeof *sn
;
130 code
= (jsbytecode
*) cx
->malloc(nbytes
);
133 memcpy(code
, script
->code
, nbytes
);
134 JS_PURGE_GSN_CACHE(cx
);
136 code
[trap
->pc
- script
->code
] = trap
->op
;
143 JS_PUBLIC_API(JSBool
)
144 JS_SetTrap(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
,
145 JSTrapHandler handler
, jsval closure
)
147 JSTrap
*junk
, *trap
, *twin
;
151 if (script
== JSScript::emptyScript()) {
152 JS_ReportErrorFlagsAndNumber(cx
, JSREPORT_ERROR
, js_GetErrorMessage
,
153 NULL
, JSMSG_READ_ONLY
, "empty script");
157 JS_ASSERT((JSOp
) *pc
!= JSOP_TRAP
);
161 trap
= FindTrap(rt
, script
, pc
);
163 JS_ASSERT(trap
->script
== script
&& trap
->pc
== pc
);
164 JS_ASSERT(*pc
== JSOP_TRAP
);
166 sample
= rt
->debuggerMutations
;
168 trap
= (JSTrap
*) cx
->malloc(sizeof *trap
);
171 trap
->closure
= JSVAL_NULL
;
173 twin
= (rt
->debuggerMutations
!= sample
)
174 ? FindTrap(rt
, script
, pc
)
180 JS_APPEND_LINK(&trap
->links
, &rt
->trapList
);
181 ++rt
->debuggerMutations
;
182 trap
->script
= script
;
184 trap
->op
= (JSOp
)*pc
;
188 trap
->handler
= handler
;
189 trap
->closure
= closure
;
197 JS_GetTrapOpcode(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
)
205 trap
= FindTrap(rt
, script
, pc
);
206 op
= trap
? trap
->op
: (JSOp
) *pc
;
212 DestroyTrapAndUnlock(JSContext
*cx
, JSTrap
*trap
)
214 ++cx
->runtime
->debuggerMutations
;
215 JS_REMOVE_LINK(&trap
->links
);
216 *trap
->pc
= (jsbytecode
)trap
->op
;
217 DBG_UNLOCK(cx
->runtime
);
222 JS_ClearTrap(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
,
223 JSTrapHandler
*handlerp
, jsval
*closurep
)
227 DBG_LOCK(cx
->runtime
);
228 trap
= FindTrap(cx
->runtime
, script
, pc
);
230 *handlerp
= trap
? trap
->handler
: NULL
;
232 *closurep
= trap
? trap
->closure
: JSVAL_NULL
;
234 DestroyTrapAndUnlock(cx
, trap
);
236 DBG_UNLOCK(cx
->runtime
);
240 JS_ClearScriptTraps(JSContext
*cx
, JSScript
*script
)
248 for (trap
= (JSTrap
*)rt
->trapList
.next
;
249 &trap
->links
!= &rt
->trapList
;
251 next
= (JSTrap
*)trap
->links
.next
;
252 if (trap
->script
== script
) {
253 sample
= rt
->debuggerMutations
;
254 DestroyTrapAndUnlock(cx
, trap
);
256 if (rt
->debuggerMutations
!= sample
+ 1)
257 next
= (JSTrap
*)rt
->trapList
.next
;
264 JS_ClearAllTraps(JSContext
*cx
)
272 for (trap
= (JSTrap
*)rt
->trapList
.next
;
273 &trap
->links
!= &rt
->trapList
;
275 next
= (JSTrap
*)trap
->links
.next
;
276 sample
= rt
->debuggerMutations
;
277 DestroyTrapAndUnlock(cx
, trap
);
279 if (rt
->debuggerMutations
!= sample
+ 1)
280 next
= (JSTrap
*)rt
->trapList
.next
;
286 * NB: js_MarkTraps does not acquire cx->runtime->debuggerLock, since the
287 * debugger should never be racing with the GC (i.e., the debugger must
288 * respect the request model).
291 js_MarkTraps(JSTracer
*trc
)
293 JSRuntime
*rt
= trc
->context
->runtime
;
295 for (JSTrap
*trap
= (JSTrap
*) rt
->trapList
.next
;
296 &trap
->links
!= &rt
->trapList
;
297 trap
= (JSTrap
*) trap
->links
.next
) {
298 MarkValue(trc
, Valueify(trap
->closure
), "trap->closure");
302 JS_PUBLIC_API(JSTrapStatus
)
303 JS_HandleTrap(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
, jsval
*rval
)
309 DBG_LOCK(cx
->runtime
);
310 trap
= FindTrap(cx
->runtime
, script
, pc
);
311 JS_ASSERT(!trap
|| trap
->handler
);
314 DBG_UNLOCK(cx
->runtime
);
316 /* Defend against "pc for wrong script" API usage error. */
317 JS_ASSERT(op
!= JSOP_TRAP
);
320 /* If the API was abused, we must fail for want of the real op. */
324 /* Assume a race with a debugger thread and try to carry on. */
325 *rval
= INT_TO_JSVAL(op
);
326 return JSTRAP_CONTINUE
;
328 /* Always fail if single-threaded (must be an API usage error). */
332 DBG_UNLOCK(cx
->runtime
);
335 * It's important that we not use 'trap->' after calling the callback --
336 * the callback might remove the trap!
338 op
= (jsint
)trap
->op
;
339 status
= trap
->handler(cx
, script
, pc
, rval
, trap
->closure
);
340 if (status
== JSTRAP_CONTINUE
) {
341 /* By convention, return the true op to the interpreter in rval. */
342 *rval
= INT_TO_JSVAL(op
);
349 JITInhibitingHookChange(JSRuntime
*rt
, bool wasInhibited
)
352 if (!rt
->debuggerInhibitsJIT()) {
353 for (JSCList
*cl
= rt
->contextList
.next
; cl
!= &rt
->contextList
; cl
= cl
->next
)
354 js_ContextFromLinkField(cl
)->updateJITEnabled();
356 } else if (rt
->debuggerInhibitsJIT()) {
357 for (JSCList
*cl
= rt
->contextList
.next
; cl
!= &rt
->contextList
; cl
= cl
->next
)
358 js_ContextFromLinkField(cl
)->jitEnabled
= false;
363 LeaveTraceRT(JSRuntime
*rt
)
365 JSThreadData
*data
= js_CurrentThreadData(rt
);
366 JSContext
*cx
= data
? data
->traceMonitor
.tracecx
: NULL
;
374 JS_PUBLIC_API(JSBool
)
375 JS_SetInterrupt(JSRuntime
*rt
, JSInterruptHook hook
, void *closure
)
380 bool wasInhibited
= rt
->debuggerInhibitsJIT();
382 rt
->globalDebugHooks
.interruptHook
= hook
;
383 rt
->globalDebugHooks
.interruptHookData
= closure
;
385 JITInhibitingHookChange(rt
, wasInhibited
);
392 JS_PUBLIC_API(JSBool
)
393 JS_ClearInterrupt(JSRuntime
*rt
, JSInterruptHook
*hoop
, void **closurep
)
397 bool wasInhibited
= rt
->debuggerInhibitsJIT();
400 *hoop
= rt
->globalDebugHooks
.interruptHook
;
402 *closurep
= rt
->globalDebugHooks
.interruptHookData
;
403 rt
->globalDebugHooks
.interruptHook
= 0;
404 rt
->globalDebugHooks
.interruptHookData
= 0;
406 JITInhibitingHookChange(rt
, wasInhibited
);
411 /************************************************************************/
413 typedef struct JSWatchPoint
{
415 JSObject
*object
; /* weak link, see js_FinalizeObject */
416 JSScopeProperty
*sprop
;
418 JSWatchPointHandler handler
;
423 #define JSWP_LIVE 0x1 /* live because set and not cleared */
424 #define JSWP_HELD 0x2 /* held while running handler/setter */
427 IsWatchedProperty(JSContext
*cx
, JSScopeProperty
*sprop
);
430 * NB: DropWatchPointAndUnlock releases cx->runtime->debuggerLock in all cases.
433 DropWatchPointAndUnlock(JSContext
*cx
, JSWatchPoint
*wp
, uintN flag
)
436 JSScopeProperty
*sprop
;
442 if (wp
->flags
!= 0) {
443 DBG_UNLOCK(cx
->runtime
);
448 * Remove wp from the list, then if there are no other watchpoints for
449 * wp->sprop in any scope, restore wp->sprop->setter from wp.
451 ++cx
->runtime
->debuggerMutations
;
452 JS_REMOVE_LINK(&wp
->links
);
456 * Passing null for the scope parameter tells js_GetWatchedSetter to find
457 * any watch point for sprop, and not to lock or unlock rt->debuggerLock.
458 * If js_ChangeNativePropertyAttrs fails, propagate failure after removing
459 * wp->closure's root and freeing wp.
461 setter
= js_GetWatchedSetter(cx
->runtime
, NULL
, sprop
);
462 DBG_UNLOCK(cx
->runtime
);
464 JS_LOCK_OBJ(cx
, wp
->object
);
465 scope
= wp
->object
->scope();
468 * If the property wasn't found on wp->object, or it isn't still being
469 * watched, then someone else must have deleted or unwatched it, and we
470 * don't need to change the property attributes.
472 JSScopeProperty
*wprop
= scope
->lookup(sprop
->id
);
474 wprop
->hasSetterValue() == sprop
->hasSetterValue() &&
475 IsWatchedProperty(cx
, wprop
)) {
476 sprop
= scope
->changeProperty(cx
, wprop
, 0, wprop
->attributes(),
477 wprop
->getter(), wp
->setter
);
481 JS_UNLOCK_SCOPE(cx
, scope
);
489 * NB: js_TraceWatchPoints does not acquire cx->runtime->debuggerLock, since
490 * the debugger should never be racing with the GC (i.e., the debugger must
491 * respect the request model).
494 js_TraceWatchPoints(JSTracer
*trc
, JSObject
*obj
)
499 rt
= trc
->context
->runtime
;
501 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
502 &wp
->links
!= &rt
->watchPointList
;
503 wp
= (JSWatchPoint
*)wp
->links
.next
) {
504 if (wp
->object
== obj
) {
505 wp
->sprop
->trace(trc
);
506 if (wp
->sprop
->hasSetterValue() && wp
->setter
)
507 JS_CALL_OBJECT_TRACER(trc
, CastAsObject(wp
->setter
), "wp->setter");
508 JS_CALL_OBJECT_TRACER(trc
, wp
->closure
, "wp->closure");
514 js_SweepWatchPoints(JSContext
*cx
)
517 JSWatchPoint
*wp
, *next
;
522 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
523 &wp
->links
!= &rt
->watchPointList
;
525 next
= (JSWatchPoint
*)wp
->links
.next
;
526 if (js_IsAboutToBeFinalized(wp
->object
)) {
527 sample
= rt
->debuggerMutations
;
529 /* Ignore failures. */
530 DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
);
532 if (rt
->debuggerMutations
!= sample
+ 1)
533 next
= (JSWatchPoint
*)rt
->watchPointList
.next
;
542 * NB: FindWatchPoint must be called with rt->debuggerLock acquired.
544 static JSWatchPoint
*
545 FindWatchPoint(JSRuntime
*rt
, JSScope
*scope
, jsid id
)
549 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
550 &wp
->links
!= &rt
->watchPointList
;
551 wp
= (JSWatchPoint
*)wp
->links
.next
) {
552 if (wp
->object
->scope() == scope
&& wp
->sprop
->id
== id
)
559 js_FindWatchPoint(JSRuntime
*rt
, JSScope
*scope
, jsid id
)
562 JSScopeProperty
*sprop
;
565 wp
= FindWatchPoint(rt
, scope
, id
);
566 sprop
= wp
? wp
->sprop
: NULL
;
572 * Secret handshake with DropWatchPointAndUnlock: if (!scope), we know our
573 * caller has acquired rt->debuggerLock, so we don't have to.
576 js_GetWatchedSetter(JSRuntime
*rt
, JSScope
*scope
,
577 const JSScopeProperty
*sprop
)
585 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
586 &wp
->links
!= &rt
->watchPointList
;
587 wp
= (JSWatchPoint
*)wp
->links
.next
) {
588 if ((!scope
|| wp
->object
->scope() == scope
) && wp
->sprop
== sprop
) {
599 js_watch_set(JSContext
*cx
, JSObject
*obj
, jsid id
, Value
*vp
)
601 JSRuntime
*rt
= cx
->runtime
;
603 for (JSWatchPoint
*wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
604 &wp
->links
!= &rt
->watchPointList
;
605 wp
= (JSWatchPoint
*)wp
->links
.next
) {
606 JSScopeProperty
*sprop
= wp
->sprop
;
607 if (wp
->object
== obj
&& SPROP_USERID(sprop
) == id
&&
608 !(wp
->flags
& JSWP_HELD
)) {
609 wp
->flags
|= JSWP_HELD
;
612 JS_LOCK_OBJ(cx
, obj
);
613 jsid propid
= sprop
->id
;
614 jsid userid
= SPROP_USERID(sprop
);
615 JSScope
*scope
= obj
->scope();
616 JS_UNLOCK_OBJ(cx
, obj
);
618 /* NB: wp is held, so we can safely dereference it still. */
619 if (!wp
->handler(cx
, obj
, propid
,
620 SPROP_HAS_VALID_SLOT(sprop
, scope
)
621 ? Jsvalify(obj
->getSlotMT(cx
, sprop
->slot
))
623 Jsvalify(vp
), wp
->closure
)) {
625 DropWatchPointAndUnlock(cx
, wp
, JSWP_HELD
);
630 * Create a pseudo-frame for the setter invocation so that any
631 * stack-walking security code under the setter will correctly
632 * identify the guilty party. So that the watcher appears to
633 * be active to obj_eval and other such code, point frame.pc
634 * at the JSOP_STOP at the end of the script.
636 * The pseudo-frame is not created for fast natives as they
637 * are treated as interpreter frame extensions and always
640 JSObject
*closure
= wp
->closure
;
641 Class
*clasp
= closure
->getClass();
644 if (clasp
== &js_FunctionClass
) {
645 fun
= GET_FUNCTION_PRIVATE(cx
, closure
);
646 script
= FUN_SCRIPT(fun
);
647 } else if (clasp
== &js_ScriptClass
) {
649 script
= (JSScript
*) closure
->getPrivate();
657 vplen
+= fun
->minArgs() + (fun
->isInterpreted() ? 0 : fun
->u
.n
.extra
);
658 uintN nfixed
= script
? script
->nfixed
: 0;
660 /* Destructor pops frame. */
662 ExecuteFrameGuard frame
;
664 if (fun
&& !fun
->isFastNative()) {
666 * Get a pointer to new frame/slots. This memory is not
667 * "claimed", so the code before pushExecuteFrame must not
668 * reenter the interpreter.
670 JSStackFrame
*down
= js_GetTopStackFrame(cx
);
671 if (!cx
->stack().getExecuteFrame(cx
, down
, vplen
, nfixed
, frame
)) {
673 DropWatchPointAndUnlock(cx
, wp
, JSWP_HELD
);
677 /* Initialize slots/frame. */
678 Value
*vp
= frame
.getvp();
679 MakeValueRangeGCSafe(vp
, vplen
);
680 vp
[0].setObject(*closure
);
681 vp
[1].setNull(); // satisfy LeaveTree assert
682 JSStackFrame
*fp
= frame
.getFrame();
684 MakeValueRangeGCSafe(fp
->slots(), nfixed
);
688 fp
->scopeChain
= closure
->getParent();
691 /* Initialize regs. */
692 regs
.pc
= script
? script
->code
: NULL
;
693 regs
.sp
= fp
->slots() + nfixed
;
695 /* Officially push |fp|. |frame|'s destructor pops. */
696 cx
->stack().pushExecuteFrame(cx
, frame
, regs
, NULL
);
698 /* Now that fp has been pushed, get the call object. */
699 if (script
&& fun
&& fun
->isHeavyweight() &&
700 !js_GetCallObject(cx
, fp
)) {
702 DropWatchPointAndUnlock(cx
, wp
, JSWP_HELD
);
707 JSBool ok
= !wp
->setter
||
708 (sprop
->hasSetterValue()
709 ? InternalCall(cx
, obj
,
710 ObjectValue(*CastAsObject(wp
->setter
)),
712 : callJSPropertyOpSetter(cx
, wp
->setter
, obj
, userid
, vp
));
714 /* Evil code can cause us to have an arguments object. */
715 if (frame
.getFrame())
716 frame
.getFrame()->putActivationObjects(cx
);
719 return DropWatchPointAndUnlock(cx
, wp
, JSWP_HELD
) && ok
;
727 js_watch_set_wrapper(JSContext
*cx
, JSObject
*obj
, uintN argc
, Value
*argv
,
734 funobj
= &argv
[-2].toObject();
735 wrapper
= GET_FUNCTION_PRIVATE(cx
, funobj
);
736 userid
= ATOM_TO_JSID(wrapper
->atom
);
738 return js_watch_set(cx
, obj
, userid
, rval
);
742 IsWatchedProperty(JSContext
*cx
, JSScopeProperty
*sprop
)
744 if (sprop
->hasSetterValue()) {
745 JSObject
*funobj
= sprop
->setterObject();
746 if (!funobj
|| !funobj
->isFunction())
749 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, funobj
);
750 return FUN_NATIVE(fun
) == js_watch_set_wrapper
;
752 return sprop
->setterOp() == js_watch_set
;
756 js_WrapWatchedSetter(JSContext
*cx
, jsid id
, uintN attrs
, PropertyOp setter
)
761 if (!(attrs
& JSPROP_SETTER
))
762 return &js_watch_set
; /* & to silence schoolmarmish MSVC */
764 if (JSID_IS_ATOM(id
)) {
765 atom
= JSID_TO_ATOM(id
);
766 } else if (JSID_IS_INT(id
)) {
767 if (!js_ValueToStringId(cx
, IdToValue(id
), &id
))
769 atom
= JSID_TO_ATOM(id
);
774 wrapper
= js_NewFunction(cx
, NULL
, js_watch_set_wrapper
, 1, 0,
775 setter
? CastAsObject(setter
)->getParent() : NULL
, atom
);
778 return CastAsPropertyOp(FUN_OBJECT(wrapper
));
781 JS_PUBLIC_API(JSBool
)
782 JS_SetWatchPoint(JSContext
*cx
, JSObject
*obj
, jsid id
,
783 JSWatchPointHandler handler
, void *closure
)
791 JSScopeProperty
*sprop
;
798 obj
= obj
->wrappedObject(cx
);
799 OBJ_TO_INNER_OBJECT(cx
, obj
);
803 AutoValueRooter
idroot(cx
);
804 if (JSID_IS_INT(id
)) {
807 if (!js_ValueToStringId(cx
, IdToValue(id
), &propid
))
809 propid
= js_CheckForStringIndex(propid
);
810 idroot
.set(IdToValue(propid
));
814 * If, by unwrapping and innerizing, we changed the object, check
815 * again to make sure that we're allowed to set a watch point.
817 if (origobj
!= obj
&& !CheckAccess(cx
, obj
, propid
, JSACC_WATCH
, &v
, &attrs
))
820 if (!obj
->isNative()) {
821 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
, JSMSG_CANT_WATCH
,
822 obj
->getClass()->name
);
826 if (!js_LookupProperty(cx
, obj
, propid
, &pobj
, &prop
))
828 sprop
= (JSScopeProperty
*) prop
;
831 /* Check for a deleted symbol watchpoint, which holds its property. */
832 sprop
= js_FindWatchPoint(rt
, obj
->scope(), propid
);
834 /* Make a new property in obj so we can watch for the first set. */
835 if (!js_DefineNativeProperty(cx
, obj
, propid
, UndefinedValue(), NULL
, NULL
,
836 JSPROP_ENUMERATE
, 0, 0, &prop
)) {
839 sprop
= (JSScopeProperty
*) prop
;
841 } else if (pobj
!= obj
) {
842 /* Clone the prototype property so we can watch the right object. */
843 AutoValueRooter
valroot(cx
);
844 PropertyOp getter
, setter
;
848 if (pobj
->isNative()) {
849 valroot
.set(SPROP_HAS_VALID_SLOT(sprop
, pobj
->scope())
850 ? pobj
->lockedGetSlot(sprop
->slot
)
852 getter
= sprop
->getter();
853 setter
= sprop
->setter();
854 attrs
= sprop
->attributes();
855 flags
= sprop
->getFlags();
856 shortid
= sprop
->shortid
;
857 JS_UNLOCK_OBJ(cx
, pobj
);
859 if (!pobj
->getProperty(cx
, propid
, valroot
.addr()) ||
860 !pobj
->getAttributes(cx
, propid
, &attrs
)) {
863 getter
= setter
= NULL
;
868 /* Recall that obj is native, whether or not pobj is native. */
869 if (!js_DefineNativeProperty(cx
, obj
, propid
, valroot
.value(),
870 getter
, setter
, attrs
, flags
,
874 sprop
= (JSScopeProperty
*) prop
;
878 * At this point, prop/sprop exists in obj, obj is locked, and we must
879 * unlock the object before returning.
883 wp
= FindWatchPoint(rt
, obj
->scope(), propid
);
886 watcher
= js_WrapWatchedSetter(cx
, propid
, sprop
->attributes(), sprop
->setter());
892 wp
= (JSWatchPoint
*) cx
->malloc(sizeof *wp
);
900 wp
->setter
= sprop
->setter();
901 wp
->flags
= JSWP_LIVE
;
903 /* XXXbe nest in obj lock here */
904 sprop
= js_ChangeNativePropertyAttrs(cx
, obj
, sprop
, 0, sprop
->attributes(),
905 sprop
->getter(), watcher
);
907 /* Self-link so DropWatchPointAndUnlock can JS_REMOVE_LINK it. */
908 JS_INIT_CLIST(&wp
->links
);
910 DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
);
917 * Now that wp is fully initialized, append it to rt's wp list.
918 * Because obj is locked we know that no other thread could have added
919 * a watchpoint for (obj, propid).
922 JS_ASSERT(!FindWatchPoint(rt
, obj
->scope(), propid
));
923 JS_APPEND_LINK(&wp
->links
, &rt
->watchPointList
);
924 ++rt
->debuggerMutations
;
926 wp
->handler
= handler
;
927 wp
->closure
= reinterpret_cast<JSObject
*>(closure
);
931 JS_UNLOCK_OBJ(cx
, obj
);
935 JS_PUBLIC_API(JSBool
)
936 JS_ClearWatchPoint(JSContext
*cx
, JSObject
*obj
, jsid id
,
937 JSWatchPointHandler
*handlerp
, void **closurep
)
944 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
945 &wp
->links
!= &rt
->watchPointList
;
946 wp
= (JSWatchPoint
*)wp
->links
.next
) {
947 if (wp
->object
== obj
&& SPROP_USERID(wp
->sprop
) == id
) {
949 *handlerp
= wp
->handler
;
951 *closurep
= wp
->closure
;
952 return DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
);
963 JS_PUBLIC_API(JSBool
)
964 JS_ClearWatchPointsForObject(JSContext
*cx
, JSObject
*obj
)
967 JSWatchPoint
*wp
, *next
;
972 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
973 &wp
->links
!= &rt
->watchPointList
;
975 next
= (JSWatchPoint
*)wp
->links
.next
;
976 if (wp
->object
== obj
) {
977 sample
= rt
->debuggerMutations
;
978 if (!DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
))
981 if (rt
->debuggerMutations
!= sample
+ 1)
982 next
= (JSWatchPoint
*)rt
->watchPointList
.next
;
989 JS_PUBLIC_API(JSBool
)
990 JS_ClearAllWatchPoints(JSContext
*cx
)
993 JSWatchPoint
*wp
, *next
;
998 for (wp
= (JSWatchPoint
*)rt
->watchPointList
.next
;
999 &wp
->links
!= &rt
->watchPointList
;
1001 next
= (JSWatchPoint
*)wp
->links
.next
;
1002 sample
= rt
->debuggerMutations
;
1003 if (!DropWatchPointAndUnlock(cx
, wp
, JSWP_LIVE
))
1006 if (rt
->debuggerMutations
!= sample
+ 1)
1007 next
= (JSWatchPoint
*)rt
->watchPointList
.next
;
1013 /************************************************************************/
1015 JS_PUBLIC_API(uintN
)
1016 JS_PCToLineNumber(JSContext
*cx
, JSScript
*script
, jsbytecode
*pc
)
1018 return js_PCToLineNumber(cx
, script
, pc
);
1021 JS_PUBLIC_API(jsbytecode
*)
1022 JS_LineNumberToPC(JSContext
*cx
, JSScript
*script
, uintN lineno
)
1024 return js_LineNumberToPC(script
, lineno
);
1027 JS_PUBLIC_API(uintN
)
1028 JS_GetFunctionArgumentCount(JSContext
*cx
, JSFunction
*fun
)
1033 JS_PUBLIC_API(JSBool
)
1034 JS_FunctionHasLocalNames(JSContext
*cx
, JSFunction
*fun
)
1036 return fun
->hasLocalNames();
1039 extern JS_PUBLIC_API(jsuword
*)
1040 JS_GetFunctionLocalNameArray(JSContext
*cx
, JSFunction
*fun
, void **markp
)
1042 *markp
= JS_ARENA_MARK(&cx
->tempPool
);
1043 return js_GetLocalNameArray(cx
, fun
, &cx
->tempPool
);
1046 extern JS_PUBLIC_API(JSAtom
*)
1047 JS_LocalNameToAtom(jsuword w
)
1049 return JS_LOCAL_NAME_TO_ATOM(w
);
1052 extern JS_PUBLIC_API(JSString
*)
1053 JS_AtomKey(JSAtom
*atom
)
1055 return ATOM_TO_STRING(atom
);
1058 extern JS_PUBLIC_API(void)
1059 JS_ReleaseFunctionLocalNameArray(JSContext
*cx
, void *mark
)
1061 JS_ARENA_RELEASE(&cx
->tempPool
, mark
);
1064 JS_PUBLIC_API(JSScript
*)
1065 JS_GetFunctionScript(JSContext
*cx
, JSFunction
*fun
)
1067 return FUN_SCRIPT(fun
);
1070 JS_PUBLIC_API(JSNative
)
1071 JS_GetFunctionNative(JSContext
*cx
, JSFunction
*fun
)
1073 return Jsvalify(FUN_NATIVE(fun
));
1076 JS_PUBLIC_API(JSFastNative
)
1077 JS_GetFunctionFastNative(JSContext
*cx
, JSFunction
*fun
)
1079 return Jsvalify(FUN_FAST_NATIVE(fun
));
1082 JS_PUBLIC_API(JSPrincipals
*)
1083 JS_GetScriptPrincipals(JSContext
*cx
, JSScript
*script
)
1085 return script
->principals
;
1088 /************************************************************************/
1091 * Stack Frame Iterator
1093 JS_PUBLIC_API(JSStackFrame
*)
1094 JS_FrameIterator(JSContext
*cx
, JSStackFrame
**iteratorp
)
1096 *iteratorp
= (*iteratorp
== NULL
) ? js_GetTopStackFrame(cx
) : (*iteratorp
)->down
;
1100 JS_PUBLIC_API(JSScript
*)
1101 JS_GetFrameScript(JSContext
*cx
, JSStackFrame
*fp
)
1106 JS_PUBLIC_API(jsbytecode
*)
1107 JS_GetFramePC(JSContext
*cx
, JSStackFrame
*fp
)
1112 JS_PUBLIC_API(JSStackFrame
*)
1113 JS_GetScriptedCaller(JSContext
*cx
, JSStackFrame
*fp
)
1115 return js_GetScriptedCaller(cx
, fp
);
1118 JS_PUBLIC_API(JSPrincipals
*)
1119 JS_StackFramePrincipals(JSContext
*cx
, JSStackFrame
*fp
)
1121 JSSecurityCallbacks
*callbacks
;
1124 callbacks
= JS_GetSecurityCallbacks(cx
);
1125 if (callbacks
&& callbacks
->findObjectPrincipals
) {
1126 if (FUN_OBJECT(fp
->fun
) != fp
->callee())
1127 return callbacks
->findObjectPrincipals(cx
, fp
->callee());
1132 return fp
->script
->principals
;
1137 js_EvalFramePrincipals(JSContext
*cx
, JSObject
*callee
, JSStackFrame
*caller
)
1139 JSPrincipals
*principals
, *callerPrincipals
;
1140 JSSecurityCallbacks
*callbacks
;
1142 callbacks
= JS_GetSecurityCallbacks(cx
);
1143 if (callbacks
&& callbacks
->findObjectPrincipals
)
1144 principals
= callbacks
->findObjectPrincipals(cx
, callee
);
1149 callerPrincipals
= JS_StackFramePrincipals(cx
, caller
);
1150 return (callerPrincipals
&& principals
&&
1151 callerPrincipals
->subsume(callerPrincipals
, principals
))
1156 JS_PUBLIC_API(JSPrincipals
*)
1157 JS_EvalFramePrincipals(JSContext
*cx
, JSStackFrame
*fp
, JSStackFrame
*caller
)
1159 return js_EvalFramePrincipals(cx
, fp
->callee(), caller
);
1162 JS_PUBLIC_API(void *)
1163 JS_GetFrameAnnotation(JSContext
*cx
, JSStackFrame
*fp
)
1165 if (fp
->annotation
&& fp
->script
) {
1166 JSPrincipals
*principals
= JS_StackFramePrincipals(cx
, fp
);
1168 if (principals
&& principals
->globalPrivilegesEnabled(cx
, principals
)) {
1170 * Give out an annotation only if privileges have not been revoked
1171 * or disabled globally.
1173 return fp
->annotation
;
1181 JS_SetFrameAnnotation(JSContext
*cx
, JSStackFrame
*fp
, void *annotation
)
1183 fp
->annotation
= annotation
;
1186 JS_PUBLIC_API(void *)
1187 JS_GetFramePrincipalArray(JSContext
*cx
, JSStackFrame
*fp
)
1189 JSPrincipals
*principals
;
1191 principals
= JS_StackFramePrincipals(cx
, fp
);
1194 return principals
->getPrincipalArray(cx
, principals
);
1197 JS_PUBLIC_API(JSBool
)
1198 JS_IsNativeFrame(JSContext
*cx
, JSStackFrame
*fp
)
1203 /* this is deprecated, use JS_GetFrameScopeChain instead */
1204 JS_PUBLIC_API(JSObject
*)
1205 JS_GetFrameObject(JSContext
*cx
, JSStackFrame
*fp
)
1207 return fp
->scopeChain
;
1210 JS_PUBLIC_API(JSObject
*)
1211 JS_GetFrameScopeChain(JSContext
*cx
, JSStackFrame
*fp
)
1213 JS_ASSERT(cx
->stack().contains(fp
));
1215 /* Force creation of argument and call objects if not yet created */
1216 (void) JS_GetFrameCallObject(cx
, fp
);
1217 return js_GetScopeChain(cx
, fp
);
1220 JS_PUBLIC_API(JSObject
*)
1221 JS_GetFrameCallObject(JSContext
*cx
, JSStackFrame
*fp
)
1223 JS_ASSERT(cx
->stack().contains(fp
));
1228 /* Force creation of argument object if not yet created */
1229 (void) js_GetArgsObject(cx
, fp
);
1232 * XXX ill-defined: null return here means error was reported, unlike a
1233 * null returned above or in the #else
1235 return js_GetCallObject(cx
, fp
);
1238 JS_PUBLIC_API(JSObject
*)
1239 JS_GetFrameThis(JSContext
*cx
, JSStackFrame
*fp
)
1241 return fp
->getThisObject(cx
);
1244 JS_PUBLIC_API(JSFunction
*)
1245 JS_GetFrameFunction(JSContext
*cx
, JSStackFrame
*fp
)
1250 JS_PUBLIC_API(JSObject
*)
1251 JS_GetFrameFunctionObject(JSContext
*cx
, JSStackFrame
*fp
)
1256 JS_ASSERT(fp
->callee()->isFunction());
1257 JS_ASSERT(fp
->callee()->getPrivate() == fp
->fun
);
1258 return fp
->callee();
1261 JS_PUBLIC_API(JSBool
)
1262 JS_IsConstructorFrame(JSContext
*cx
, JSStackFrame
*fp
)
1264 return (fp
->flags
& JSFRAME_CONSTRUCTING
) != 0;
1267 JS_PUBLIC_API(JSObject
*)
1268 JS_GetFrameCalleeObject(JSContext
*cx
, JSStackFrame
*fp
)
1270 return fp
->callee();
1273 JS_PUBLIC_API(JSBool
)
1274 JS_IsDebuggerFrame(JSContext
*cx
, JSStackFrame
*fp
)
1276 return (fp
->flags
& JSFRAME_DEBUGGER
) != 0;
1279 JS_PUBLIC_API(jsval
)
1280 JS_GetFrameReturnValue(JSContext
*cx
, JSStackFrame
*fp
)
1282 return Jsvalify(fp
->rval
);
1286 JS_SetFrameReturnValue(JSContext
*cx
, JSStackFrame
*fp
, jsval rval
)
1288 fp
->rval
= Valueify(rval
);
1291 /************************************************************************/
1293 JS_PUBLIC_API(const char *)
1294 JS_GetScriptFilename(JSContext
*cx
, JSScript
*script
)
1296 return script
->filename
;
1299 JS_PUBLIC_API(uintN
)
1300 JS_GetScriptBaseLineNumber(JSContext
*cx
, JSScript
*script
)
1302 return script
->lineno
;
1305 JS_PUBLIC_API(uintN
)
1306 JS_GetScriptLineExtent(JSContext
*cx
, JSScript
*script
)
1308 return js_GetScriptLineExtent(script
);
1311 JS_PUBLIC_API(JSVersion
)
1312 JS_GetScriptVersion(JSContext
*cx
, JSScript
*script
)
1314 return (JSVersion
) (script
->version
& JSVERSION_MASK
);
1317 /***************************************************************************/
1320 JS_SetNewScriptHook(JSRuntime
*rt
, JSNewScriptHook hook
, void *callerdata
)
1322 rt
->globalDebugHooks
.newScriptHook
= hook
;
1323 rt
->globalDebugHooks
.newScriptHookData
= callerdata
;
1327 JS_SetDestroyScriptHook(JSRuntime
*rt
, JSDestroyScriptHook hook
,
1330 rt
->globalDebugHooks
.destroyScriptHook
= hook
;
1331 rt
->globalDebugHooks
.destroyScriptHookData
= callerdata
;
1334 /***************************************************************************/
1336 JS_PUBLIC_API(JSBool
)
1337 JS_EvaluateUCInStackFrame(JSContext
*cx
, JSStackFrame
*fp
,
1338 const jschar
*chars
, uintN length
,
1339 const char *filename
, uintN lineno
,
1342 JS_ASSERT_NOT_ON_TRACE(cx
);
1344 JSObject
*scobj
= JS_GetFrameScopeChain(cx
, fp
);
1349 * NB: This function breaks the assumption that the compiler can see all
1350 * calls and properly compute a static level. In order to get around this,
1351 * we use a static level that will cause us not to attempt to optimize
1352 * variable references made by this frame.
1354 JSScript
*script
= Compiler::compileScript(cx
, scobj
, fp
, JS_StackFramePrincipals(cx
, fp
),
1355 TCF_COMPILE_N_GO
, chars
, length
, NULL
,
1356 filename
, lineno
, NULL
,
1357 UpvarCookie::UPVAR_LEVEL_LIMIT
);
1362 bool ok
= !!Execute(cx
, scobj
, script
, fp
, JSFRAME_DEBUGGER
| JSFRAME_EVAL
, Valueify(rval
));
1364 js_DestroyScript(cx
, script
);
1368 JS_PUBLIC_API(JSBool
)
1369 JS_EvaluateInStackFrame(JSContext
*cx
, JSStackFrame
*fp
,
1370 const char *bytes
, uintN length
,
1371 const char *filename
, uintN lineno
,
1376 size_t len
= length
;
1378 chars
= js_InflateString(cx
, bytes
, &len
);
1381 length
= (uintN
) len
;
1382 ok
= JS_EvaluateUCInStackFrame(cx
, fp
, chars
, length
, filename
, lineno
,
1389 /************************************************************************/
1391 /* XXXbe this all needs to be reworked to avoid requiring JSScope types. */
1393 JS_PUBLIC_API(JSScopeProperty
*)
1394 JS_PropertyIterator(JSObject
*obj
, JSScopeProperty
**iteratorp
)
1396 JSScopeProperty
*sprop
;
1400 scope
= obj
->scope();
1402 /* XXXbe minor(?) incompatibility: iterate in reverse definition order */
1403 sprop
= sprop
? sprop
->parent
: scope
->lastProperty();
1408 JS_PUBLIC_API(JSBool
)
1409 JS_GetPropertyDesc(JSContext
*cx
, JSObject
*obj
, JSScopeProperty
*sprop
,
1412 pd
->id
= IdToJsval(sprop
->id
);
1414 JSBool wasThrowing
= cx
->throwing
;
1415 AutoValueRooter
lastException(cx
, cx
->exception
);
1416 cx
->throwing
= JS_FALSE
;
1418 if (!js_GetProperty(cx
, obj
, sprop
->id
, Valueify(&pd
->value
))) {
1419 if (!cx
->throwing
) {
1420 pd
->flags
= JSPD_ERROR
;
1421 pd
->value
= JSVAL_VOID
;
1423 pd
->flags
= JSPD_EXCEPTION
;
1424 pd
->value
= Jsvalify(cx
->exception
);
1430 cx
->throwing
= wasThrowing
;
1432 cx
->exception
= lastException
.value();
1434 pd
->flags
|= (sprop
->enumerable() ? JSPD_ENUMERATE
: 0)
1435 | (!sprop
->writable() ? JSPD_READONLY
: 0)
1436 | (!sprop
->configurable() ? JSPD_PERMANENT
: 0);
1438 if (sprop
->getter() == js_GetCallArg
) {
1439 pd
->slot
= sprop
->shortid
;
1440 pd
->flags
|= JSPD_ARGUMENT
;
1441 } else if (sprop
->getter() == js_GetCallVar
) {
1442 pd
->slot
= sprop
->shortid
;
1443 pd
->flags
|= JSPD_VARIABLE
;
1447 pd
->alias
= JSVAL_VOID
;
1449 JSScope
*scope
= obj
->scope();
1450 if (SPROP_HAS_VALID_SLOT(sprop
, scope
)) {
1451 JSScopeProperty
*aprop
;
1452 for (aprop
= scope
->lastProperty(); aprop
; aprop
= aprop
->parent
) {
1453 if (aprop
!= sprop
&& aprop
->slot
== sprop
->slot
) {
1454 pd
->alias
= IdToJsval(aprop
->id
);
1462 JS_PUBLIC_API(JSBool
)
1463 JS_GetPropertyDescArray(JSContext
*cx
, JSObject
*obj
, JSPropertyDescArray
*pda
)
1468 JSScopeProperty
*sprop
;
1470 Class
*clasp
= obj
->getClass();
1471 if (!obj
->isNative() || (clasp
->flags
& JSCLASS_NEW_ENUMERATE
)) {
1472 JS_ReportErrorNumber(cx
, js_GetErrorMessage
, NULL
,
1473 JSMSG_CANT_DESCRIBE_PROPS
, clasp
->name
);
1476 if (!clasp
->enumerate(cx
, obj
))
1479 /* have no props, or object's scope has not mutated from that of proto */
1480 scope
= obj
->scope();
1481 if (scope
->entryCount
== 0) {
1487 n
= scope
->entryCount
;
1488 pd
= (JSPropertyDesc
*) cx
->malloc((size_t)n
* sizeof(JSPropertyDesc
));
1492 for (sprop
= scope
->lastProperty(); sprop
; sprop
= sprop
->parent
) {
1493 if (!js_AddRoot(cx
, Valueify(&pd
[i
].id
), NULL
))
1495 if (!js_AddRoot(cx
, Valueify(&pd
[i
].value
), NULL
))
1497 if (!JS_GetPropertyDesc(cx
, obj
, sprop
, &pd
[i
]))
1499 if ((pd
[i
].flags
& JSPD_ALIAS
) && !js_AddRoot(cx
, Valueify(&pd
[i
].alias
), NULL
))
1509 pda
->length
= i
+ 1;
1511 JS_PutPropertyDescArray(cx
, pda
);
1516 JS_PutPropertyDescArray(JSContext
*cx
, JSPropertyDescArray
*pda
)
1522 for (i
= 0; i
< pda
->length
; i
++) {
1523 js_RemoveRoot(cx
->runtime
, &pd
[i
].id
);
1524 js_RemoveRoot(cx
->runtime
, &pd
[i
].value
);
1525 if (pd
[i
].flags
& JSPD_ALIAS
)
1526 js_RemoveRoot(cx
->runtime
, &pd
[i
].alias
);
1531 /************************************************************************/
1534 SetupFakeFrame(JSContext
*cx
, ExecuteFrameGuard
&frame
, JSFrameRegs
®s
, JSObject
*scopeobj
)
1536 JSFunction
*fun
= GET_FUNCTION_PRIVATE(cx
, scopeobj
);
1537 JS_ASSERT(fun
->minArgs() == 0 && !fun
->isInterpreted() && fun
->u
.n
.extra
== 0);
1539 const uintN vplen
= 2;
1540 const uintN nfixed
= 0;
1541 if (!cx
->stack().getExecuteFrame(cx
, js_GetTopStackFrame(cx
), vplen
, nfixed
, frame
))
1544 Value
*vp
= frame
.getvp();
1546 vp
[0].setObject(*scopeobj
);
1547 vp
[1].setNull(); // satisfy LeaveTree assert
1549 JSStackFrame
*fp
= frame
.getFrame();
1553 fp
->scopeChain
= scopeobj
->getGlobal();
1556 regs
.sp
= fp
->slots();
1558 cx
->stack().pushExecuteFrame(cx
, frame
, regs
, NULL
);
1562 JS_FRIEND_API(JSBool
)
1563 js_GetPropertyByIdWithFakeFrame(JSContext
*cx
, JSObject
*obj
, JSObject
*scopeobj
, jsid id
,
1566 ExecuteFrameGuard frame
;
1569 if (!SetupFakeFrame(cx
, frame
, regs
, scopeobj
))
1572 bool ok
= JS_GetPropertyById(cx
, obj
, id
, vp
);
1573 frame
.getFrame()->putActivationObjects(cx
);
1577 JS_FRIEND_API(JSBool
)
1578 js_SetPropertyByIdWithFakeFrame(JSContext
*cx
, JSObject
*obj
, JSObject
*scopeobj
, jsid id
,
1581 ExecuteFrameGuard frame
;
1584 if (!SetupFakeFrame(cx
, frame
, regs
, scopeobj
))
1587 bool ok
= JS_SetPropertyById(cx
, obj
, id
, vp
);
1588 frame
.getFrame()->putActivationObjects(cx
);
1592 JS_FRIEND_API(JSBool
)
1593 js_CallFunctionValueWithFakeFrame(JSContext
*cx
, JSObject
*obj
, JSObject
*scopeobj
, jsval funval
,
1594 uintN argc
, jsval
*argv
, jsval
*rval
)
1596 ExecuteFrameGuard frame
;
1599 if (!SetupFakeFrame(cx
, frame
, regs
, scopeobj
))
1602 bool ok
= JS_CallFunctionValue(cx
, obj
, funval
, argc
, argv
, rval
);
1603 frame
.getFrame()->putActivationObjects(cx
);
1607 /************************************************************************/
1609 JS_PUBLIC_API(JSBool
)
1610 JS_SetDebuggerHandler(JSRuntime
*rt
, JSDebuggerHandler handler
, void *closure
)
1612 rt
->globalDebugHooks
.debuggerHandler
= handler
;
1613 rt
->globalDebugHooks
.debuggerHandlerData
= closure
;
1617 JS_PUBLIC_API(JSBool
)
1618 JS_SetSourceHandler(JSRuntime
*rt
, JSSourceHandler handler
, void *closure
)
1620 rt
->globalDebugHooks
.sourceHandler
= handler
;
1621 rt
->globalDebugHooks
.sourceHandlerData
= closure
;
1625 JS_PUBLIC_API(JSBool
)
1626 JS_SetExecuteHook(JSRuntime
*rt
, JSInterpreterHook hook
, void *closure
)
1628 rt
->globalDebugHooks
.executeHook
= hook
;
1629 rt
->globalDebugHooks
.executeHookData
= closure
;
1633 JS_PUBLIC_API(JSBool
)
1634 JS_SetCallHook(JSRuntime
*rt
, JSInterpreterHook hook
, void *closure
)
1638 AutoLockGC
lock(rt
);
1639 bool wasInhibited
= rt
->debuggerInhibitsJIT();
1641 rt
->globalDebugHooks
.callHook
= hook
;
1642 rt
->globalDebugHooks
.callHookData
= closure
;
1644 JITInhibitingHookChange(rt
, wasInhibited
);
1652 JS_PUBLIC_API(JSBool
)
1653 JS_SetThrowHook(JSRuntime
*rt
, JSThrowHook hook
, void *closure
)
1655 rt
->globalDebugHooks
.throwHook
= hook
;
1656 rt
->globalDebugHooks
.throwHookData
= closure
;
1660 JS_PUBLIC_API(JSBool
)
1661 JS_SetDebugErrorHook(JSRuntime
*rt
, JSDebugErrorHook hook
, void *closure
)
1663 rt
->globalDebugHooks
.debugErrorHook
= hook
;
1664 rt
->globalDebugHooks
.debugErrorHookData
= closure
;
1668 /************************************************************************/
1670 JS_PUBLIC_API(size_t)
1671 JS_GetObjectTotalSize(JSContext
*cx
, JSObject
*obj
)
1676 nbytes
= sizeof *obj
;
1678 nbytes
+= (obj
->dslots
[-1].toPrivateUint32() - JS_INITIAL_NSLOTS
+ 1)
1679 * sizeof obj
->dslots
[0];
1681 if (obj
->isNative()) {
1682 scope
= obj
->scope();
1683 if (!scope
->isSharedEmpty()) {
1684 nbytes
+= sizeof *scope
;
1685 nbytes
+= SCOPE_CAPACITY(scope
) * sizeof(JSScopeProperty
*);
1692 GetAtomTotalSize(JSContext
*cx
, JSAtom
*atom
)
1696 nbytes
= sizeof(JSAtom
*) + sizeof(JSDHashEntryStub
);
1697 nbytes
+= sizeof(JSString
);
1698 nbytes
+= (ATOM_TO_STRING(atom
)->flatLength() + 1) * sizeof(jschar
);
1702 JS_PUBLIC_API(size_t)
1703 JS_GetFunctionTotalSize(JSContext
*cx
, JSFunction
*fun
)
1707 nbytes
= sizeof *fun
;
1708 nbytes
+= JS_GetObjectTotalSize(cx
, FUN_OBJECT(fun
));
1709 if (FUN_INTERPRETED(fun
))
1710 nbytes
+= JS_GetScriptTotalSize(cx
, fun
->u
.i
.script
);
1712 nbytes
+= GetAtomTotalSize(cx
, fun
->atom
);
1718 JS_PUBLIC_API(size_t)
1719 JS_GetScriptTotalSize(JSContext
*cx
, JSScript
*script
)
1721 size_t nbytes
, pbytes
;
1723 jssrcnote
*sn
, *notes
;
1724 JSObjectArray
*objarray
;
1725 JSPrincipals
*principals
;
1727 nbytes
= sizeof *script
;
1728 if (script
->u
.object
)
1729 nbytes
+= JS_GetObjectTotalSize(cx
, script
->u
.object
);
1731 nbytes
+= script
->length
* sizeof script
->code
[0];
1732 nbytes
+= script
->atomMap
.length
* sizeof script
->atomMap
.vector
[0];
1733 for (i
= 0; i
< script
->atomMap
.length
; i
++)
1734 nbytes
+= GetAtomTotalSize(cx
, script
->atomMap
.vector
[i
]);
1736 if (script
->filename
)
1737 nbytes
+= strlen(script
->filename
) + 1;
1739 notes
= script
->notes();
1740 for (sn
= notes
; !SN_IS_TERMINATOR(sn
); sn
= SN_NEXT(sn
))
1742 nbytes
+= (sn
- notes
+ 1) * sizeof *sn
;
1744 if (script
->objectsOffset
!= 0) {
1745 objarray
= script
->objects();
1746 i
= objarray
->length
;
1747 nbytes
+= sizeof *objarray
+ i
* sizeof objarray
->vector
[0];
1749 nbytes
+= JS_GetObjectTotalSize(cx
, objarray
->vector
[--i
]);
1753 if (script
->regexpsOffset
!= 0) {
1754 objarray
= script
->regexps();
1755 i
= objarray
->length
;
1756 nbytes
+= sizeof *objarray
+ i
* sizeof objarray
->vector
[0];
1758 nbytes
+= JS_GetObjectTotalSize(cx
, objarray
->vector
[--i
]);
1762 if (script
->trynotesOffset
!= 0) {
1763 nbytes
+= sizeof(JSTryNoteArray
) +
1764 script
->trynotes()->length
* sizeof(JSTryNote
);
1767 principals
= script
->principals
;
1769 JS_ASSERT(principals
->refcount
);
1770 pbytes
= sizeof *principals
;
1771 if (principals
->refcount
> 1)
1772 pbytes
= JS_HOWMANY(pbytes
, principals
->refcount
);
1779 JS_PUBLIC_API(uint32
)
1780 JS_GetTopScriptFilenameFlags(JSContext
*cx
, JSStackFrame
*fp
)
1783 fp
= js_GetTopStackFrame(cx
);
1786 return JS_GetScriptFilenameFlags(fp
->script
);
1792 JS_PUBLIC_API(uint32
)
1793 JS_GetScriptFilenameFlags(JSScript
*script
)
1796 if (!script
->filename
)
1797 return JSFILENAME_NULL
;
1798 return js_GetScriptFilenameFlags(script
->filename
);
1801 JS_PUBLIC_API(JSBool
)
1802 JS_FlagScriptFilenamePrefix(JSRuntime
*rt
, const char *prefix
, uint32 flags
)
1804 if (!js_SaveScriptFilenameRT(rt
, prefix
, flags
))
1809 JS_PUBLIC_API(JSBool
)
1810 JS_IsSystemObject(JSContext
*cx
, JSObject
*obj
)
1812 return obj
->isSystem();
1815 JS_PUBLIC_API(JSBool
)
1816 JS_MakeSystemObject(JSContext
*cx
, JSObject
*obj
)
1822 /************************************************************************/
1824 JS_PUBLIC_API(const JSDebugHooks
*)
1825 JS_GetGlobalDebugHooks(JSRuntime
*rt
)
1827 return &rt
->globalDebugHooks
;
1830 const JSDebugHooks js_NullDebugHooks
= {};
1832 JS_PUBLIC_API(JSDebugHooks
*)
1833 JS_SetContextDebugHooks(JSContext
*cx
, const JSDebugHooks
*hooks
)
1836 if (hooks
!= &cx
->runtime
->globalDebugHooks
&& hooks
!= &js_NullDebugHooks
)
1840 AutoLockGC
lock(cx
->runtime
);
1842 JSDebugHooks
*old
= const_cast<JSDebugHooks
*>(cx
->debugHooks
);
1843 cx
->debugHooks
= hooks
;
1845 cx
->updateJITEnabled();
1850 JS_PUBLIC_API(JSDebugHooks
*)
1851 JS_ClearContextDebugHooks(JSContext
*cx
)
1853 return JS_SetContextDebugHooks(cx
, &js_NullDebugHooks
);
1858 #include <CHUD/CHUD.h>
1860 JS_PUBLIC_API(JSBool
)
1861 JS_StartChudRemote()
1863 if (chudIsRemoteAccessAcquired() &&
1864 (chudStartRemotePerfMonitor("Mozilla") == chudSuccess
)) {
1871 JS_PUBLIC_API(JSBool
)
1874 if (chudIsRemoteAccessAcquired() &&
1875 (chudStopRemotePerfMonitor() == chudSuccess
)) {
1882 JS_PUBLIC_API(JSBool
)
1885 if (!chudIsInitialized() && (chudInitialize() != chudSuccess
))
1888 if (chudAcquireRemoteAccess() != chudSuccess
)
1894 JS_PUBLIC_API(JSBool
)
1895 JS_DisconnectShark()
1897 if (chudIsRemoteAccessAcquired() && (chudReleaseRemoteAccess() != chudSuccess
))
1903 JS_FRIEND_API(JSBool
)
1904 js_StartShark(JSContext
*cx
, JSObject
*obj
,
1905 uintN argc
, jsval
*argv
, jsval
*rval
)
1907 if (!JS_StartChudRemote()) {
1908 JS_ReportError(cx
, "Error starting CHUD.");
1915 JS_FRIEND_API(JSBool
)
1916 js_StopShark(JSContext
*cx
, JSObject
*obj
,
1917 uintN argc
, jsval
*argv
, jsval
*rval
)
1919 if (!JS_StopChudRemote()) {
1920 JS_ReportError(cx
, "Error stopping CHUD.");
1927 JS_FRIEND_API(JSBool
)
1928 js_ConnectShark(JSContext
*cx
, JSObject
*obj
,
1929 uintN argc
, jsval
*argv
, jsval
*rval
)
1931 if (!JS_ConnectShark()) {
1932 JS_ReportError(cx
, "Error connecting to Shark.");
1939 JS_FRIEND_API(JSBool
)
1940 js_DisconnectShark(JSContext
*cx
, JSObject
*obj
,
1941 uintN argc
, jsval
*argv
, jsval
*rval
)
1943 if (!JS_DisconnectShark()) {
1944 JS_ReportError(cx
, "Error disconnecting from Shark.");
1951 #endif /* MOZ_SHARK */
1953 #ifdef MOZ_CALLGRIND
1955 #include <valgrind/callgrind.h>
1957 JS_FRIEND_API(JSBool
)
1958 js_StartCallgrind(JSContext
*cx
, JSObject
*obj
,
1959 uintN argc
, jsval
*argv
, jsval
*rval
)
1961 CALLGRIND_START_INSTRUMENTATION
;
1962 CALLGRIND_ZERO_STATS
;
1966 JS_FRIEND_API(JSBool
)
1967 js_StopCallgrind(JSContext
*cx
, JSObject
*obj
,
1968 uintN argc
, jsval
*argv
, jsval
*rval
)
1970 CALLGRIND_STOP_INSTRUMENTATION
;
1974 JS_FRIEND_API(JSBool
)
1975 js_DumpCallgrind(JSContext
*cx
, JSObject
*obj
,
1976 uintN argc
, jsval
*argv
, jsval
*rval
)
1981 if (argc
> 0 && JSVAL_IS_STRING(argv
[0])) {
1982 str
= JSVAL_TO_STRING(argv
[0]);
1983 cstr
= js_DeflateString(cx
, str
->chars(), str
->length());
1985 CALLGRIND_DUMP_STATS_AT(cstr
);
1990 CALLGRIND_DUMP_STATS
;
1995 #endif /* MOZ_CALLGRIND */
1998 #include <VTuneApi.h>
2000 static const char *vtuneErrorMessages
[] = {
2001 "unknown, error #0",
2002 "invalid 'max samples' field",
2003 "invalid 'samples per buffer' field",
2004 "invalid 'sample interval' field",
2006 "sample file in use",
2007 "invalid 'number of events' field",
2008 "unknown, error #7",
2011 "VTStopSampling called without calling VTStartSampling",
2012 "no events selected for event-based sampling",
2013 "events selected cannot be run together",
2014 "no sampling parameters",
2015 "sample database already exists",
2016 "sampling already started",
2017 "time-based sampling not supported",
2018 "invalid 'sampling parameters size' field",
2019 "invalid 'event size' field",
2020 "sampling file already bound",
2021 "invalid event path",
2023 "invalid 'global options' field",
2027 JS_FRIEND_API(JSBool
)
2028 js_StartVtune(JSContext
*cx
, JSObject
*obj
,
2029 uintN argc
, jsval
*argv
, jsval
*rval
)
2031 VTUNE_EVENT events
[] = {
2032 { 1000000, 0, 0, 0, "CPU_CLK_UNHALTED.CORE" },
2033 { 1000000, 0, 0, 0, "INST_RETIRED.ANY" },
2036 U32 n_events
= sizeof(events
) / sizeof(VTUNE_EVENT
);
2037 char *default_filename
= "mozilla-vtune.tb5";
2041 VTUNE_SAMPLING_PARAMS params
=
2042 sizeof(VTUNE_SAMPLING_PARAMS
),
2043 sizeof(VTUNE_EVENT
),
2044 0, 0, /* Reserved fields */
2045 1, /* Initialize in "paused" state */
2046 0, /* Max samples, or 0 for "continuous" */
2047 4096, /* Samples per buffer */
2048 0.1, /* Sampling interval in ms */
2049 1, /* 1 for event-based sampling, 0 for time-based */
2056 if (argc
> 0 && JSVAL_IS_STRING(argv
[0])) {
2057 str
= JSVAL_TO_STRING(argv
[0]);
2058 params
.tb5Filename
= js_DeflateString(cx
, str
->chars(), str
->length());
2061 status
= VTStartSampling(¶ms
);
2063 if (params
.tb5Filename
!= default_filename
)
2064 cx
->free(params
.tb5Filename
);
2067 if (status
== VTAPI_MULTIPLE_RUNS
)
2069 if (status
< sizeof(vtuneErrorMessages
))
2070 JS_ReportError(cx
, "Vtune setup error: %s",
2071 vtuneErrorMessages
[status
]);
2073 JS_ReportError(cx
, "Vtune setup error: %d",
2080 JS_FRIEND_API(JSBool
)
2081 js_StopVtune(JSContext
*cx
, JSObject
*obj
,
2082 uintN argc
, jsval
*argv
, jsval
*rval
)
2084 U32 status
= VTStopSampling(1);
2086 if (status
< sizeof(vtuneErrorMessages
))
2087 JS_ReportError(cx
, "Vtune shutdown error: %s",
2088 vtuneErrorMessages
[status
]);
2090 JS_ReportError(cx
, "Vtune shutdown error: %d",
2097 JS_FRIEND_API(JSBool
)
2098 js_PauseVtune(JSContext
*cx
, JSObject
*obj
,
2099 uintN argc
, jsval
*argv
, jsval
*rval
)
2105 JS_FRIEND_API(JSBool
)
2106 js_ResumeVtune(JSContext
*cx
, JSObject
*obj
,
2107 uintN argc
, jsval
*argv
, jsval
*rval
)
2113 #endif /* MOZ_VTUNE */
2117 * Ethogram - Javascript wrapper for TraceVis state
2119 * ethology: The scientific study of animal behavior,
2120 * especially as it occurs in a natural environment.
2121 * ethogram: A pictorial catalog of the behavioral patterns of
2122 * an organism or a species.
2126 #include <windows.h>
2128 #include <sys/time.h>
2130 #include "jstracer.h"
2132 #define ETHOGRAM_BUF_SIZE 65536
2135 ethogram_construct(JSContext
*cx
, JSObject
*obj
,
2136 uintN argc
, jsval
*argv
, jsval
*rval
);
2138 ethogram_finalize(JSContext
*cx
, JSObject
*obj
);
2140 static JSClass ethogram_class
= {
2142 JSCLASS_HAS_PRIVATE
,
2143 JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
, JS_PropertyStub
,
2144 JS_EnumerateStub
, JS_ResolveStub
, JS_ConvertStub
, ethogram_finalize
,
2145 JSCLASS_NO_OPTIONAL_MEMBERS
2148 struct EthogramEvent
{
2150 TraceVisExitReason r
;
2158 compare_strings(const void *k1
, const void *k2
)
2160 return strcmp((const char *) k1
, (const char *) k2
) == 0;
2163 class EthogramEventBuffer
{
2165 EthogramEvent mBuf
[ETHOGRAM_BUF_SIZE
];
2168 JSObject
*mFilenames
;
2171 struct EthogramScriptEntry
{
2173 JSString
*jsfilename
;
2175 EthogramScriptEntry
*next
;
2177 EthogramScriptEntry
*mScripts
;
2181 ethogram_construct(JSContext
*cx
, JSObject
*obj
,
2182 uintN argc
, jsval
*argv
, jsval
*rval
);
2184 inline void push(TraceVisState s
, TraceVisExitReason r
, char *filename
, int lineno
) {
2185 mBuf
[mWritePos
].s
= s
;
2186 mBuf
[mWritePos
].r
= r
;
2189 GetSystemTimeAsFileTime(&now
);
2190 unsigned long long raw_us
= 0.1 *
2191 (((unsigned long long) now
.dwHighDateTime
<< 32ULL) |
2192 (unsigned long long) now
.dwLowDateTime
);
2193 unsigned int sec
= raw_us
/ 1000000L;
2194 unsigned int usec
= raw_us
% 1000000L;
2195 mBuf
[mWritePos
].ts
= sec
- mStartSecond
;
2196 mBuf
[mWritePos
].tus
= usec
;
2199 gettimeofday(&tv
, NULL
);
2200 mBuf
[mWritePos
].ts
= tv
.tv_sec
- mStartSecond
;
2201 mBuf
[mWritePos
].tus
= tv
.tv_usec
;
2204 JSString
*jsfilename
= findScript(filename
);
2205 mBuf
[mWritePos
].filename
= jsfilename
;
2206 mBuf
[mWritePos
].lineno
= lineno
;
2208 mWritePos
= (mWritePos
+ 1) % ETHOGRAM_BUF_SIZE
;
2209 if (mWritePos
== mReadPos
) {
2210 mReadPos
= (mWritePos
+ 1) % ETHOGRAM_BUF_SIZE
;
2214 inline EthogramEvent
*pop() {
2215 EthogramEvent
*e
= &mBuf
[mReadPos
];
2216 mReadPos
= (mReadPos
+ 1) % ETHOGRAM_BUF_SIZE
;
2221 return (mReadPos
== mWritePos
);
2224 EthogramScriptEntry
*addScript(JSContext
*cx
, JSObject
*obj
, char *filename
, JSString
*jsfilename
) {
2225 JSHashNumber hash
= JS_HashString(filename
);
2226 JSHashEntry
**hep
= JS_HashTableRawLookup(traceVisScriptTable
, hash
, filename
);
2230 JS_HashTableRawAdd(traceVisScriptTable
, hep
, hash
, filename
, this);
2232 EthogramScriptEntry
* entry
= (EthogramScriptEntry
*) JS_malloc(cx
, sizeof(EthogramScriptEntry
));
2236 entry
->next
= mScripts
;
2238 entry
->filename
= filename
;
2239 entry
->jsfilename
= jsfilename
;
2244 void removeScripts(JSContext
*cx
) {
2245 EthogramScriptEntry
*se
= mScripts
;
2246 while (se
!= NULL
) {
2247 char *filename
= se
->filename
;
2249 JSHashNumber hash
= JS_HashString(filename
);
2250 JSHashEntry
**hep
= JS_HashTableRawLookup(traceVisScriptTable
, hash
, filename
);
2251 JSHashEntry
*he
= *hep
;
2253 /* we hardly knew he */
2254 JS_HashTableRawRemove(traceVisScriptTable
, hep
, he
);
2257 EthogramScriptEntry
*se_head
= se
;
2259 JS_free(cx
, se_head
);
2263 JSString
*findScript(char *filename
) {
2264 EthogramScriptEntry
*se
= mScripts
;
2265 while (se
!= NULL
) {
2266 if (compare_strings(se
->filename
, filename
))
2267 return (se
->jsfilename
);
2273 JSObject
*filenames() {
2278 if (mWritePos
< mReadPos
)
2279 return (mWritePos
+ ETHOGRAM_BUF_SIZE
) - mReadPos
;
2281 return mWritePos
- mReadPos
;
2285 static char jstv_empty
[] = "<null>";
2288 jstv_Filename(JSStackFrame
*fp
)
2290 while (fp
&& fp
->script
== NULL
)
2292 return (fp
&& fp
->script
&& fp
->script
->filename
)
2293 ? (char *)fp
->script
->filename
2297 jstv_Lineno(JSContext
*cx
, JSStackFrame
*fp
)
2299 while (fp
&& fp
->pc(cx
) == NULL
)
2301 return (fp
&& fp
->pc(cx
)) ? js_FramePCToLineNumber(cx
, fp
) : 0;
2304 /* Collect states here and distribute to a matching buffer, if any */
2306 js::StoreTraceVisState(JSContext
*cx
, TraceVisState s
, TraceVisExitReason r
)
2308 JSStackFrame
*fp
= cx
->fp
;
2310 char *script_file
= jstv_Filename(fp
);
2311 JSHashNumber hash
= JS_HashString(script_file
);
2313 JSHashEntry
**hep
= JS_HashTableRawLookup(traceVisScriptTable
, hash
, script_file
);
2314 /* update event buffer, flag if overflowed */
2315 JSHashEntry
*he
= *hep
;
2317 EthogramEventBuffer
*p
;
2318 p
= (EthogramEventBuffer
*) he
->value
;
2320 p
->push(s
, r
, script_file
, jstv_Lineno(cx
, fp
));
2325 ethogram_construct(JSContext
*cx
, JSObject
*obj
,
2326 uintN argc
, jsval
*argv
, jsval
*rval
)
2328 EthogramEventBuffer
*p
;
2330 p
= (EthogramEventBuffer
*) JS_malloc(cx
, sizeof(EthogramEventBuffer
));
2332 p
->mReadPos
= p
->mWritePos
= 0;
2334 p
->mFilenames
= JS_NewArrayObject(cx
, 0, NULL
);
2338 GetSystemTimeAsFileTime(&now
);
2339 unsigned long long raw_us
= 0.1 *
2340 (((unsigned long long) now
.dwHighDateTime
<< 32ULL) |
2341 (unsigned long long) now
.dwLowDateTime
);
2342 unsigned int s
= raw_us
/ 1000000L;
2343 p
->mStartSecond
= s
;
2346 gettimeofday(&tv
, NULL
);
2347 p
->mStartSecond
= tv
.tv_sec
;
2349 jsval filenames
= OBJECT_TO_JSVAL(p
->filenames());
2350 if (!JS_DefineProperty(cx
, obj
, "filenames", filenames
,
2351 NULL
, NULL
, JSPROP_READONLY
|JSPROP_PERMANENT
))
2354 if (!JS_IsConstructing(cx
)) {
2355 obj
= JS_NewObject(cx
, ðogram_class
, NULL
, NULL
);
2358 *rval
= OBJECT_TO_JSVAL(obj
);
2360 JS_SetPrivate(cx
, obj
, p
);
2365 ethogram_finalize(JSContext
*cx
, JSObject
*obj
)
2367 EthogramEventBuffer
*p
;
2368 p
= (EthogramEventBuffer
*) JS_GetInstancePrivate(cx
, obj
, ðogram_class
, NULL
);
2372 p
->removeScripts(cx
);
2378 ethogram_addScript(JSContext
*cx
, JSObject
*obj
,
2379 uintN argc
, jsval
*argv
, jsval
*rval
)
2382 char *filename
= NULL
;
2383 if (argc
> 0 && JSVAL_IS_STRING(argv
[0])) {
2384 str
= JSVAL_TO_STRING(argv
[0]);
2385 filename
= js_DeflateString(cx
,
2390 /* silently ignore no args */
2394 EthogramEventBuffer
*p
= (EthogramEventBuffer
*) JS_GetInstancePrivate(cx
, obj
, ðogram_class
, argv
);
2396 p
->addScript(cx
, obj
, filename
, str
);
2397 JS_CallFunctionName(cx
, p
->filenames(), "push", 1, argv
, rval
);
2402 ethogram_getAllEvents(JSContext
*cx
, JSObject
*obj
,
2403 uintN argc
, jsval
*argv
, jsval
*rval
)
2405 EthogramEventBuffer
*p
;
2407 p
= (EthogramEventBuffer
*) JS_GetInstancePrivate(cx
, obj
, ðogram_class
, argv
);
2416 JSObject
*rarray
= JS_NewArrayObject(cx
, 0, NULL
);
2417 if (rarray
== NULL
) {
2422 *rval
= OBJECT_TO_JSVAL(rarray
);
2424 for (int i
= 0; !p
->isEmpty(); i
++) {
2426 JSObject
*x
= JS_NewObject(cx
, NULL
, NULL
, NULL
);
2430 EthogramEvent
*e
= p
->pop();
2432 jsval state
= INT_TO_JSVAL(e
->s
);
2433 jsval reason
= INT_TO_JSVAL(e
->r
);
2434 jsval ts
= INT_TO_JSVAL(e
->ts
);
2435 jsval tus
= INT_TO_JSVAL(e
->tus
);
2437 jsval filename
= STRING_TO_JSVAL(e
->filename
);
2438 jsval lineno
= INT_TO_JSVAL(e
->lineno
);
2440 if (!JS_SetProperty(cx
, x
, "state", &state
))
2442 if (!JS_SetProperty(cx
, x
, "reason", &reason
))
2444 if (!JS_SetProperty(cx
, x
, "ts", &ts
))
2446 if (!JS_SetProperty(cx
, x
, "tus", &tus
))
2449 if (!JS_SetProperty(cx
, x
, "filename", &filename
))
2451 if (!JS_SetProperty(cx
, x
, "lineno", &lineno
))
2454 jsval element
= OBJECT_TO_JSVAL(x
);
2455 JS_SetElement(cx
, rarray
, i
, &element
);
2462 ethogram_getNextEvent(JSContext
*cx
, JSObject
*obj
,
2463 uintN argc
, jsval
*argv
, jsval
*rval
)
2465 EthogramEventBuffer
*p
;
2467 p
= (EthogramEventBuffer
*) JS_GetInstancePrivate(cx
, obj
, ðogram_class
, argv
);
2471 JSObject
*x
= JS_NewObject(cx
, NULL
, NULL
, NULL
);
2480 EthogramEvent
*e
= p
->pop();
2481 jsval state
= INT_TO_JSVAL(e
->s
);
2482 jsval reason
= INT_TO_JSVAL(e
->r
);
2483 jsval ts
= INT_TO_JSVAL(e
->ts
);
2484 jsval tus
= INT_TO_JSVAL(e
->tus
);
2486 jsval filename
= STRING_TO_JSVAL(e
->filename
);
2487 jsval lineno
= INT_TO_JSVAL(e
->lineno
);
2489 if (!JS_SetProperty(cx
, x
, "state", &state
))
2491 if (!JS_SetProperty(cx
, x
, "reason", &reason
))
2493 if (!JS_SetProperty(cx
, x
, "ts", &ts
))
2495 if (!JS_SetProperty(cx
, x
, "tus", &tus
))
2497 if (!JS_SetProperty(cx
, x
, "filename", &filename
))
2500 if (!JS_SetProperty(cx
, x
, "lineno", &lineno
))
2503 *rval
= OBJECT_TO_JSVAL(x
);
2508 static JSFunctionSpec ethogram_methods
[] = {
2509 {"addScript", ethogram_addScript
, 1},
2510 {"getAllEvents", ethogram_getAllEvents
, 0},
2511 {"getNextEvent", ethogram_getNextEvent
, 0},
2516 * An |Ethogram| organizes the output of a collection of files that should be
2517 * monitored together. A single object gets events for the group.
2519 JS_FRIEND_API(JSBool
)
2520 js_InitEthogram(JSContext
*cx
, JSObject
*obj
,
2521 uintN argc
, jsval
*argv
, jsval
*rval
)
2523 if (!traceVisScriptTable
) {
2524 traceVisScriptTable
= JS_NewHashTable(8, JS_HashString
, compare_strings
,
2528 JS_InitClass(cx
, JS_GetGlobalObject(cx
), NULL
, ðogram_class
,
2529 ethogram_construct
, 0, NULL
, ethogram_methods
,
2535 JS_FRIEND_API(JSBool
)
2536 js_ShutdownEthogram(JSContext
*cx
, JSObject
*obj
,
2537 uintN argc
, jsval
*argv
, jsval
*rval
)
2539 if (traceVisScriptTable
)
2540 JS_HashTableDestroy(traceVisScriptTable
);
2545 #endif /* MOZ_TRACEVIS */