PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/js/jsdbgapi.cpp

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
C++ | 1954 lines | 1571 code | 241 blank | 142 comment | 304 complexity | 9da1bf018cd02a156e9fd449d3e17c9d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * vim: set ts=8 sw=4 et tw=78:
  3. *
  4. * ***** BEGIN LICENSE BLOCK *****
  5. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6. *
  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/
  11. *
  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
  15. * License.
  16. *
  17. * The Original Code is Mozilla Communicator client code, released
  18. * March 31, 1998.
  19. *
  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.
  24. *
  25. * Contributor(s):
  26. *
  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.
  38. *
  39. * ***** END LICENSE BLOCK ***** */
  40. /*
  41. * JS debugging API.
  42. */
  43. #include "jsstddef.h"
  44. #include <string.h>
  45. #include "jstypes.h"
  46. #include "jsutil.h" /* Added by JSIFY */
  47. #include "jsclist.h"
  48. #include "jsapi.h"
  49. #include "jscntxt.h"
  50. #include "jsversion.h"
  51. #include "jsdbgapi.h"
  52. #include "jsemit.h"
  53. #include "jsfun.h"
  54. #include "jsgc.h"
  55. #include "jsinterp.h"
  56. #include "jslock.h"
  57. #include "jsobj.h"
  58. #include "jsopcode.h"
  59. #include "jsparse.h"
  60. #include "jsscope.h"
  61. #include "jsscript.h"
  62. #include "jsstr.h"
  63. #include "jsautooplen.h"
  64. typedef struct JSTrap {
  65. JSCList links;
  66. JSScript *script;
  67. jsbytecode *pc;
  68. JSOp op;
  69. JSTrapHandler handler;
  70. void *closure;
  71. } JSTrap;
  72. #define DBG_LOCK(rt) JS_ACQUIRE_LOCK((rt)->debuggerLock)
  73. #define DBG_UNLOCK(rt) JS_RELEASE_LOCK((rt)->debuggerLock)
  74. #define DBG_LOCK_EVAL(rt,expr) (DBG_LOCK(rt), (expr), DBG_UNLOCK(rt))
  75. /*
  76. * NB: FindTrap must be called with rt->debuggerLock acquired.
  77. */
  78. static JSTrap *
  79. FindTrap(JSRuntime *rt, JSScript *script, jsbytecode *pc)
  80. {
  81. JSTrap *trap;
  82. for (trap = (JSTrap *)rt->trapList.next;
  83. &trap->links != &rt->trapList;
  84. trap = (JSTrap *)trap->links.next) {
  85. if (trap->script == script && trap->pc == pc)
  86. return trap;
  87. }
  88. return NULL;
  89. }
  90. jsbytecode *
  91. js_UntrapScriptCode(JSContext *cx, JSScript *script)
  92. {
  93. jsbytecode *code;
  94. JSRuntime *rt;
  95. JSTrap *trap;
  96. code = script->code;
  97. rt = cx->runtime;
  98. DBG_LOCK(rt);
  99. for (trap = (JSTrap *)rt->trapList.next;
  100. &trap->links !=
  101. &rt->trapList;
  102. trap = (JSTrap *)trap->links.next) {
  103. if (trap->script == script &&
  104. (size_t)(trap->pc - script->code) < script->length) {
  105. if (code == script->code) {
  106. jssrcnote *sn, *notes;
  107. size_t nbytes;
  108. nbytes = script->length * sizeof(jsbytecode);
  109. notes = SCRIPT_NOTES(script);
  110. for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
  111. continue;
  112. nbytes += (sn - notes + 1) * sizeof *sn;
  113. code = (jsbytecode *) JS_malloc(cx, nbytes);
  114. if (!code)
  115. break;
  116. memcpy(code, script->code, nbytes);
  117. JS_CLEAR_GSN_CACHE(cx);
  118. }
  119. code[trap->pc - script->code] = trap->op;
  120. }
  121. }
  122. DBG_UNLOCK(rt);
  123. return code;
  124. }
  125. JS_PUBLIC_API(JSBool)
  126. JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
  127. JSTrapHandler handler, void *closure)
  128. {
  129. JSTrap *junk, *trap, *twin;
  130. JSRuntime *rt;
  131. uint32 sample;
  132. JS_ASSERT((JSOp) *pc != JSOP_TRAP);
  133. junk = NULL;
  134. rt = cx->runtime;
  135. DBG_LOCK(rt);
  136. trap = FindTrap(rt, script, pc);
  137. if (trap) {
  138. JS_ASSERT(trap->script == script && trap->pc == pc);
  139. JS_ASSERT(*pc == JSOP_TRAP);
  140. } else {
  141. sample = rt->debuggerMutations;
  142. DBG_UNLOCK(rt);
  143. trap = (JSTrap *) JS_malloc(cx, sizeof *trap);
  144. if (!trap)
  145. return JS_FALSE;
  146. trap->closure = NULL;
  147. if(!js_AddRoot(cx, &trap->closure, "trap->closure")) {
  148. JS_free(cx, trap);
  149. return JS_FALSE;
  150. }
  151. DBG_LOCK(rt);
  152. twin = (rt->debuggerMutations != sample)
  153. ? FindTrap(rt, script, pc)
  154. : NULL;
  155. if (twin) {
  156. junk = trap;
  157. trap = twin;
  158. } else {
  159. JS_APPEND_LINK(&trap->links, &rt->trapList);
  160. ++rt->debuggerMutations;
  161. trap->script = script;
  162. trap->pc = pc;
  163. trap->op = (JSOp)*pc;
  164. *pc = JSOP_TRAP;
  165. }
  166. }
  167. trap->handler = handler;
  168. trap->closure = closure;
  169. DBG_UNLOCK(rt);
  170. if (junk) {
  171. js_RemoveRoot(rt, &junk->closure);
  172. JS_free(cx, junk);
  173. }
  174. return JS_TRUE;
  175. }
  176. JS_PUBLIC_API(JSOp)
  177. JS_GetTrapOpcode(JSContext *cx, JSScript *script, jsbytecode *pc)
  178. {
  179. JSRuntime *rt;
  180. JSTrap *trap;
  181. JSOp op;
  182. rt = cx->runtime;
  183. DBG_LOCK(rt);
  184. trap = FindTrap(rt, script, pc);
  185. op = trap ? trap->op : (JSOp) *pc;
  186. DBG_UNLOCK(rt);
  187. return op;
  188. }
  189. static void
  190. DestroyTrapAndUnlock(JSContext *cx, JSTrap *trap)
  191. {
  192. ++cx->runtime->debuggerMutations;
  193. JS_REMOVE_LINK(&trap->links);
  194. *trap->pc = (jsbytecode)trap->op;
  195. DBG_UNLOCK(cx->runtime);
  196. js_RemoveRoot(cx->runtime, &trap->closure);
  197. JS_free(cx, trap);
  198. }
  199. JS_PUBLIC_API(void)
  200. JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
  201. JSTrapHandler *handlerp, void **closurep)
  202. {
  203. JSTrap *trap;
  204. DBG_LOCK(cx->runtime);
  205. trap = FindTrap(cx->runtime, script, pc);
  206. if (handlerp)
  207. *handlerp = trap ? trap->handler : NULL;
  208. if (closurep)
  209. *closurep = trap ? trap->closure : NULL;
  210. if (trap)
  211. DestroyTrapAndUnlock(cx, trap);
  212. else
  213. DBG_UNLOCK(cx->runtime);
  214. }
  215. JS_PUBLIC_API(void)
  216. JS_ClearScriptTraps(JSContext *cx, JSScript *script)
  217. {
  218. JSRuntime *rt;
  219. JSTrap *trap, *next;
  220. uint32 sample;
  221. rt = cx->runtime;
  222. DBG_LOCK(rt);
  223. for (trap = (JSTrap *)rt->trapList.next;
  224. &trap->links != &rt->trapList;
  225. trap = next) {
  226. next = (JSTrap *)trap->links.next;
  227. if (trap->script == script) {
  228. sample = rt->debuggerMutations;
  229. DestroyTrapAndUnlock(cx, trap);
  230. DBG_LOCK(rt);
  231. if (rt->debuggerMutations != sample + 1)
  232. next = (JSTrap *)rt->trapList.next;
  233. }
  234. }
  235. DBG_UNLOCK(rt);
  236. }
  237. JS_PUBLIC_API(void)
  238. JS_ClearAllTraps(JSContext *cx)
  239. {
  240. JSRuntime *rt;
  241. JSTrap *trap, *next;
  242. uint32 sample;
  243. rt = cx->runtime;
  244. DBG_LOCK(rt);
  245. for (trap = (JSTrap *)rt->trapList.next;
  246. &trap->links != &rt->trapList;
  247. trap = next) {
  248. next = (JSTrap *)trap->links.next;
  249. sample = rt->debuggerMutations;
  250. DestroyTrapAndUnlock(cx, trap);
  251. DBG_LOCK(rt);
  252. if (rt->debuggerMutations != sample + 1)
  253. next = (JSTrap *)rt->trapList.next;
  254. }
  255. DBG_UNLOCK(rt);
  256. }
  257. JS_PUBLIC_API(JSTrapStatus)
  258. JS_HandleTrap(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval)
  259. {
  260. JSTrap *trap;
  261. jsint op;
  262. JSTrapStatus status;
  263. DBG_LOCK(cx->runtime);
  264. trap = FindTrap(cx->runtime, script, pc);
  265. JS_ASSERT(!trap || trap->handler);
  266. if (!trap) {
  267. op = (JSOp) *pc;
  268. DBG_UNLOCK(cx->runtime);
  269. /* Defend against "pc for wrong script" API usage error. */
  270. JS_ASSERT(op != JSOP_TRAP);
  271. #ifdef JS_THREADSAFE
  272. /* If the API was abused, we must fail for want of the real op. */
  273. if (op == JSOP_TRAP)
  274. return JSTRAP_ERROR;
  275. /* Assume a race with a debugger thread and try to carry on. */
  276. *rval = INT_TO_JSVAL(op);
  277. return JSTRAP_CONTINUE;
  278. #else
  279. /* Always fail if single-threaded (must be an API usage error). */
  280. return JSTRAP_ERROR;
  281. #endif
  282. }
  283. DBG_UNLOCK(cx->runtime);
  284. /*
  285. * It's important that we not use 'trap->' after calling the callback --
  286. * the callback might remove the trap!
  287. */
  288. op = (jsint)trap->op;
  289. status = trap->handler(cx, script, pc, rval, trap->closure);
  290. if (status == JSTRAP_CONTINUE) {
  291. /* By convention, return the true op to the interpreter in rval. */
  292. *rval = INT_TO_JSVAL(op);
  293. }
  294. return status;
  295. }
  296. JS_PUBLIC_API(JSBool)
  297. JS_SetInterrupt(JSRuntime *rt, JSTrapHandler handler, void *closure)
  298. {
  299. rt->globalDebugHooks.interruptHandler = handler;
  300. rt->globalDebugHooks.interruptHandlerData = closure;
  301. return JS_TRUE;
  302. }
  303. JS_PUBLIC_API(JSBool)
  304. JS_ClearInterrupt(JSRuntime *rt, JSTrapHandler *handlerp, void **closurep)
  305. {
  306. if (handlerp)
  307. *handlerp = (JSTrapHandler)rt->globalDebugHooks.interruptHandler;
  308. if (closurep)
  309. *closurep = rt->globalDebugHooks.interruptHandlerData;
  310. rt->globalDebugHooks.interruptHandler = 0;
  311. rt->globalDebugHooks.interruptHandlerData = 0;
  312. return JS_TRUE;
  313. }
  314. /************************************************************************/
  315. typedef struct JSWatchPoint {
  316. JSCList links;
  317. JSObject *object; /* weak link, see js_FinalizeObject */
  318. JSScopeProperty *sprop;
  319. JSPropertyOp setter;
  320. JSWatchPointHandler handler;
  321. void *closure;
  322. uintN flags;
  323. } JSWatchPoint;
  324. #define JSWP_LIVE 0x1 /* live because set and not cleared */
  325. #define JSWP_HELD 0x2 /* held while running handler/setter */
  326. /*
  327. * NB: DropWatchPointAndUnlock releases cx->runtime->debuggerLock in all cases.
  328. */
  329. static JSBool
  330. DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag)
  331. {
  332. JSBool ok, found;
  333. JSScopeProperty *sprop;
  334. JSScope *scope;
  335. JSPropertyOp setter;
  336. ok = JS_TRUE;
  337. wp->flags &= ~flag;
  338. if (wp->flags != 0) {
  339. DBG_UNLOCK(cx->runtime);
  340. return ok;
  341. }
  342. /*
  343. * Remove wp from the list, then if there are no other watchpoints for
  344. * wp->sprop in any scope, restore wp->sprop->setter from wp.
  345. */
  346. ++cx->runtime->debuggerMutations;
  347. JS_REMOVE_LINK(&wp->links);
  348. sprop = wp->sprop;
  349. /*
  350. * Passing null for the scope parameter tells js_GetWatchedSetter to find
  351. * any watch point for sprop, and not to lock or unlock rt->debuggerLock.
  352. * If js_ChangeNativePropertyAttrs fails, propagate failure after removing
  353. * wp->closure's root and freeing wp.
  354. */
  355. setter = js_GetWatchedSetter(cx->runtime, NULL, sprop);
  356. DBG_UNLOCK(cx->runtime);
  357. if (!setter) {
  358. JS_LOCK_OBJ(cx, wp->object);
  359. scope = OBJ_SCOPE(wp->object);
  360. found = (scope->object == wp->object &&
  361. SCOPE_GET_PROPERTY(scope, sprop->id));
  362. JS_UNLOCK_SCOPE(cx, scope);
  363. /*
  364. * If the property wasn't found on wp->object or didn't exist, then
  365. * someone else has dealt with this sprop, and we don't need to change
  366. * the property attributes.
  367. */
  368. if (found) {
  369. sprop = js_ChangeScopePropertyAttrs(cx, scope, sprop,
  370. 0, sprop->attrs,
  371. sprop->getter,
  372. wp->setter);
  373. if (!sprop)
  374. ok = JS_FALSE;
  375. }
  376. }
  377. JS_free(cx, wp);
  378. return ok;
  379. }
  380. /*
  381. * NB: js_TraceWatchPoints does not acquire cx->runtime->debuggerLock, since
  382. * the debugger should never be racing with the GC (i.e., the debugger must
  383. * respect the request model).
  384. */
  385. void
  386. js_TraceWatchPoints(JSTracer *trc, JSObject *obj)
  387. {
  388. JSRuntime *rt;
  389. JSWatchPoint *wp;
  390. rt = trc->context->runtime;
  391. for (wp = (JSWatchPoint *)rt->watchPointList.next;
  392. &wp->links != &rt->watchPointList;
  393. wp = (JSWatchPoint *)wp->links.next) {
  394. if (wp->object == obj) {
  395. TRACE_SCOPE_PROPERTY(trc, wp->sprop);
  396. if ((wp->sprop->attrs & JSPROP_SETTER) && wp->setter) {
  397. JS_CALL_OBJECT_TRACER(trc, (JSObject *)wp->setter,
  398. "wp->setter");
  399. }
  400. JS_SET_TRACING_NAME(trc, "wp->closure");
  401. js_CallValueTracerIfGCThing(trc, (jsval) wp->closure);
  402. }
  403. }
  404. }
  405. void
  406. js_SweepWatchPoints(JSContext *cx)
  407. {
  408. JSRuntime *rt;
  409. JSWatchPoint *wp, *next;
  410. uint32 sample;
  411. rt = cx->runtime;
  412. DBG_LOCK(rt);
  413. for (wp = (JSWatchPoint *)rt->watchPointList.next;
  414. &wp->links != &rt->watchPointList;
  415. wp = next) {
  416. next = (JSWatchPoint *)wp->links.next;
  417. if (js_IsAboutToBeFinalized(cx, wp->object)) {
  418. sample = rt->debuggerMutations;
  419. /* Ignore failures. */
  420. DropWatchPointAndUnlock(cx, wp, JSWP_LIVE);
  421. DBG_LOCK(rt);
  422. if (rt->debuggerMutations != sample + 1)
  423. next = (JSWatchPoint *)rt->watchPointList.next;
  424. }
  425. }
  426. DBG_UNLOCK(rt);
  427. }
  428. /*
  429. * NB: FindWatchPoint must be called with rt->debuggerLock acquired.
  430. */
  431. static JSWatchPoint *
  432. FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id)
  433. {
  434. JSWatchPoint *wp;
  435. for (wp = (JSWatchPoint *)rt->watchPointList.next;
  436. &wp->links != &rt->watchPointList;
  437. wp = (JSWatchPoint *)wp->links.next) {
  438. if (wp->object == scope->object && wp->sprop->id == id)
  439. return wp;
  440. }
  441. return NULL;
  442. }
  443. JSScopeProperty *
  444. js_FindWatchPoint(JSRuntime *rt, JSScope *scope, jsid id)
  445. {
  446. JSWatchPoint *wp;
  447. JSScopeProperty *sprop;
  448. DBG_LOCK(rt);
  449. wp = FindWatchPoint(rt, scope, id);
  450. sprop = wp ? wp->sprop : NULL;
  451. DBG_UNLOCK(rt);
  452. return sprop;
  453. }
  454. /*
  455. * Secret handshake with DropWatchPointAndUnlock: if (!scope), we know our
  456. * caller has acquired rt->debuggerLock, so we don't have to.
  457. */
  458. JSPropertyOp
  459. js_GetWatchedSetter(JSRuntime *rt, JSScope *scope,
  460. const JSScopeProperty *sprop)
  461. {
  462. JSPropertyOp setter;
  463. JSWatchPoint *wp;
  464. setter = NULL;
  465. if (scope)
  466. DBG_LOCK(rt);
  467. for (wp = (JSWatchPoint *)rt->watchPointList.next;
  468. &wp->links != &rt->watchPointList;
  469. wp = (JSWatchPoint *)wp->links.next) {
  470. if ((!scope || wp->object == scope->object) && wp->sprop == sprop) {
  471. setter = wp->setter;
  472. break;
  473. }
  474. }
  475. if (scope)
  476. DBG_UNLOCK(rt);
  477. return setter;
  478. }
  479. JSBool
  480. js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
  481. {
  482. JSRuntime *rt;
  483. JSWatchPoint *wp;
  484. JSScopeProperty *sprop;
  485. jsval propid, userid;
  486. JSScope *scope;
  487. JSBool ok;
  488. rt = cx->runtime;
  489. DBG_LOCK(rt);
  490. for (wp = (JSWatchPoint *)rt->watchPointList.next;
  491. &wp->links != &rt->watchPointList;
  492. wp = (JSWatchPoint *)wp->links.next) {
  493. sprop = wp->sprop;
  494. if (wp->object == obj && SPROP_USERID(sprop) == id &&
  495. !(wp->flags & JSWP_HELD)) {
  496. wp->flags |= JSWP_HELD;
  497. DBG_UNLOCK(rt);
  498. JS_LOCK_OBJ(cx, obj);
  499. propid = ID_TO_VALUE(sprop->id);
  500. userid = (sprop->flags & SPROP_HAS_SHORTID)
  501. ? INT_TO_JSVAL(sprop->shortid)
  502. : propid;
  503. scope = OBJ_SCOPE(obj);
  504. JS_UNLOCK_OBJ(cx, obj);
  505. /* NB: wp is held, so we can safely dereference it still. */
  506. ok = wp->handler(cx, obj, propid,
  507. SPROP_HAS_VALID_SLOT(sprop, scope)
  508. ? OBJ_GET_SLOT(cx, obj, sprop->slot)
  509. : JSVAL_VOID,
  510. vp, wp->closure);
  511. if (ok) {
  512. /*
  513. * Create a pseudo-frame for the setter invocation so that any
  514. * stack-walking security code under the setter will correctly
  515. * identify the guilty party. So that the watcher appears to
  516. * be active to obj_eval and other such code, point frame.pc
  517. * at the JSOP_STOP at the end of the script.
  518. *
  519. * The pseudo-frame is not created for fast natives as they
  520. * are treated as interpreter frame extensions and always
  521. * trusted.
  522. */
  523. JSObject *closure;
  524. JSClass *clasp;
  525. JSFunction *fun;
  526. JSScript *script;
  527. JSBool injectFrame;
  528. uintN nslots;
  529. jsval smallv[5];
  530. jsval *argv;
  531. JSStackFrame frame;
  532. JSFrameRegs regs;
  533. closure = (JSObject *) wp->closure;
  534. clasp = OBJ_GET_CLASS(cx, closure);
  535. if (clasp == &js_FunctionClass) {
  536. fun = GET_FUNCTION_PRIVATE(cx, closure);
  537. script = FUN_SCRIPT(fun);
  538. } else if (clasp == &js_ScriptClass) {
  539. fun = NULL;
  540. script = (JSScript *) JS_GetPrivate(cx, closure);
  541. } else {
  542. fun = NULL;
  543. script = NULL;
  544. }
  545. nslots = 2;
  546. injectFrame = JS_TRUE;
  547. if (fun) {
  548. nslots += FUN_MINARGS(fun);
  549. if (!FUN_INTERPRETED(fun)) {
  550. nslots += fun->u.n.extra;
  551. injectFrame = !(fun->flags & JSFUN_FAST_NATIVE);
  552. }
  553. }
  554. if (injectFrame) {
  555. if (nslots <= JS_ARRAY_LENGTH(smallv)) {
  556. argv = smallv;
  557. } else {
  558. argv = (jsval *) JS_malloc(cx, nslots * sizeof(jsval));
  559. if (!argv) {
  560. DBG_LOCK(rt);
  561. DropWatchPointAndUnlock(cx, wp, JSWP_HELD);
  562. return JS_FALSE;
  563. }
  564. }
  565. argv[0] = OBJECT_TO_JSVAL(closure);
  566. argv[1] = JSVAL_NULL;
  567. memset(argv + 2, 0, (nslots - 2) * sizeof(jsval));
  568. memset(&frame, 0, sizeof(frame));
  569. frame.script = script;
  570. frame.regs = NULL;
  571. if (script) {
  572. JS_ASSERT(script->length >= JSOP_STOP_LENGTH);
  573. regs.pc = script->code + script->length
  574. - JSOP_STOP_LENGTH;
  575. regs.sp = NULL;
  576. frame.regs = &regs;
  577. }
  578. frame.callee = closure;
  579. frame.fun = fun;
  580. frame.argv = argv + 2;
  581. frame.down = cx->fp;
  582. frame.scopeChain = OBJ_GET_PARENT(cx, closure);
  583. cx->fp = &frame;
  584. }
  585. #ifdef __GNUC__
  586. else
  587. argv = NULL; /* suppress bogus gcc warnings */
  588. #endif
  589. ok = !wp->setter ||
  590. ((sprop->attrs & JSPROP_SETTER)
  591. ? js_InternalCall(cx, obj, OBJECT_TO_JSVAL(wp->setter),
  592. 1, vp, vp)
  593. : wp->setter(cx, OBJ_THIS_OBJECT(cx, obj), userid, vp));
  594. if (injectFrame) {
  595. /* Evil code can cause us to have an arguments object. */
  596. if (frame.callobj)
  597. ok &= js_PutCallObject(cx, &frame);
  598. if (frame.argsobj)
  599. ok &= js_PutArgsObject(cx, &frame);
  600. cx->fp = frame.down;
  601. if (argv != smallv)
  602. JS_free(cx, argv);
  603. }
  604. }
  605. DBG_LOCK(rt);
  606. return DropWatchPointAndUnlock(cx, wp, JSWP_HELD) && ok;
  607. }
  608. }
  609. DBG_UNLOCK(rt);
  610. return JS_TRUE;
  611. }
  612. JSBool
  613. js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
  614. jsval *rval)
  615. {
  616. JSObject *funobj;
  617. JSFunction *wrapper;
  618. jsval userid;
  619. funobj = JSVAL_TO_OBJECT(argv[-2]);
  620. JS_ASSERT(OBJ_GET_CLASS(cx, funobj) == &js_FunctionClass);
  621. wrapper = GET_FUNCTION_PRIVATE(cx, funobj);
  622. userid = ATOM_KEY(wrapper->atom);
  623. *rval = argv[0];
  624. return js_watch_set(cx, obj, userid, rval);
  625. }
  626. JSPropertyOp
  627. js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
  628. {
  629. JSAtom *atom;
  630. JSFunction *wrapper;
  631. if (!(attrs & JSPROP_SETTER))
  632. return &js_watch_set; /* & to silence schoolmarmish MSVC */
  633. if (JSID_IS_ATOM(id)) {
  634. atom = JSID_TO_ATOM(id);
  635. } else if (JSID_IS_INT(id)) {
  636. if (!js_ValueToStringId(cx, INT_JSID_TO_JSVAL(id), &id))
  637. return NULL;
  638. atom = JSID_TO_ATOM(id);
  639. } else {
  640. atom = NULL;
  641. }
  642. wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0,
  643. OBJ_GET_PARENT(cx, (JSObject *)setter),
  644. atom);
  645. if (!wrapper)
  646. return NULL;
  647. return (JSPropertyOp) FUN_OBJECT(wrapper);
  648. }
  649. JS_PUBLIC_API(JSBool)
  650. JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
  651. JSWatchPointHandler handler, void *closure)
  652. {
  653. jsid propid;
  654. JSObject *pobj;
  655. JSProperty *prop;
  656. JSScopeProperty *sprop;
  657. JSRuntime *rt;
  658. JSBool ok;
  659. JSWatchPoint *wp;
  660. JSPropertyOp watcher;
  661. if (!OBJ_IS_NATIVE(obj)) {
  662. JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_WATCH,
  663. OBJ_GET_CLASS(cx, obj)->name);
  664. return JS_FALSE;
  665. }
  666. if (JSVAL_IS_INT(idval))
  667. propid = INT_JSVAL_TO_JSID(idval);
  668. else if (!js_ValueToStringId(cx, idval, &propid))
  669. return JS_FALSE;
  670. if (!js_LookupProperty(cx, obj, propid, &pobj, &prop))
  671. return JS_FALSE;
  672. sprop = (JSScopeProperty *) prop;
  673. rt = cx->runtime;
  674. if (!sprop) {
  675. /* Check for a deleted symbol watchpoint, which holds its property. */
  676. sprop = js_FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
  677. if (!sprop) {
  678. /* Make a new property in obj so we can watch for the first set. */
  679. if (!js_DefineProperty(cx, obj, propid, JSVAL_VOID,
  680. NULL, NULL, JSPROP_ENUMERATE,
  681. &prop)) {
  682. return JS_FALSE;
  683. }
  684. sprop = (JSScopeProperty *) prop;
  685. }
  686. } else if (pobj != obj) {
  687. /* Clone the prototype property so we can watch the right object. */
  688. jsval value;
  689. JSPropertyOp getter, setter;
  690. uintN attrs, flags;
  691. intN shortid;
  692. if (OBJ_IS_NATIVE(pobj)) {
  693. value = SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(pobj))
  694. ? LOCKED_OBJ_GET_SLOT(pobj, sprop->slot)
  695. : JSVAL_VOID;
  696. getter = sprop->getter;
  697. setter = sprop->setter;
  698. attrs = sprop->attrs;
  699. flags = sprop->flags;
  700. shortid = sprop->shortid;
  701. } else {
  702. if (!OBJ_GET_PROPERTY(cx, pobj, propid, &value) ||
  703. !OBJ_GET_ATTRIBUTES(cx, pobj, propid, prop, &attrs)) {
  704. OBJ_DROP_PROPERTY(cx, pobj, prop);
  705. return JS_FALSE;
  706. }
  707. getter = setter = NULL;
  708. flags = 0;
  709. shortid = 0;
  710. }
  711. OBJ_DROP_PROPERTY(cx, pobj, prop);
  712. /* Recall that obj is native, whether or not pobj is native. */
  713. if (!js_DefineNativeProperty(cx, obj, propid, value, getter, setter,
  714. attrs, flags, shortid, &prop)) {
  715. return JS_FALSE;
  716. }
  717. sprop = (JSScopeProperty *) prop;
  718. }
  719. /*
  720. * At this point, prop/sprop exists in obj, obj is locked, and we must
  721. * OBJ_DROP_PROPERTY(cx, obj, prop) before returning.
  722. */
  723. ok = JS_TRUE;
  724. DBG_LOCK(rt);
  725. wp = FindWatchPoint(rt, OBJ_SCOPE(obj), propid);
  726. if (!wp) {
  727. DBG_UNLOCK(rt);
  728. watcher = js_WrapWatchedSetter(cx, propid, sprop->attrs, sprop->setter);
  729. if (!watcher) {
  730. ok = JS_FALSE;
  731. goto out;
  732. }
  733. wp = (JSWatchPoint *) JS_malloc(cx, sizeof *wp);
  734. if (!wp) {
  735. ok = JS_FALSE;
  736. goto out;
  737. }
  738. wp->handler = NULL;
  739. wp->closure = NULL;
  740. wp->object = obj;
  741. JS_ASSERT(sprop->setter != js_watch_set || pobj != obj);
  742. wp->setter = sprop->setter;
  743. wp->flags = JSWP_LIVE;
  744. /* XXXbe nest in obj lock here */
  745. sprop = js_ChangeNativePropertyAttrs(cx, obj, sprop, 0, sprop->attrs,
  746. sprop->getter, watcher);
  747. if (!sprop) {
  748. /* Self-link so DropWatchPointAndUnlock can JS_REMOVE_LINK it. */
  749. JS_INIT_CLIST(&wp->links);
  750. DBG_LOCK(rt);
  751. DropWatchPointAndUnlock(cx, wp, JSWP_LIVE);
  752. ok = JS_FALSE;
  753. goto out;
  754. }
  755. wp->sprop = sprop;
  756. /*
  757. * Now that wp is fully initialized, append it to rt's wp list.
  758. * Because obj is locked we know that no other thread could have added
  759. * a watchpoint for (obj, propid).
  760. */
  761. DBG_LOCK(rt);
  762. JS_ASSERT(!FindWatchPoint(rt, OBJ_SCOPE(obj), propid));
  763. JS_APPEND_LINK(&wp->links, &rt->watchPointList);
  764. ++rt->debuggerMutations;
  765. }
  766. wp->handler = handler;
  767. wp->closure = closure;
  768. DBG_UNLOCK(rt);
  769. out:
  770. OBJ_DROP_PROPERTY(cx, obj, prop);
  771. return ok;
  772. }
  773. JS_PUBLIC_API(JSBool)
  774. JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsval id,
  775. JSWatchPointHandler *handlerp, void **closurep)
  776. {
  777. JSRuntime *rt;
  778. JSWatchPoint *wp;
  779. rt = cx->runtime;
  780. DBG_LOCK(rt);
  781. for (wp = (JSWatchPoint *)rt->watchPointList.next;
  782. &wp->links != &rt->watchPointList;
  783. wp = (JSWatchPoint *)wp->links.next) {
  784. if (wp->object == obj && SPROP_USERID(wp->sprop) == id) {
  785. if (handlerp)
  786. *handlerp = wp->handler;
  787. if (closurep)
  788. *closurep = wp->closure;
  789. return DropWatchPointAndUnlock(cx, wp, JSWP_LIVE);
  790. }
  791. }
  792. DBG_UNLOCK(rt);
  793. if (handlerp)
  794. *handlerp = NULL;
  795. if (closurep)
  796. *closurep = NULL;
  797. return JS_TRUE;
  798. }
  799. JS_PUBLIC_API(JSBool)
  800. JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj)
  801. {
  802. JSRuntime *rt;
  803. JSWatchPoint *wp, *next;
  804. uint32 sample;
  805. rt = cx->runtime;
  806. DBG_LOCK(rt);
  807. for (wp = (JSWatchPoint *)rt->watchPointList.next;
  808. &wp->links != &rt->watchPointList;
  809. wp = next) {
  810. next = (JSWatchPoint *)wp->links.next;
  811. if (wp->object == obj) {
  812. sample = rt->debuggerMutations;
  813. if (!DropWatchPointAndUnlock(cx, wp, JSWP_LIVE))
  814. return JS_FALSE;
  815. DBG_LOCK(rt);
  816. if (rt->debuggerMutations != sample + 1)
  817. next = (JSWatchPoint *)rt->watchPointList.next;
  818. }
  819. }
  820. DBG_UNLOCK(rt);
  821. return JS_TRUE;
  822. }
  823. JS_PUBLIC_API(JSBool)
  824. JS_ClearAllWatchPoints(JSContext *cx)
  825. {
  826. JSRuntime *rt;
  827. JSWatchPoint *wp, *next;
  828. uint32 sample;
  829. rt = cx->runtime;
  830. DBG_LOCK(rt);
  831. for (wp = (JSWatchPoint *)rt->watchPointList.next;
  832. &wp->links != &rt->watchPointList;
  833. wp = next) {
  834. next = (JSWatchPoint *)wp->links.next;
  835. sample = rt->debuggerMutations;
  836. if (!DropWatchPointAndUnlock(cx, wp, JSWP_LIVE))
  837. return JS_FALSE;
  838. DBG_LOCK(rt);
  839. if (rt->debuggerMutations != sample + 1)
  840. next = (JSWatchPoint *)rt->watchPointList.next;
  841. }
  842. DBG_UNLOCK(rt);
  843. return JS_TRUE;
  844. }
  845. /************************************************************************/
  846. JS_PUBLIC_API(uintN)
  847. JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc)
  848. {
  849. return js_PCToLineNumber(cx, script, pc);
  850. }
  851. JS_PUBLIC_API(jsbytecode *)
  852. JS_LineNumberToPC(JSContext *cx, JSScript *script, uintN lineno)
  853. {
  854. return js_LineNumberToPC(script, lineno);
  855. }
  856. JS_PUBLIC_API(JSScript *)
  857. JS_GetFunctionScript(JSContext *cx, JSFunction *fun)
  858. {
  859. return FUN_SCRIPT(fun);
  860. }
  861. JS_PUBLIC_API(JSNative)
  862. JS_GetFunctionNative(JSContext *cx, JSFunction *fun)
  863. {
  864. return FUN_NATIVE(fun);
  865. }
  866. JS_PUBLIC_API(JSFastNative)
  867. JS_GetFunctionFastNative(JSContext *cx, JSFunction *fun)
  868. {
  869. return FUN_FAST_NATIVE(fun);
  870. }
  871. JS_PUBLIC_API(JSPrincipals *)
  872. JS_GetScriptPrincipals(JSContext *cx, JSScript *script)
  873. {
  874. return script->principals;
  875. }
  876. /************************************************************************/
  877. /*
  878. * Stack Frame Iterator
  879. */
  880. JS_PUBLIC_API(JSStackFrame *)
  881. JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp)
  882. {
  883. *iteratorp = (*iteratorp == NULL) ? cx->fp : (*iteratorp)->down;
  884. return *iteratorp;
  885. }
  886. JS_PUBLIC_API(JSScript *)
  887. JS_GetFrameScript(JSContext *cx, JSStackFrame *fp)
  888. {
  889. return fp->script;
  890. }
  891. JS_PUBLIC_API(jsbytecode *)
  892. JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
  893. {
  894. return fp->regs ? fp->regs->pc : NULL;
  895. }
  896. JS_PUBLIC_API(JSStackFrame *)
  897. JS_GetScriptedCaller(JSContext *cx, JSStackFrame *fp)
  898. {
  899. if (!fp)
  900. fp = cx->fp;
  901. while (fp) {
  902. if (fp->script)
  903. return fp;
  904. fp = fp->down;
  905. }
  906. return NULL;
  907. }
  908. JS_PUBLIC_API(JSPrincipals *)
  909. JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
  910. {
  911. JSSecurityCallbacks *callbacks;
  912. if (fp->fun) {
  913. callbacks = JS_GetSecurityCallbacks(cx);
  914. if (callbacks && callbacks->findObjectPrincipals) {
  915. if (FUN_OBJECT(fp->fun) != fp->callee)
  916. return callbacks->findObjectPrincipals(cx, fp->callee);
  917. /* FALL THROUGH */
  918. }
  919. }
  920. if (fp->script)
  921. return fp->script->principals;
  922. return NULL;
  923. }
  924. JS_PUBLIC_API(JSPrincipals *)
  925. JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller)
  926. {
  927. JSPrincipals *principals, *callerPrincipals;
  928. JSSecurityCallbacks *callbacks;
  929. callbacks = JS_GetSecurityCallbacks(cx);
  930. if (callbacks && callbacks->findObjectPrincipals) {
  931. principals = callbacks->findObjectPrincipals(cx, fp->callee);
  932. } else {
  933. principals = NULL;
  934. }
  935. if (!caller)
  936. return principals;
  937. callerPrincipals = JS_StackFramePrincipals(cx, caller);
  938. return (callerPrincipals && principals &&
  939. callerPrincipals->subsume(callerPrincipals, principals))
  940. ? principals
  941. : callerPrincipals;
  942. }
  943. JS_PUBLIC_API(void *)
  944. JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
  945. {
  946. if (fp->annotation && fp->script) {
  947. JSPrincipals *principals = JS_StackFramePrincipals(cx, fp);
  948. if (principals && principals->globalPrivilegesEnabled(cx, principals)) {
  949. /*
  950. * Give out an annotation only if privileges have not been revoked
  951. * or disabled globally.
  952. */
  953. return fp->annotation;
  954. }
  955. }
  956. return NULL;
  957. }
  958. JS_PUBLIC_API(void)
  959. JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation)
  960. {
  961. fp->annotation = annotation;
  962. }
  963. JS_PUBLIC_API(void *)
  964. JS_GetFramePrincipalArray(JSContext *cx, JSStackFrame *fp)
  965. {
  966. JSPrincipals *principals;
  967. principals = JS_StackFramePrincipals(cx, fp);
  968. if (!principals)
  969. return NULL;
  970. return principals->getPrincipalArray(cx, principals);
  971. }
  972. JS_PUBLIC_API(JSBool)
  973. JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp)
  974. {
  975. return !fp->script;
  976. }
  977. /* this is deprecated, use JS_GetFrameScopeChain instead */
  978. JS_PUBLIC_API(JSObject *)
  979. JS_GetFrameObject(JSContext *cx, JSStackFrame *fp)
  980. {
  981. return fp->scopeChain;
  982. }
  983. JS_PUBLIC_API(JSObject *)
  984. JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp)
  985. {
  986. /* Force creation of argument and call objects if not yet created */
  987. (void) JS_GetFrameCallObject(cx, fp);
  988. return js_GetScopeChain(cx, fp);
  989. }
  990. JS_PUBLIC_API(JSObject *)
  991. JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp)
  992. {
  993. if (! fp->fun)
  994. return NULL;
  995. /* Force creation of argument object if not yet created */
  996. (void) js_GetArgsObject(cx, fp);
  997. /*
  998. * XXX ill-defined: null return here means error was reported, unlike a
  999. * null returned above or in the #else
  1000. */
  1001. return js_GetCallObject(cx, fp, NULL);
  1002. }
  1003. JS_PUBLIC_API(JSObject *)
  1004. JS_GetFrameThis(JSContext *cx, JSStackFrame *fp)
  1005. {
  1006. JSStackFrame *afp;
  1007. if (fp->flags & JSFRAME_COMPUTED_THIS)
  1008. return fp->thisp;
  1009. /* js_ComputeThis gets confused if fp != cx->fp, so set it aside. */
  1010. if (cx->fp != fp) {
  1011. afp = cx->fp;
  1012. if (afp) {
  1013. afp->dormantNext = cx->dormantFrameChain;
  1014. cx->dormantFrameChain = afp;
  1015. cx->fp = fp;
  1016. }
  1017. } else {
  1018. afp = NULL;
  1019. }
  1020. if (!fp->thisp && fp->argv)
  1021. fp->thisp = js_ComputeThis(cx, JS_TRUE, fp->argv);
  1022. if (afp) {
  1023. cx->fp = afp;
  1024. cx->dormantFrameChain = afp->dormantNext;
  1025. afp->dormantNext = NULL;
  1026. }
  1027. return fp->thisp;
  1028. }
  1029. JS_PUBLIC_API(JSFunction *)
  1030. JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp)
  1031. {
  1032. return fp->fun;
  1033. }
  1034. JS_PUBLIC_API(JSObject *)
  1035. JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp)
  1036. {
  1037. if (!fp->fun)
  1038. return NULL;
  1039. JS_ASSERT(OBJ_GET_CLASS(cx, fp->callee) == &js_FunctionClass);
  1040. JS_ASSERT(OBJ_GET_PRIVATE(cx, fp->callee) == fp->fun);
  1041. return fp->callee;
  1042. }
  1043. JS_PUBLIC_API(JSBool)
  1044. JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp)
  1045. {
  1046. return (fp->flags & JSFRAME_CONSTRUCTING) != 0;
  1047. }
  1048. JS_PUBLIC_API(JSObject *)
  1049. JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp)
  1050. {
  1051. return fp->callee;
  1052. }
  1053. JS_PUBLIC_API(JSBool)
  1054. JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
  1055. {
  1056. return (fp->flags & JSFRAME_DEBUGGER) != 0;
  1057. }
  1058. JS_PUBLIC_API(jsval)
  1059. JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp)
  1060. {
  1061. return fp->rval;
  1062. }
  1063. JS_PUBLIC_API(void)
  1064. JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval)
  1065. {
  1066. fp->rval = rval;
  1067. }
  1068. /************************************************************************/
  1069. JS_PUBLIC_API(const char *)
  1070. JS_GetScriptFilename(JSContext *cx, JSScript *script)
  1071. {
  1072. return script->filename;
  1073. }
  1074. JS_PUBLIC_API(uintN)
  1075. JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script)
  1076. {
  1077. return script->lineno;
  1078. }
  1079. JS_PUBLIC_API(uintN)
  1080. JS_GetScriptLineExtent(JSContext *cx, JSScript *script)
  1081. {
  1082. return js_GetScriptLineExtent(script);
  1083. }
  1084. JS_PUBLIC_API(JSVersion)
  1085. JS_GetScriptVersion(JSContext *cx, JSScript *script)
  1086. {
  1087. return (JSVersion) (script->version & JSVERSION_MASK);
  1088. }
  1089. /***************************************************************************/
  1090. JS_PUBLIC_API(void)
  1091. JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata)
  1092. {
  1093. rt->globalDebugHooks.newScriptHook = hook;
  1094. rt->globalDebugHooks.newScriptHookData = callerdata;
  1095. }
  1096. JS_PUBLIC_API(void)
  1097. JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
  1098. void *callerdata)
  1099. {
  1100. rt->globalDebugHooks.destroyScriptHook = hook;
  1101. rt->globalDebugHooks.destroyScriptHookData = callerdata;
  1102. }
  1103. /***************************************************************************/
  1104. JS_PUBLIC_API(JSBool)
  1105. JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
  1106. const jschar *chars, uintN length,
  1107. const char *filename, uintN lineno,
  1108. jsval *rval)
  1109. {
  1110. JSObject *scobj;
  1111. JSScript *script;
  1112. JSBool ok;
  1113. scobj = JS_GetFrameScopeChain(cx, fp);
  1114. if (!scobj)
  1115. return JS_FALSE;
  1116. script = js_CompileScript(cx, scobj, fp, JS_StackFramePrincipals(cx, fp),
  1117. TCF_COMPILE_N_GO |
  1118. TCF_PUT_STATIC_DEPTH(fp->script->staticDepth + 1),
  1119. chars, length, NULL,
  1120. filename, lineno);
  1121. if (!script)
  1122. return JS_FALSE;
  1123. ok = js_Execute(cx, scobj, script, fp, JSFRAME_DEBUGGER | JSFRAME_EVAL,
  1124. rval);
  1125. js_DestroyScript(cx, script);
  1126. return ok;
  1127. }
  1128. JS_PUBLIC_API(JSBool)
  1129. JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
  1130. const char *bytes, uintN length,
  1131. const char *filename, uintN lineno,
  1132. jsval *rval)
  1133. {
  1134. jschar *chars;
  1135. JSBool ok;
  1136. size_t len = length;
  1137. chars = js_InflateString(cx, bytes, &len);
  1138. if (!chars)
  1139. return JS_FALSE;
  1140. length = (uintN) len;
  1141. ok = JS_EvaluateUCInStackFrame(cx, fp, chars, length, filename, lineno,
  1142. rval);
  1143. JS_free(cx, chars);
  1144. return ok;
  1145. }
  1146. /************************************************************************/
  1147. /* XXXbe this all needs to be reworked to avoid requiring JSScope types. */
  1148. JS_PUBLIC_API(JSScopeProperty *)
  1149. JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
  1150. {
  1151. JSScopeProperty *sprop;
  1152. JSScope *scope;
  1153. sprop = *iteratorp;
  1154. scope = OBJ_SCOPE(obj);
  1155. /* XXXbe minor(?) incompatibility: iterate in reverse definition order */
  1156. if (!sprop) {
  1157. sprop = SCOPE_LAST_PROP(scope);
  1158. } else {
  1159. while ((sprop = sprop->parent) != NULL) {
  1160. if (!SCOPE_HAD_MIDDLE_DELETE(scope))
  1161. break;
  1162. if (SCOPE_HAS_PROPERTY(scope, sprop))
  1163. break;
  1164. }
  1165. }
  1166. *iteratorp = sprop;
  1167. return sprop;
  1168. }
  1169. JS_PUBLIC_API(JSBool)
  1170. JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
  1171. JSPropertyDesc *pd)
  1172. {
  1173. JSScope *scope;
  1174. JSScopeProperty *aprop;
  1175. jsval lastException;
  1176. JSBool wasThrowing;
  1177. pd->id = ID_TO_VALUE(sprop->id);
  1178. wasThrowing = cx->throwing;
  1179. if (wasThrowing) {
  1180. lastException = cx->exception;
  1181. if (JSVAL_IS_GCTHING(lastException) &&
  1182. !js_AddRoot(cx, &lastException, "lastException")) {
  1183. return JS_FALSE;
  1184. }
  1185. cx->throwing = JS_FALSE;
  1186. }
  1187. if (!js_GetProperty(cx, obj, sprop->id, &pd->value)) {
  1188. if (!cx->throwing) {
  1189. pd->flags = JSPD_ERROR;
  1190. pd->value = JSVAL_VOID;
  1191. } else {
  1192. pd->flags = JSPD_EXCEPTION;
  1193. pd->value = cx->exception;
  1194. }
  1195. } else {
  1196. pd->flags = 0;
  1197. }
  1198. cx->throwing = wasThrowing;
  1199. if (wasThrowing) {
  1200. cx->exception = lastException;
  1201. if (JSVAL_IS_GCTHING(lastException))
  1202. js_RemoveRoot(cx->runtime, &lastException);
  1203. }
  1204. pd->flags |= ((sprop->attrs & JSPROP_ENUMERATE) ? JSPD_ENUMERATE : 0)
  1205. | ((sprop->attrs & JSPROP_READONLY) ? JSPD_READONLY : 0)
  1206. | ((sprop->attrs & JSPROP_PERMANENT) ? JSPD_PERMANENT : 0);
  1207. pd->spare = 0;
  1208. if (sprop->getter == js_GetCallArg) {
  1209. pd->slot = sprop->shortid;
  1210. pd->flags |= JSPD_ARGUMENT;
  1211. } else if (sprop->getter == js_GetCallVar) {
  1212. pd->slot = sprop->shortid;
  1213. pd->flags |= JSPD_VARIABLE;
  1214. } else {
  1215. pd->slot = 0;
  1216. }
  1217. pd->alias = JSVAL_VOID;
  1218. scope = OBJ_SCOPE(obj);
  1219. if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
  1220. for (aprop = SCOPE_LAST_PROP(scope); aprop; aprop = aprop->parent) {
  1221. if (aprop != sprop && aprop->slot == sprop->slot) {
  1222. pd->alias = ID_TO_VALUE(aprop->id);
  1223. break;
  1224. }
  1225. }
  1226. }
  1227. return JS_TRUE;
  1228. }
  1229. JS_PUBLIC_API(JSBool)
  1230. JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
  1231. {
  1232. JSClass *clasp;
  1233. JSScope *scope;
  1234. uint32 i, n;
  1235. JSPropertyDesc *pd;
  1236. JSScopeProperty *sprop;
  1237. clasp = OBJ_GET_CLASS(cx, obj);
  1238. if (!OBJ_IS_NATIVE(obj) || (clasp->flags & JSCLASS_NEW_ENUMERATE)) {
  1239. JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
  1240. JSMSG_CANT_DESCRIBE_PROPS, clasp->name);
  1241. return JS_FALSE;
  1242. }
  1243. if (!clasp->enumerate(cx, obj))
  1244. return JS_FALSE;
  1245. /* have no props, or object's scope has not mutated from that of proto */
  1246. scope = OBJ_SCOPE(obj);
  1247. if (scope->object != obj || scope->entryCount == 0) {
  1248. pda->length = 0;
  1249. pda->array = NULL;
  1250. return JS_TRUE;
  1251. }
  1252. n = STOBJ_NSLOTS(obj);
  1253. if (n > scope->entryCount)
  1254. n = scope->entryCount;
  1255. pd = (JSPropertyDesc *) JS_malloc(cx, (size_t)n * sizeof(JSPropertyDesc));
  1256. if (!pd)
  1257. return JS_FALSE;
  1258. i = 0;
  1259. for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
  1260. if (SCOPE_HAD_MIDDLE_DELETE(scope) && !SCOPE_HAS_PROPERTY(scope, sprop))
  1261. continue;
  1262. if (!js_AddRoot(cx, &pd[i].id, NULL))
  1263. goto bad;
  1264. if (!js_AddRoot(cx, &pd[i].value, NULL))
  1265. goto bad;
  1266. if (!JS_GetPropertyDesc(cx, obj, sprop, &pd[i]))
  1267. goto bad;
  1268. if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
  1269. goto bad;
  1270. if (++i == n)
  1271. break;
  1272. }
  1273. pda->length = i;
  1274. pda->array = pd;
  1275. return JS_TRUE;
  1276. bad:
  1277. pda->length = i + 1;
  1278. pda->array = pd;
  1279. JS_PutPropertyDescArray(cx, pda);
  1280. return JS_FALSE;
  1281. }
  1282. JS_PUBLIC_API(void)
  1283. JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
  1284. {
  1285. JSPropertyDesc *pd;
  1286. uint32 i;
  1287. pd = pda->array;
  1288. for (i = 0; i < pda->length; i++) {
  1289. js_RemoveRoot(cx->runtime, &pd[i].id);
  1290. js_RemoveRoot(cx->runtime, &pd[i].value);
  1291. if (pd[i].flags & JSPD_ALIAS)
  1292. js_RemoveRoot(cx->runtime, &pd[i].alias);
  1293. }
  1294. JS_free(cx, pd);
  1295. }
  1296. /************************************************************************/
  1297. JS_PUBLIC_API(JSBool)
  1298. JS_SetDebuggerHandler(JSRuntime *rt, JSTrapHandler handler, void *closure)
  1299. {
  1300. rt->globalDebugHooks.debuggerHandler = handler;
  1301. rt->globalDebugHooks.debuggerHandlerData = closure;
  1302. return JS_TRUE;
  1303. }
  1304. JS_PUBLIC_API(JSBool)
  1305. JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure)
  1306. {
  1307. rt->globalDebugHooks.sourceHandler = handler;
  1308. rt->globalDebugHooks.sourceHandlerData = closure;
  1309. return JS_TRUE;
  1310. }
  1311. JS_PUBLIC_API(JSBool)
  1312. JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
  1313. {
  1314. rt->globalDebugHooks.executeHook = hook;
  1315. rt->globalDebugHooks.executeHookData = closure;
  1316. return JS_TRUE;
  1317. }
  1318. JS_PUBLIC_API(JSBool)
  1319. JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure)
  1320. {
  1321. rt->globalDebugHooks.callHook = hook;
  1322. rt->globalDebugHooks.callHookData = closure;
  1323. return JS_TRUE;
  1324. }
  1325. JS_PUBLIC_API(JSBool)
  1326. JS_SetObjectHook(JSRuntime *rt, JSObjectHook hook, void *closure)
  1327. {
  1328. rt->globalDebugHooks.objectHook = hook;
  1329. rt->globalDebugHooks.objectHookData = closure;
  1330. return JS_TRUE;
  1331. }
  1332. JS_PUBLIC_API(JSBool)
  1333. JS_SetThrowHook(JSRuntime *rt, JSTrapHandler hook, void *closure)
  1334. {
  1335. rt->globalDebugHooks.throwHook = hook;
  1336. rt->globalDebugHooks.throwHookData = closure;
  1337. return JS_TRUE;
  1338. }
  1339. JS_PUBLIC_API(JSBool)
  1340. JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure)
  1341. {
  1342. rt->globalDebugHooks.debugErrorHook = hook;
  1343. rt->globalDebugHooks.debugErrorHookData = closure;
  1344. return JS_TRUE;
  1345. }
  1346. /************************************************************************/
  1347. JS_PUBLIC_API(size_t)
  1348. JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
  1349. {
  1350. size_t nbytes;
  1351. JSScope *scope;
  1352. nbytes = sizeof *obj;
  1353. if (obj->dslots) {
  1354. nbytes += ((uint32)obj->dslots[-1] - JS_INITIAL_NSLOTS + 1)
  1355. * sizeof obj->dslots[0];
  1356. }
  1357. if (OBJ_IS_NATIVE(obj)) {
  1358. scope = OBJ_SCOPE(obj);
  1359. if (scope->object == obj) {
  1360. nbytes += sizeof *scope;
  1361. nbytes += SCOPE_CAPACITY(scope) * sizeof(JSScopeProperty *);
  1362. }
  1363. }
  1364. return nbytes;
  1365. }
  1366. static size_t
  1367. GetAtomTotalSize(JSContext *cx, JSAtom *atom)
  1368. {
  1369. size_t nbytes;
  1370. nbytes = sizeof(JSAtom *) + sizeof(JSDHashEntryStub);
  1371. if (ATOM_IS_STRING(atom)) {
  1372. nbytes += sizeof(JSString);
  1373. nbytes += (JSFLATSTR_LENGTH(ATOM_TO_STRING(atom)) + 1) * sizeof(jschar);
  1374. } else if (ATOM_IS_DOUBLE(atom)) {
  1375. nbytes += sizeof(jsdouble);
  1376. }
  1377. return nbytes;
  1378. }
  1379. JS_PUBLIC_API(size_t)
  1380. JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun)
  1381. {
  1382. size_t nbytes;
  1383. nbytes = sizeof *fun;
  1384. nbytes += JS_GetObjectTotalSize(cx, FUN_OBJECT(fun));
  1385. if (FUN_INTERPRETED(fun))
  1386. nbytes += JS_GetScriptTotalSize(cx, fun->u.i.script);
  1387. if (fun->atom)
  1388. nbytes += GetAtomTotalSize(cx, fun->atom);
  1389. return nbytes;
  1390. }
  1391. #include "jsemit.h"
  1392. JS_PUBLIC_API(size_t)
  1393. JS_GetScriptTotalSize(JSContext *cx, JSScript *script)
  1394. {
  1395. size_t nbytes, pbytes;
  1396. jsatomid i;
  1397. jssrcnote *sn, *notes;
  1398. JSObjectArray *objarray;
  1399. JSPrincipals *principals;
  1400. nbytes = sizeof *script;
  1401. if (script->u.object)
  1402. nbytes += JS_GetObjectTotalSize(cx, script->u.object);
  1403. nbytes += script->length * sizeof script->code[0];
  1404. nbytes += script->atomMap.length * sizeof script->atomMap.vector[0];
  1405. for (i = 0; i < script->atomMap.length; i++)
  1406. nbytes += GetAtomTotalSize(cx, script->atomMap.vector[i]);
  1407. if (script->filename)
  1408. nbytes += strlen(script->filename) + 1;
  1409. notes = SCRIPT_NOTES(script);
  1410. for (sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn))
  1411. continue;
  1412. nbytes += (sn - notes + 1) * sizeof *sn;
  1413. if (script->objectsOffset != 0) {
  1414. objarray = JS_SCRIPT_OBJECTS(script);
  1415. i = objarray->length;
  1416. nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
  1417. do {
  1418. nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
  1419. } while (i != 0);
  1420. }
  1421. if (script->regexpsOffset != 0) {
  1422. objarray = JS_SCRIPT_REGEXPS(script);
  1423. i = objarray->length;
  1424. nbytes += sizeof *objarray + i * sizeof objarray->vector[0];
  1425. do {
  1426. nbytes += JS_GetObjectTotalSize(cx, objarray->vector[--i]);
  1427. } while (i != 0);
  1428. }
  1429. if (script->trynotesOffset != 0) {
  1430. nbytes += sizeof(JSTryNoteArray) +
  1431. JS_SCRIPT_TRYNOTES(script)->length * sizeof(JSTryNote);
  1432. }
  1433. principals = script->principals;
  1434. if (principals) {
  1435. JS_ASSERT(principals->refcount);
  1436. pbytes = sizeof *principals;
  1437. if (principals->refcount > 1)
  1438. pbytes = JS_HOWMANY(pbytes, principals->refcount);
  1439. nbytes += pbytes;
  1440. }
  1441. return nbytes;
  1442. }
  1443. JS_PUBLIC_API(uint32)
  1444. JS_GetTopScriptFilenameFlags(JSContext *cx, JSStackFrame *fp)
  1445. {
  1446. if (!fp)
  1447. fp = cx->fp;
  1448. while (fp) {
  1449. if (fp->script)
  1450. return JS_GetScriptFilenameFlags(fp->script);
  1451. fp = fp->down;
  1452. }
  1453. return 0;
  1454. }
  1455. JS_PUBLIC_API(uint32)
  1456. JS_GetScriptFilenameFlags(JSScript *script)
  1457. {
  1458. JS_ASSERT(script);
  1459. if (!script->filename)
  1460. return JSFILENAME_NULL;
  1461. return js_GetScriptFilenameFlags(script->filename);
  1462. }
  1463. JS_PUBLIC_API(JSBool)
  1464. JS_FlagScriptFilenamePrefix(JSRuntime *rt, const char *prefix, uint32 flags)
  1465. {
  1466. if (!js_SaveScriptFilenameRT(rt, prefix, flags))
  1467. return JS_FALSE;
  1468. return JS_TRUE;
  1469. }
  1470. JS_PUBLIC_API(JSBool)
  1471. JS_IsSystemObject(JSContext *cx, JSObject *obj)
  1472. {
  1473. return STOBJ_IS_SYSTEM(obj);
  1474. }
  1475. JS_PUBLIC_API(JSObject *)
  1476. JS_NewSystemObject(JSContext *cx, JSClass *clasp, JSObject *proto,
  1477. JSObject *parent, JSBool system)
  1478. {
  1479. JSObject *obj;
  1480. obj = js_NewObject(cx, clasp, proto, parent, 0);
  1481. if (obj && system)
  1482. STOBJ_SET_SYSTEM(obj);
  1483. return obj;
  1484. }
  1485. /************************************************************************/
  1486. JS_PUBLIC_API(JSDebugHooks *)
  1487. JS_GetGlobalDebugHooks(JSRuntime *rt)
  1488. {
  1489. return &rt->globalDebugHooks;
  1490. }
  1491. JS_PUBLIC_API(JSDebugHooks *)
  1492. JS_SetContextDebugHooks(JSContext *cx, JSDebugHooks *hooks)
  1493. {
  1494. JSDebugHooks *old;
  1495. JS_ASSERT(hooks);
  1496. old = cx->debugHooks;
  1497. cx->debugHooks = hooks;
  1498. return old;
  1499. }
  1500. #ifdef MOZ_SHARK
  1501. #include <CHUD/CHUD.h>
  1502. JS_PUBLIC_API(JSBool)
  1503. JS_StartChudRemote()
  1504. {
  1505. if (chudIsRemoteAccessAcquired() &&
  1506. (chudStartRemotePerfMonitor("Mozilla") == chudSuccess)) {
  1507. return JS_TRUE;
  1508. }
  1509. return JS_FALSE;
  1510. }
  1511. JS_PUBLIC_API(JSBool)
  1512. JS_StopChudRemote()
  1513. {
  1514. if (chudIsRemoteAccessAcquired() &&
  1515. (chudStopRemotePerfMonitor() == chudSuccess)) {
  1516. return JS_TRUE;
  1517. }
  1518. return JS_FALSE;
  1519. }
  1520. JS_PUBLIC_API(JSBool)
  1521. JS_ConnectShark()
  1522. {
  1523. if (!chudIsInitialized() && (chudInitialize() != chudSuccess))
  1524. return JS_FALSE;
  1525. if (chudAcquireRemoteAccess() != chudSuccess)
  1526. return JS_FALSE;
  1527. return JS_TRUE;
  1528. }
  1529. JS_PUBLIC_API(JSBool)
  1530. JS_DisconnectShark()
  1531. {
  1532. if (chudIsRemoteAccessAcquired() && (chudReleaseRemoteAccess() != chudSuccess))
  1533. return JS_FALSE;
  1534. return JS_TRUE;
  1535. }
  1536. JS_FRIEND_API(JSBool)
  1537. js_StartShark(JSContext *cx, JSObject *obj,
  1538. uintN argc, jsval *argv, jsval *rval)
  1539. {
  1540. if (!JS_StartChudRemote()) {
  1541. JS_ReportError(cx, "Error starting CHUD.");
  1542. }
  1543. return JS_TRUE;
  1544. }
  1545. JS_FRIEND_API(JSBool)
  1546. js_StopShark(JSContext *cx, JSObject *obj,
  1547. uintN argc, jsval *argv, jsval *rval)
  1548. {
  1549. if (!JS_StopChudRemote()) {
  1550. JS_ReportError(cx, "Error stoppiā€¦

Large files files are truncated, but you can click here to view the full file