/src/mozilla-central/devtools/platform/nsJSInspector.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | #include "nsJSInspector.h" |
7 | | #include "nsIXPConnect.h" |
8 | | #include "nsThreadUtils.h" |
9 | | #include "jsfriendapi.h" |
10 | | #include "mozilla/HoldDropJSObjects.h" |
11 | | #include "mozilla/ModuleUtils.h" |
12 | | #include "mozilla/dom/ScriptSettings.h" |
13 | | #include "nsServiceManagerUtils.h" |
14 | | #include "nsMemory.h" |
15 | | #include "nsArray.h" |
16 | | #include "nsTArray.h" |
17 | | |
18 | | #define JSINSPECTOR_CONTRACTID \ |
19 | | "@mozilla.org/jsinspector;1" |
20 | | |
21 | | #define JSINSPECTOR_CID \ |
22 | | { 0xec5aa99c, 0x7abb, 0x4142, { 0xac, 0x5f, 0xaa, 0xb2, 0x41, 0x9e, 0x38, 0xe2 } } |
23 | | |
24 | | namespace mozilla { |
25 | | namespace jsinspector { |
26 | | |
27 | | NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSInspector) |
28 | | |
29 | 0 | NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSInspector) |
30 | 0 | NS_INTERFACE_MAP_ENTRY(nsISupports) |
31 | 0 | NS_INTERFACE_MAP_ENTRY(nsIJSInspector) |
32 | 0 | NS_INTERFACE_MAP_END |
33 | | |
34 | | NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSInspector) |
35 | | |
36 | | NS_IMPL_CYCLE_COLLECTING_ADDREF(nsJSInspector) |
37 | | NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSInspector) |
38 | | |
39 | 0 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSInspector) |
40 | 0 | NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END |
41 | | |
42 | 0 | NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSInspector) |
43 | 0 | tmp->mRequestors.Clear(); |
44 | 0 | tmp->mLastRequestor = JS::NullValue(); |
45 | 0 | NS_IMPL_CYCLE_COLLECTION_UNLINK_END |
46 | | |
47 | 0 | NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSInspector) |
48 | 0 | for (uint32_t i = 0; i < tmp->mRequestors.Length(); ++i) { |
49 | 0 | NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mRequestors[i]) |
50 | 0 | } |
51 | 0 | NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mLastRequestor) |
52 | 0 | NS_IMPL_CYCLE_COLLECTION_TRACE_END |
53 | | |
54 | | nsJSInspector::nsJSInspector() : mNestedLoopLevel(0), mRequestors(1), mLastRequestor(JS::NullValue()) |
55 | 0 | { |
56 | 0 | } |
57 | | |
58 | | nsJSInspector::~nsJSInspector() |
59 | 0 | { |
60 | 0 | MOZ_ASSERT(mRequestors.Length() == 0); |
61 | 0 | MOZ_ASSERT(mLastRequestor.isNull()); |
62 | 0 | mozilla::DropJSObjects(this); |
63 | 0 | } |
64 | | |
65 | | NS_IMETHODIMP |
66 | | nsJSInspector::EnterNestedEventLoop(JS::Handle<JS::Value> requestor, uint32_t *out) |
67 | 0 | { |
68 | 0 | nsresult rv = NS_OK; |
69 | 0 |
|
70 | 0 | mLastRequestor = requestor; |
71 | 0 | mRequestors.AppendElement(requestor); |
72 | 0 | mozilla::HoldJSObjects(this); |
73 | 0 |
|
74 | 0 | mozilla::dom::AutoNoJSAPI nojsapi; |
75 | 0 |
|
76 | 0 | uint32_t nestLevel = ++mNestedLoopLevel; |
77 | 0 | if (!SpinEventLoopUntil([&]() { return mNestedLoopLevel < nestLevel; })) { |
78 | 0 | rv = NS_ERROR_UNEXPECTED; |
79 | 0 | } |
80 | 0 |
|
81 | 0 | NS_ASSERTION(mNestedLoopLevel <= nestLevel, |
82 | 0 | "nested event didn't unwind properly"); |
83 | 0 |
|
84 | 0 | if (mNestedLoopLevel == nestLevel) { |
85 | 0 | mLastRequestor = mRequestors.ElementAt(--mNestedLoopLevel); |
86 | 0 | } |
87 | 0 |
|
88 | 0 | *out = mNestedLoopLevel; |
89 | 0 | return rv; |
90 | 0 | } |
91 | | |
92 | | NS_IMETHODIMP |
93 | | nsJSInspector::ExitNestedEventLoop(uint32_t *out) |
94 | 0 | { |
95 | 0 | if (mNestedLoopLevel > 0) { |
96 | 0 | mRequestors.RemoveElementAt(--mNestedLoopLevel); |
97 | 0 | if (mNestedLoopLevel > 0) |
98 | 0 | mLastRequestor = mRequestors.ElementAt(mNestedLoopLevel - 1); |
99 | 0 | else |
100 | 0 | mLastRequestor = JS::NullValue(); |
101 | 0 | } else { |
102 | 0 | return NS_ERROR_FAILURE; |
103 | 0 | } |
104 | 0 | |
105 | 0 | *out = mNestedLoopLevel; |
106 | 0 |
|
107 | 0 | return NS_OK; |
108 | 0 | } |
109 | | |
110 | | NS_IMETHODIMP |
111 | | nsJSInspector::GetEventLoopNestLevel(uint32_t *out) |
112 | 0 | { |
113 | 0 | *out = mNestedLoopLevel; |
114 | 0 | return NS_OK; |
115 | 0 | } |
116 | | |
117 | | NS_IMETHODIMP |
118 | | nsJSInspector::GetLastNestRequestor(JS::MutableHandle<JS::Value> out) |
119 | 0 | { |
120 | 0 | out.set(mLastRequestor); |
121 | 0 | return NS_OK; |
122 | 0 | } |
123 | | |
124 | | } // namespace jsinspector |
125 | | } // namespace mozilla |
126 | | |
127 | | NS_DEFINE_NAMED_CID(JSINSPECTOR_CID); |
128 | | |
129 | | static const mozilla::Module::CIDEntry kJSInspectorCIDs[] = { |
130 | | { &kJSINSPECTOR_CID, false, nullptr, mozilla::jsinspector::nsJSInspectorConstructor }, |
131 | | { nullptr } |
132 | | }; |
133 | | |
134 | | static const mozilla::Module::ContractIDEntry kJSInspectorContracts[] = { |
135 | | { JSINSPECTOR_CONTRACTID, &kJSINSPECTOR_CID }, |
136 | | { nullptr } |
137 | | }; |
138 | | |
139 | | static const mozilla::Module kJSInspectorModule = { |
140 | | mozilla::Module::kVersion, |
141 | | kJSInspectorCIDs, |
142 | | kJSInspectorContracts |
143 | | }; |
144 | | |
145 | | NSMODULE_DEFN(jsinspector) = &kJSInspectorModule; |