Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=80:
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #ifndef mozilla_jsipc_JavaScriptLogging__
9 : #define mozilla_jsipc_JavaScriptLogging__
10 :
11 : #include "nsString.h"
12 : #include "nsPrintfCString.h"
13 : #include "jsfriendapi.h"
14 : #include "jswrapper.h"
15 :
16 : namespace mozilla {
17 : namespace jsipc {
18 :
19 : #define LOG(...) \
20 : PR_BEGIN_MACRO \
21 : if (LoggingEnabled()) { \
22 : Logging log(this, cx); \
23 : log.print(__VA_ARGS__); \
24 : } \
25 : PR_END_MACRO
26 :
27 : #define LOG_STACK() \
28 : PR_BEGIN_MACRO \
29 : if (StackLoggingEnabled()) { \
30 : js::DumpBacktrace(cx); \
31 : } \
32 : PR_END_MACRO
33 :
34 : struct ReceiverObj
35 : {
36 : ObjectId id;
37 0 : explicit ReceiverObj(ObjectId id) : id(id) {}
38 : };
39 :
40 0 : struct InVariant
41 : {
42 : JSVariant variant;
43 0 : explicit InVariant(const JSVariant& variant) : variant(variant) {}
44 : };
45 :
46 0 : struct OutVariant
47 : {
48 : JSVariant variant;
49 0 : explicit OutVariant(const JSVariant& variant) : variant(variant) {}
50 : };
51 :
52 0 : struct Identifier
53 : {
54 : JSIDVariant variant;
55 0 : explicit Identifier(const JSIDVariant& variant) : variant(variant) {}
56 : };
57 :
58 : class Logging
59 : {
60 : public:
61 0 : Logging(JavaScriptShared* shared, JSContext* cx) : shared(shared), cx(cx) {}
62 :
63 0 : void print(const nsCString& str) {
64 0 : const char* side = shared->isParent() ? "from child" : "from parent";
65 0 : printf("CPOW %s: %s\n", side, str.get());
66 0 : }
67 :
68 : void print(const char* str) {
69 : print(nsCString(str));
70 : }
71 : template<typename T1>
72 0 : void print(const char* fmt, const T1& a1) {
73 0 : nsAutoCString tmp1;
74 0 : format(a1, tmp1);
75 0 : print(nsPrintfCString(fmt, tmp1.get()));
76 0 : }
77 : template<typename T1, typename T2>
78 0 : void print(const char* fmt, const T1& a1, const T2& a2) {
79 0 : nsAutoCString tmp1;
80 0 : nsAutoCString tmp2;
81 0 : format(a1, tmp1);
82 0 : format(a2, tmp2);
83 0 : print(nsPrintfCString(fmt, tmp1.get(), tmp2.get()));
84 0 : }
85 : template<typename T1, typename T2, typename T3>
86 0 : void print(const char* fmt, const T1& a1, const T2& a2, const T3& a3) {
87 0 : nsAutoCString tmp1;
88 0 : nsAutoCString tmp2;
89 0 : nsAutoCString tmp3;
90 0 : format(a1, tmp1);
91 0 : format(a2, tmp2);
92 0 : format(a3, tmp3);
93 0 : print(nsPrintfCString(fmt, tmp1.get(), tmp2.get(), tmp3.get()));
94 0 : }
95 :
96 0 : void format(const nsString& str, nsCString& out) {
97 0 : out = NS_ConvertUTF16toUTF8(str);
98 0 : }
99 :
100 0 : void formatObject(bool incoming, bool local, ObjectId id, nsCString& out) {
101 : const char* side;
102 : const char* objDesc;
103 : void* ptr;
104 :
105 0 : if (local == incoming) {
106 0 : JS::RootedObject obj(cx);
107 0 : obj = shared->objects_.find(id);
108 0 : if (obj) {
109 0 : JSAutoCompartment ac(cx, obj);
110 0 : objDesc = js::ObjectClassName(cx, obj);
111 : } else {
112 0 : objDesc = "<dead object>";
113 : }
114 :
115 0 : side = shared->isParent() ? "parent" : "child";
116 0 : ptr = js::UncheckedUnwrap(obj, true);
117 : } else {
118 0 : objDesc = "<cpow>";
119 0 : side = shared->isParent() ? "child" : "parent";
120 0 : ptr = nullptr;
121 : }
122 :
123 0 : out = nsPrintfCString("<%s %s:%" PRIu64 ":%p>", side, objDesc, id.serialNumber(), ptr);
124 0 : }
125 :
126 0 : void format(const ReceiverObj& obj, nsCString& out) {
127 0 : formatObject(true, true, obj.id, out);
128 0 : }
129 :
130 0 : void format(const nsTArray<JSParam>& values, nsCString& out) {
131 0 : nsAutoCString tmp;
132 0 : out.Truncate();
133 0 : for (size_t i = 0; i < values.Length(); i++) {
134 0 : if (i)
135 0 : out.AppendLiteral(", ");
136 0 : if (values[i].type() == JSParam::Tvoid_t) {
137 0 : out.AppendLiteral("<void>");
138 : } else {
139 0 : format(InVariant(values[i].get_JSVariant()), tmp);
140 0 : out += tmp;
141 : }
142 : }
143 0 : }
144 :
145 0 : void format(const InVariant& value, nsCString& out) {
146 0 : format(true, value.variant, out);
147 0 : }
148 :
149 0 : void format(const OutVariant& value, nsCString& out) {
150 0 : format(false, value.variant, out);
151 0 : }
152 :
153 0 : void format(bool incoming, const JSVariant& value, nsCString& out) {
154 0 : switch (value.type()) {
155 : case JSVariant::TUndefinedVariant: {
156 0 : out = "undefined";
157 0 : break;
158 : }
159 : case JSVariant::TNullVariant: {
160 0 : out = "null";
161 0 : break;
162 : }
163 : case JSVariant::TnsString: {
164 0 : nsAutoCString tmp;
165 0 : format(value.get_nsString(), tmp);
166 0 : out = nsPrintfCString("\"%s\"", tmp.get());
167 0 : break;
168 : }
169 : case JSVariant::TObjectVariant: {
170 0 : const ObjectVariant& ovar = value.get_ObjectVariant();
171 0 : if (ovar.type() == ObjectVariant::TLocalObject)
172 0 : formatObject(incoming, true, ObjectId::deserialize(ovar.get_LocalObject().serializedId()), out);
173 : else
174 0 : formatObject(incoming, false, ObjectId::deserialize(ovar.get_RemoteObject().serializedId()), out);
175 0 : break;
176 : }
177 : case JSVariant::TSymbolVariant: {
178 0 : out = "<Symbol>";
179 0 : break;
180 : }
181 : case JSVariant::Tdouble: {
182 0 : out = nsPrintfCString("%.0f", value.get_double());
183 0 : break;
184 : }
185 : case JSVariant::Tbool: {
186 0 : out = value.get_bool() ? "true" : "false";
187 0 : break;
188 : }
189 : case JSVariant::TJSIID: {
190 0 : out = "<JSIID>";
191 0 : break;
192 : }
193 : default: {
194 0 : out = "<JSIID>";
195 0 : break;
196 : }
197 : }
198 0 : }
199 :
200 0 : void format(const Identifier& id, nsCString& out) {
201 0 : switch (id.variant.type()) {
202 : case JSIDVariant::TSymbolVariant: {
203 0 : out = "<Symbol>";
204 0 : break;
205 : }
206 : case JSIDVariant::TnsString: {
207 0 : nsAutoCString tmp;
208 0 : format(id.variant.get_nsString(), tmp);
209 0 : out = nsPrintfCString("\"%s\"", tmp.get());
210 0 : break;
211 : }
212 : case JSIDVariant::Tint32_t: {
213 0 : out = nsPrintfCString("%d", id.variant.get_int32_t());
214 0 : break;
215 : }
216 : default: {
217 0 : out = "Unknown";
218 0 : break;
219 : }
220 : }
221 0 : }
222 :
223 : private:
224 : JavaScriptShared* shared;
225 : JSContext* cx;
226 : };
227 :
228 : } // namespace jsipc
229 : } // namespace mozilla
230 :
231 : #endif
|