LCOV - code coverage report
Current view: top level - js/public - Debug.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 8 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13