|
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 "js/OldDebugAPI.h" |
|
11 #include "mozilla/HoldDropJSObjects.h" |
|
12 #include "mozilla/ModuleUtils.h" |
|
13 #include "mozilla/dom/ScriptSettings.h" |
|
14 #include "nsServiceManagerUtils.h" |
|
15 #include "nsMemory.h" |
|
16 #include "nsArray.h" |
|
17 #include "nsTArray.h" |
|
18 |
|
19 #define JSINSPECTOR_CONTRACTID \ |
|
20 "@mozilla.org/jsinspector;1" |
|
21 |
|
22 #define JSINSPECTOR_CID \ |
|
23 { 0xec5aa99c, 0x7abb, 0x4142, { 0xac, 0x5f, 0xaa, 0xb2, 0x41, 0x9e, 0x38, 0xe2 } } |
|
24 |
|
25 namespace mozilla { |
|
26 namespace jsinspector { |
|
27 |
|
28 NS_GENERIC_FACTORY_CONSTRUCTOR(nsJSInspector) |
|
29 |
|
30 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSInspector) |
|
31 NS_INTERFACE_MAP_ENTRY(nsISupports) |
|
32 NS_INTERFACE_MAP_ENTRY(nsIJSInspector) |
|
33 NS_INTERFACE_MAP_END |
|
34 |
|
35 NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSInspector) |
|
36 |
|
37 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsJSInspector) |
|
38 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsJSInspector) |
|
39 |
|
40 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSInspector) |
|
41 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS |
|
42 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END |
|
43 |
|
44 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSInspector) |
|
45 tmp->mRequestors.Clear(); |
|
46 tmp->mLastRequestor = JS::NullValue(); |
|
47 NS_IMPL_CYCLE_COLLECTION_UNLINK_END |
|
48 |
|
49 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSInspector) |
|
50 for (uint32_t i = 0; i < tmp->mRequestors.Length(); ++i) { |
|
51 NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mRequestors[i]) |
|
52 } |
|
53 NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mLastRequestor) |
|
54 NS_IMPL_CYCLE_COLLECTION_TRACE_END |
|
55 |
|
56 nsJSInspector::nsJSInspector() : mNestedLoopLevel(0), mRequestors(1), mLastRequestor(JSVAL_NULL) |
|
57 { |
|
58 } |
|
59 |
|
60 nsJSInspector::~nsJSInspector() |
|
61 { |
|
62 MOZ_ASSERT(mRequestors.Length() == 0); |
|
63 MOZ_ASSERT(mLastRequestor.isNull()); |
|
64 mozilla::DropJSObjects(this); |
|
65 } |
|
66 |
|
67 NS_IMETHODIMP |
|
68 nsJSInspector::EnterNestedEventLoop(JS::Handle<JS::Value> requestor, uint32_t *out) |
|
69 { |
|
70 nsresult rv = NS_OK; |
|
71 |
|
72 mLastRequestor = requestor; |
|
73 mRequestors.AppendElement(requestor); |
|
74 mozilla::HoldJSObjects(this); |
|
75 |
|
76 mozilla::dom::AutoNoJSAPI nojsapi; |
|
77 |
|
78 uint32_t nestLevel = ++mNestedLoopLevel; |
|
79 while (NS_SUCCEEDED(rv) && mNestedLoopLevel >= nestLevel) { |
|
80 if (!NS_ProcessNextEvent()) |
|
81 rv = NS_ERROR_UNEXPECTED; |
|
82 } |
|
83 |
|
84 NS_ASSERTION(mNestedLoopLevel <= nestLevel, |
|
85 "nested event didn't unwind properly"); |
|
86 |
|
87 if (mNestedLoopLevel == nestLevel) { |
|
88 mLastRequestor = mRequestors.ElementAt(--mNestedLoopLevel); |
|
89 } |
|
90 |
|
91 *out = mNestedLoopLevel; |
|
92 return rv; |
|
93 } |
|
94 |
|
95 NS_IMETHODIMP |
|
96 nsJSInspector::ExitNestedEventLoop(uint32_t *out) |
|
97 { |
|
98 if (mNestedLoopLevel > 0) { |
|
99 mRequestors.RemoveElementAt(--mNestedLoopLevel); |
|
100 if (mNestedLoopLevel > 0) |
|
101 mLastRequestor = mRequestors.ElementAt(mNestedLoopLevel - 1); |
|
102 else |
|
103 mLastRequestor = JSVAL_NULL; |
|
104 } else { |
|
105 return NS_ERROR_FAILURE; |
|
106 } |
|
107 |
|
108 *out = mNestedLoopLevel; |
|
109 |
|
110 return NS_OK; |
|
111 } |
|
112 |
|
113 NS_IMETHODIMP |
|
114 nsJSInspector::GetEventLoopNestLevel(uint32_t *out) |
|
115 { |
|
116 *out = mNestedLoopLevel; |
|
117 return NS_OK; |
|
118 } |
|
119 |
|
120 NS_IMETHODIMP |
|
121 nsJSInspector::GetLastNestRequestor(JS::MutableHandle<JS::Value> out) |
|
122 { |
|
123 out.set(mLastRequestor); |
|
124 return NS_OK; |
|
125 } |
|
126 |
|
127 } |
|
128 } |
|
129 |
|
130 NS_DEFINE_NAMED_CID(JSINSPECTOR_CID); |
|
131 |
|
132 static const mozilla::Module::CIDEntry kJSInspectorCIDs[] = { |
|
133 { &kJSINSPECTOR_CID, false, nullptr, mozilla::jsinspector::nsJSInspectorConstructor }, |
|
134 { nullptr } |
|
135 }; |
|
136 |
|
137 static const mozilla::Module::ContractIDEntry kJSInspectorContracts[] = { |
|
138 { JSINSPECTOR_CONTRACTID, &kJSINSPECTOR_CID }, |
|
139 { nullptr } |
|
140 }; |
|
141 |
|
142 static const mozilla::Module kJSInspectorModule = { |
|
143 mozilla::Module::kVersion, |
|
144 kJSInspectorCIDs, |
|
145 kJSInspectorContracts |
|
146 }; |
|
147 |
|
148 NSMODULE_DEFN(jsinspector) = &kJSInspectorModule; |