Debug.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * vim: set ts=8 sts=4 et sw=4 tw=99:
  3. * This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. // Interfaces by which the embedding can interact with the Debugger API.
  7. #ifndef js_Debug_h
  8. #define js_Debug_h
  9. #include "mozilla/Assertions.h"
  10. #include "mozilla/Attributes.h"
  11. #include "mozilla/MemoryReporting.h"
  12. #include "jsapi.h"
  13. #include "jspubtd.h"
  14. #include "js/GCAPI.h"
  15. #include "js/RootingAPI.h"
  16. #include "js/TypeDecls.h"
  17. namespace js {
  18. class Debugger;
  19. } // namespace js
  20. namespace JS {
  21. namespace dbg {
  22. // Helping embedding code build objects for Debugger
  23. // -------------------------------------------------
  24. //
  25. // Some Debugger API features lean on the embedding application to construct
  26. // their result values. For example, Debugger.Frame.prototype.scriptEntryReason
  27. // calls hooks provided by the embedding to construct values explaining why it
  28. // invoked JavaScript; if F is a frame called from a mouse click event handler,
  29. // F.scriptEntryReason would return an object of the form:
  30. //
  31. // { eventType: "mousedown", event: <object> }
  32. //
  33. // where <object> is a Debugger.Object whose referent is the event being
  34. // dispatched.
  35. //
  36. // However, Debugger implements a trust boundary. Debuggee code may be
  37. // considered untrusted; debugger code needs to be protected from debuggee
  38. // getters, setters, proxies, Object.watch watchpoints, and any other feature
  39. // that might accidentally cause debugger code to set the debuggee running. The
  40. // Debugger API tries to make it easy to write safe debugger code by only
  41. // offering access to debuggee objects via Debugger.Object instances, which
  42. // ensure that only those operations whose explicit purpose is to invoke
  43. // debuggee code do so. But this protective membrane is only helpful if we
  44. // interpose Debugger.Object instances in all the necessary spots.
  45. //
  46. // SpiderMonkey's compartment system also implements a trust boundary. The
  47. // debuggee and debugger are always in different compartments. Inter-compartment
  48. // work requires carefully tracking which compartment each JSObject or JS::Value
  49. // belongs to, and ensuring that is is correctly wrapped for each operation.
  50. //
  51. // It seems precarious to expect the embedding's hooks to implement these trust
  52. // boundaries. Instead, the JS::dbg::Builder API segregates the code which
  53. // constructs trusted objects from that which deals with untrusted objects.
  54. // Trusted objects have an entirely different C++ type, so code that improperly
  55. // mixes trusted and untrusted objects is caught at compile time.
  56. //
  57. // In the structure shown above, there are two trusted objects, and one
  58. // untrusted object:
  59. //
  60. // - The overall object, with the 'eventType' and 'event' properties, is a
  61. // trusted object. We're going to return it to D.F.p.scriptEntryReason's
  62. // caller, which will handle it directly.
  63. //
  64. // - The Debugger.Object instance appearing as the value of the 'event' property
  65. // is a trusted object. It belongs to the same Debugger instance as the
  66. // Debugger.Frame instance whose scriptEntryReason accessor was called, and
  67. // presents a safe reflection-oriented API for inspecting its referent, which
  68. // is:
  69. //
  70. // - The actual event object, an untrusted object, and the referent of the
  71. // Debugger.Object above. (Content can do things like replacing accessors on
  72. // Event.prototype.)
  73. //
  74. // Using JS::dbg::Builder, all objects and values the embedding deals with
  75. // directly are considered untrusted, and are assumed to be debuggee values. The
  76. // only way to construct trusted objects is to use Builder's own methods, which
  77. // return a separate Object type. The only way to set a property on a trusted
  78. // object is through that Object type. The actual trusted object is never
  79. // exposed to the embedding.
  80. //
  81. // So, for example, the embedding might use code like the following to construct
  82. // the object shown above, given a Builder passed to it by Debugger:
  83. //
  84. // bool
  85. // MyScriptEntryReason::explain(JSContext* cx,
  86. // Builder& builder,
  87. // Builder::Object& result)
  88. // {
  89. // JSObject* eventObject = ... obtain debuggee event object somehow ...;
  90. // if (!eventObject)
  91. // return false;
  92. // result = builder.newObject(cx);
  93. // return result &&
  94. // result.defineProperty(cx, "eventType", SafelyFetchType(eventObject)) &&
  95. // result.defineProperty(cx, "event", eventObject);
  96. // }
  97. //
  98. //
  99. // Object::defineProperty also accepts an Object as the value to store on the
  100. // property. By its type, we know that the value is trusted, so we set it
  101. // directly as the property's value, without interposing a Debugger.Object
  102. // wrapper. This allows the embedding to builted nested structures of trusted
  103. // objects.
  104. //
  105. // The Builder and Builder::Object methods take care of doing whatever
  106. // compartment switching and wrapping are necessary to construct the trusted
  107. // values in the Debugger's compartment.
  108. //
  109. // The Object type is self-rooting. Construction, assignment, and destruction
  110. // all properly root the referent object.
  111. class BuilderOrigin;
  112. class Builder {
  113. // The Debugger instance whose client we are building a value for. We build
  114. // objects in this object's compartment.
  115. PersistentRootedObject debuggerObject;
  116. // debuggerObject's Debugger structure, for convenience.
  117. js::Debugger* debugger;
  118. // Check that |thing| is in the same compartment as our debuggerObject. Used
  119. // for assertions when constructing BuiltThings. We can overload this as we
  120. // add more instantiations of BuiltThing.
  121. #if DEBUG
  122. void assertBuilt(JSObject* obj);
  123. #else
  124. void assertBuilt(JSObject* obj) { }
  125. #endif
  126. protected:
  127. // A reference to a trusted object or value. At the moment, we only use it
  128. // with JSObject*.
  129. template<typename T>
  130. class BuiltThing {
  131. friend class BuilderOrigin;
  132. protected:
  133. // The Builder to which this trusted thing belongs.
  134. Builder& owner;
  135. // A rooted reference to our value.
  136. PersistentRooted<T> value;
  137. BuiltThing(JSContext* cx, Builder& owner_, T value_ = GCPolicy<T>::initial())
  138. : owner(owner_), value(cx, value_)
  139. {
  140. owner.assertBuilt(value_);
  141. }
  142. // Forward some things from our owner, for convenience.
  143. js::Debugger* debugger() const { return owner.debugger; }
  144. JSObject* debuggerObject() const { return owner.debuggerObject; }
  145. public:
  146. BuiltThing(const BuiltThing& rhs) : owner(rhs.owner), value(rhs.value) { }
  147. BuiltThing& operator=(const BuiltThing& rhs) {
  148. MOZ_ASSERT(&owner == &rhs.owner);
  149. owner.assertBuilt(rhs.value);
  150. value = rhs.value;
  151. return *this;
  152. }
  153. explicit operator bool() const {
  154. // If we ever instantiate BuiltThing<Value>, this might not suffice.
  155. return value;
  156. }
  157. private:
  158. BuiltThing() = delete;
  159. };
  160. public:
  161. // A reference to a trusted object, possibly null. Instances of Object are
  162. // always properly rooted. They can be copied and assigned, as if they were
  163. // pointers.
  164. class Object: private BuiltThing<JSObject*> {
  165. friend class Builder; // for construction
  166. friend class BuilderOrigin; // for unwrapping
  167. typedef BuiltThing<JSObject*> Base;
  168. // This is private, because only Builders can create Objects that
  169. // actually point to something (hence the 'friend' declaration).
  170. Object(JSContext* cx, Builder& owner_, HandleObject obj) : Base(cx, owner_, obj.get()) { }
  171. bool definePropertyToTrusted(JSContext* cx, const char* name,
  172. JS::MutableHandleValue value);
  173. public:
  174. Object(JSContext* cx, Builder& owner_) : Base(cx, owner_, nullptr) { }
  175. Object(const Object& rhs) : Base(rhs) { }
  176. // Our automatically-generated assignment operator can see our base
  177. // class's assignment operator, so we don't need to write one out here.
  178. // Set the property named |name| on this object to |value|.
  179. //
  180. // If |value| is a string or primitive, re-wrap it for the debugger's
  181. // compartment.
  182. //
  183. // If |value| is an object, assume it is a debuggee object and make a
  184. // Debugger.Object instance referring to it. Set that as the propery's
  185. // value.
  186. //
  187. // If |value| is another trusted object, store it directly as the
  188. // property's value.
  189. //
  190. // On error, report the problem on cx and return false.
  191. bool defineProperty(JSContext* cx, const char* name, JS::HandleValue value);
  192. bool defineProperty(JSContext* cx, const char* name, JS::HandleObject value);
  193. bool defineProperty(JSContext* cx, const char* name, Object& value);
  194. using Base::operator bool;
  195. };
  196. // Build an empty object for direct use by debugger code, owned by this
  197. // Builder. If an error occurs, report it on cx and return a false Object.
  198. Object newObject(JSContext* cx);
  199. protected:
  200. Builder(JSContext* cx, js::Debugger* debugger);
  201. };
  202. // Debugger itself instantiates this subclass of Builder, which can unwrap
  203. // BuiltThings that belong to it.
  204. class BuilderOrigin : public Builder {
  205. template<typename T>
  206. T unwrapAny(const BuiltThing<T>& thing) {
  207. MOZ_ASSERT(&thing.owner == this);
  208. return thing.value.get();
  209. }
  210. public:
  211. BuilderOrigin(JSContext* cx, js::Debugger* debugger_)
  212. : Builder(cx, debugger_)
  213. { }
  214. JSObject* unwrap(Object& object) { return unwrapAny(object); }
  215. };
  216. // Finding the size of blocks allocated with malloc
  217. // ------------------------------------------------
  218. //
  219. // Debugger.Memory wants to be able to report how many bytes items in memory are
  220. // consuming. To do this, it needs a function that accepts a pointer to a block,
  221. // and returns the number of bytes allocated to that block. SpiderMonkey itself
  222. // doesn't know which function is appropriate to use, but the embedding does.
  223. // Tell Debuggers in |cx| to use |mallocSizeOf| to find the size of
  224. // malloc'd blocks.
  225. JS_PUBLIC_API(void)
  226. SetDebuggerMallocSizeOf(JSContext* cx, mozilla::MallocSizeOf mallocSizeOf);
  227. // Get the MallocSizeOf function that the given context is using to find the
  228. // size of malloc'd blocks.
  229. JS_PUBLIC_API(mozilla::MallocSizeOf)
  230. GetDebuggerMallocSizeOf(JSContext* cx);
  231. // Debugger and Garbage Collection Events
  232. // --------------------------------------
  233. //
  234. // The Debugger wants to report about its debuggees' GC cycles, however entering
  235. // JS after a GC is troublesome since SpiderMonkey will often do something like
  236. // force a GC and then rely on the nursery being empty. If we call into some
  237. // Debugger's hook after the GC, then JS runs and the nursery won't be
  238. // empty. Instead, we rely on embedders to call back into SpiderMonkey after a
  239. // GC and notify Debuggers to call their onGarbageCollection hook.
  240. // For each Debugger that observed a debuggee involved in the given GC event,
  241. // call its `onGarbageCollection` hook.
  242. JS_PUBLIC_API(bool)
  243. FireOnGarbageCollectionHook(JSContext* cx, GarbageCollectionEvent::Ptr&& data);
  244. // Handlers for observing Promises
  245. // -------------------------------
  246. //
  247. // The Debugger wants to observe behavior of promises, which are implemented by
  248. // Gecko with webidl and which SpiderMonkey knows nothing about. On the other
  249. // hand, Gecko knows nothing about which (if any) debuggers are observing a
  250. // promise's global. The compromise is that Gecko is responsible for calling
  251. // these handlers at the appropriate times, and SpiderMonkey will handle
  252. // notifying any Debugger instances that are observing the given promise's
  253. // global.
  254. // Notify any Debugger instances observing this promise's global that a new
  255. // promise was allocated.
  256. JS_PUBLIC_API(void)
  257. onNewPromise(JSContext* cx, HandleObject promise);
  258. // Notify any Debugger instances observing this promise's global that the
  259. // promise has settled (ie, it has either been fulfilled or rejected). Note that
  260. // this is *not* equivalent to the promise resolution (ie, the promise's fate
  261. // getting locked in) because you can resolve a promise with another pending
  262. // promise, in which case neither promise has settled yet.
  263. //
  264. // It is Gecko's responsibility to ensure that this is never called on the same
  265. // promise more than once (because a promise can only make the transition from
  266. // unsettled to settled once).
  267. JS_PUBLIC_API(void)
  268. onPromiseSettled(JSContext* cx, HandleObject promise);
  269. // Return true if the given value is a Debugger object, false otherwise.
  270. JS_PUBLIC_API(bool)
  271. IsDebugger(JSObject& obj);
  272. // Append each of the debuggee global objects observed by the Debugger object
  273. // |dbgObj| to |vector|. Returns true on success, false on failure.
  274. JS_PUBLIC_API(bool)
  275. GetDebuggeeGlobals(JSContext* cx, JSObject& dbgObj, AutoObjectVector& vector);
  276. // Hooks for reporting where JavaScript execution began.
  277. //
  278. // Our performance tools would like to be able to label blocks of JavaScript
  279. // execution with the function name and source location where execution began:
  280. // the event handler, the callback, etc.
  281. //
  282. // Construct an instance of this class on the stack, providing a JSContext
  283. // belonging to the runtime in which execution will occur. Each time we enter
  284. // JavaScript --- specifically, each time we push a JavaScript stack frame that
  285. // has no older JS frames younger than this AutoEntryMonitor --- we will
  286. // call the appropriate |Entry| member function to indicate where we've begun
  287. // execution.
  288. class MOZ_STACK_CLASS AutoEntryMonitor {
  289. JSRuntime* runtime_;
  290. AutoEntryMonitor* savedMonitor_;
  291. public:
  292. explicit AutoEntryMonitor(JSContext* cx);
  293. ~AutoEntryMonitor();
  294. // SpiderMonkey reports the JavaScript entry points occuring within this
  295. // AutoEntryMonitor's scope to the following member functions, which the
  296. // embedding is expected to override.
  297. //
  298. // It is important to note that |asyncCause| is owned by the caller and its
  299. // lifetime must outlive the lifetime of the AutoEntryMonitor object. It is
  300. // strongly encouraged that |asyncCause| be a string constant or similar
  301. // statically allocated string.
  302. // We have begun executing |function|. Note that |function| may not be the
  303. // actual closure we are running, but only the canonical function object to
  304. // which the script refers.
  305. virtual void Entry(JSContext* cx, JSFunction* function,
  306. HandleValue asyncStack,
  307. const char* asyncCause) = 0;
  308. // Execution has begun at the entry point of |script|, which is not a
  309. // function body. (This is probably being executed by 'eval' or some
  310. // JSAPI equivalent.)
  311. virtual void Entry(JSContext* cx, JSScript* script,
  312. HandleValue asyncStack,
  313. const char* asyncCause) = 0;
  314. // Execution of the function or script has ended.
  315. virtual void Exit(JSContext* cx) { }
  316. };
  317. } // namespace dbg
  318. } // namespace JS
  319. #endif /* js_Debug_h */