Bumping manifests a=b2g-bump
[gecko.git] / js / public / Debug.h
blobea008c4a5e29fd7792e4c8c865a3a84901728555
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/. */
7 // Interfaces by which the embedding can interact with the Debugger API.
9 #ifndef js_Debug_h
10 #define js_Debug_h
12 #include "mozilla/Assertions.h"
13 #include "mozilla/Attributes.h"
14 #include "mozilla/MemoryReporting.h"
15 #include "mozilla/Move.h"
17 #include "jspubtd.h"
19 #include "js/RootingAPI.h"
20 #include "js/TypeDecls.h"
22 namespace js {
23 class Debugger;
26 namespace JS {
27 namespace dbg {
29 // Helping embedding code build objects for Debugger
30 // -------------------------------------------------
32 // Some Debugger API features lean on the embedding application to construct
33 // their result values. For example, Debugger.Frame.prototype.scriptEntryReason
34 // calls hooks provided by the embedding to construct values explaining why it
35 // invoked JavaScript; if F is a frame called from a mouse click event handler,
36 // F.scriptEntryReason would return an object of the form:
38 // { eventType: "mousedown", event: <object> }
40 // where <object> is a Debugger.Object whose referent is the event being
41 // dispatched.
43 // However, Debugger implements a trust boundary. Debuggee code may be
44 // considered untrusted; debugger code needs to be protected from debuggee
45 // getters, setters, proxies, Object.watch watchpoints, and any other feature
46 // that might accidentally cause debugger code to set the debuggee running. The
47 // Debugger API tries to make it easy to write safe debugger code by only
48 // offering access to debuggee objects via Debugger.Object instances, which
49 // ensure that only those operations whose explicit purpose is to invoke
50 // debuggee code do so. But this protective membrane is only helpful if we
51 // interpose Debugger.Object instances in all the necessary spots.
53 // SpiderMonkey's compartment system also implements a trust boundary. The
54 // debuggee and debugger are always in different compartments. Inter-compartment
55 // work requires carefully tracking which compartment each JSObject or JS::Value
56 // belongs to, and ensuring that is is correctly wrapped for each operation.
58 // It seems precarious to expect the embedding's hooks to implement these trust
59 // boundaries. Instead, the JS::dbg::Builder API segregates the code which
60 // constructs trusted objects from that which deals with untrusted objects.
61 // Trusted objects have an entirely different C++ type, so code that improperly
62 // mixes trusted and untrusted objects is caught at compile time.
64 // In the structure shown above, there are two trusted objects, and one
65 // untrusted object:
67 // - The overall object, with the 'eventType' and 'event' properties, is a
68 // trusted object. We're going to return it to D.F.p.scriptEntryReason's
69 // caller, which will handle it directly.
71 // - The Debugger.Object instance appearing as the value of the 'event' property
72 // is a trusted object. It belongs to the same Debugger instance as the
73 // Debugger.Frame instance whose scriptEntryReason accessor was called, and
74 // presents a safe reflection-oriented API for inspecting its referent, which
75 // is:
77 // - The actual event object, an untrusted object, and the referent of the
78 // Debugger.Object above. (Content can do things like replacing accessors on
79 // Event.prototype.)
81 // Using JS::dbg::Builder, all objects and values the embedding deals with
82 // directly are considered untrusted, and are assumed to be debuggee values. The
83 // only way to construct trusted objects is to use Builder's own methods, which
84 // return a separate Object type. The only way to set a property on a trusted
85 // object is through that Object type. The actual trusted object is never
86 // exposed to the embedding.
88 // So, for example, the embedding might use code like the following to construct
89 // the object shown above, given a Builder passed to it by Debugger:
91 // bool
92 // MyScriptEntryReason::explain(JSContext* cx,
93 // Builder& builder,
94 // Builder::Object& result)
95 // {
96 // JSObject* eventObject = ... obtain debuggee event object somehow ...;
97 // if (!eventObject)
98 // return false;
99 // result = builder.newObject(cx);
100 // return result &&
101 // result.defineProperty(cx, "eventType", SafelyFetchType(eventObject)) &&
102 // result.defineProperty(cx, "event", eventObject);
103 // }
106 // Object::defineProperty also accepts an Object as the value to store on the
107 // property. By its type, we know that the value is trusted, so we set it
108 // directly as the property's value, without interposing a Debugger.Object
109 // wrapper. This allows the embedding to builted nested structures of trusted
110 // objects.
112 // The Builder and Builder::Object methods take care of doing whatever
113 // compartment switching and wrapping are necessary to construct the trusted
114 // values in the Debugger's compartment.
116 // The Object type is self-rooting. Construction, assignment, and destruction
117 // all properly root the referent object.
119 class BuilderOrigin;
121 class Builder {
122 // The Debugger instance whose client we are building a value for. We build
123 // objects in this object's compartment.
124 PersistentRootedObject debuggerObject;
126 // debuggerObject's Debugger structure, for convenience.
127 js::Debugger* debugger;
129 // Check that |thing| is in the same compartment as our debuggerObject. Used
130 // for assertions when constructing BuiltThings. We can overload this as we
131 // add more instantiations of BuiltThing.
132 #if DEBUG
133 void assertBuilt(JSObject* obj);
134 #else
135 void assertBuilt(JSObject* obj) { }
136 #endif
138 protected:
139 // A reference to a trusted object or value. At the moment, we only use it
140 // with JSObject*.
141 template<typename T>
142 class BuiltThing {
143 friend class BuilderOrigin;
145 void nonNull() {}
147 protected:
148 // The Builder to which this trusted thing belongs.
149 Builder& owner;
151 // A rooted reference to our value.
152 PersistentRooted<T> value;
154 BuiltThing(JSContext* cx, Builder& owner_, T value_ = js::GCMethods<T>::initial())
155 : owner(owner_), value(cx, value_)
157 owner.assertBuilt(value_);
160 // Forward some things from our owner, for convenience.
161 js::Debugger* debugger() const { return owner.debugger; }
162 JSObject* debuggerObject() const { return owner.debuggerObject; }
164 public:
165 BuiltThing(const BuiltThing& rhs) : owner(rhs.owner), value(rhs.value) { }
166 BuiltThing& operator=(const BuiltThing& rhs) {
167 MOZ_ASSERT(&owner == &rhs.owner);
168 owner.assertBuilt(rhs.value);
169 value = rhs.value;
170 return *this;
173 typedef void (BuiltThing::* ConvertibleToBool)();
174 operator ConvertibleToBool() const {
175 // If we ever instantiate BuiltThink<Value>, this might not suffice.
176 return value ? &BuiltThing::nonNull : 0;
179 private:
180 BuiltThing() = delete;
183 public:
184 // A reference to a trusted object, possibly null. Instances of Object are
185 // always properly rooted. They can be copied and assigned, as if they were
186 // pointers.
187 class Object: private BuiltThing<JSObject*> {
188 friend class Builder; // for construction
189 friend class BuilderOrigin; // for unwrapping
191 typedef BuiltThing<JSObject*> Base;
193 // This is private, because only Builders can create Objects that
194 // actually point to something (hence the 'friend' declaration).
195 Object(JSContext* cx, Builder& owner_, HandleObject obj) : Base(cx, owner_, obj.get()) { }
197 bool definePropertyToTrusted(JSContext* cx, const char* name,
198 JS::MutableHandleValue value);
200 public:
201 Object(JSContext* cx, Builder& owner_) : Base(cx, owner_, nullptr) { }
202 Object(const Object& rhs) : Base(rhs) { }
204 // Our automatically-generated assignment operator can see our base
205 // class's assignment operator, so we don't need to write one out here.
207 // Set the property named |name| on this object to |value|.
209 // If |value| is a string or primitive, re-wrap it for the debugger's
210 // compartment.
212 // If |value| is an object, assume it is a debuggee object and make a
213 // Debugger.Object instance referring to it. Set that as the propery's
214 // value.
216 // If |value| is another trusted object, store it directly as the
217 // property's value.
219 // On error, report the problem on cx and return false.
220 bool defineProperty(JSContext* cx, const char* name, JS::HandleValue value);
221 bool defineProperty(JSContext* cx, const char* name, JS::HandleObject value);
222 bool defineProperty(JSContext* cx, const char* name, Object& value);
224 using Base::ConvertibleToBool;
225 using Base::operator ConvertibleToBool;
228 // Build an empty object for direct use by debugger code, owned by this
229 // Builder. If an error occurs, report it on cx and return a false Object.
230 Object newObject(JSContext* cx);
232 protected:
233 Builder(JSContext* cx, js::Debugger* debugger);
236 // Debugger itself instantiates this subclass of Builder, which can unwrap
237 // BuiltThings that belong to it.
238 class BuilderOrigin : public Builder {
239 template<typename T>
240 T unwrapAny(const BuiltThing<T>& thing) {
241 MOZ_ASSERT(&thing.owner == this);
242 return thing.value.get();
245 public:
246 BuilderOrigin(JSContext* cx, js::Debugger* debugger_)
247 : Builder(cx, debugger_)
250 JSObject* unwrap(Object& object) { return unwrapAny(object); }
255 // Finding the size of blocks allocated with malloc
256 // ------------------------------------------------
258 // Debugger.Memory wants to be able to report how many bytes items in memory are
259 // consuming. To do this, it needs a function that accepts a pointer to a block,
260 // and returns the number of bytes allocated to that block. SpiderMonkey itself
261 // doesn't know which function is appropriate to use, but the embedding does.
263 // Tell Debuggers in |runtime| to use |mallocSizeOf| to find the size of
264 // malloc'd blocks.
265 void SetDebuggerMallocSizeOf(JSRuntime* runtime, mozilla::MallocSizeOf mallocSizeOf);
269 // Handlers for observing Promises
270 // -------------------------------
272 // The Debugger wants to observe behavior of promises, which are implemented by
273 // Gecko with webidl and which SpiderMonkey knows nothing about. On the other
274 // hand, Gecko knows nothing about which (if any) debuggers are observing a
275 // promise's global. The compromise is that Gecko is responsible for calling
276 // these handlers at the appropriate times, and SpiderMonkey will handle
277 // notifying any Debugger instances that are observing the given promise's
278 // global.
280 // Notify any Debugger instances observing this promise's global that a new
281 // promise was allocated.
282 JS_PUBLIC_API(void)
283 onNewPromise(JSContext* cx, HandleObject promise);
285 // Notify any Debugger instances observing this promise's global that the
286 // promise has settled (ie, it has either been fulfilled or rejected). Note that
287 // this is *not* equivalent to the promise resolution (ie, the promise's fate
288 // getting locked in) because you can resolve a promise with another pending
289 // promise, in which case neither promise has settled yet.
291 // It is Gecko's responsibility to ensure that this is never called on the same
292 // promise more than once (because a promise can only make the transition from
293 // unsettled to settled once).
294 JS_PUBLIC_API(void)
295 onPromiseSettled(JSContext* cx, HandleObject promise);
299 // Return true if the given value is a Debugger object, false otherwise.
300 JS_PUBLIC_API(bool)
301 IsDebugger(JS::Value val);
303 } // namespace dbg
304 } // namespace JS
307 #endif /* js_Debug_h */