JavaScriptLogging.h 6.9 KB

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