js/xpconnect/src/XPCDebug.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "xpcprivate.h"
michael@0 8 #include "jsprf.h"
michael@0 9 #include "js/OldDebugAPI.h"
michael@0 10
michael@0 11 #ifdef XP_WIN
michael@0 12 #include <windows.h>
michael@0 13 #endif
michael@0 14
michael@0 15 static void DebugDump(const char* fmt, ...)
michael@0 16 {
michael@0 17 char buffer[2048];
michael@0 18 va_list ap;
michael@0 19 va_start(ap, fmt);
michael@0 20 #ifdef XPWIN
michael@0 21 _vsnprintf(buffer, sizeof(buffer), fmt, ap);
michael@0 22 #else
michael@0 23 vsnprintf(buffer, sizeof(buffer), fmt, ap);
michael@0 24 #endif
michael@0 25 buffer[sizeof(buffer)-1] = '\0';
michael@0 26 va_end(ap);
michael@0 27 #ifdef XP_WIN
michael@0 28 if (IsDebuggerPresent()) {
michael@0 29 OutputDebugStringA(buffer);
michael@0 30 }
michael@0 31 #endif
michael@0 32 printf("%s", buffer);
michael@0 33 }
michael@0 34
michael@0 35 bool
michael@0 36 xpc_DumpJSStack(JSContext* cx, bool showArgs, bool showLocals, bool showThisProps)
michael@0 37 {
michael@0 38 if (char* buf = xpc_PrintJSStack(cx, showArgs, showLocals, showThisProps)) {
michael@0 39 DebugDump("%s\n", buf);
michael@0 40 JS_smprintf_free(buf);
michael@0 41 }
michael@0 42 return true;
michael@0 43 }
michael@0 44
michael@0 45 char*
michael@0 46 xpc_PrintJSStack(JSContext* cx, bool showArgs, bool showLocals,
michael@0 47 bool showThisProps)
michael@0 48 {
michael@0 49 JS::AutoSaveExceptionState state(cx);
michael@0 50
michael@0 51 char *buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, showThisProps);
michael@0 52 if (!buf)
michael@0 53 DebugDump("%s", "Failed to format JavaScript stack for dump\n");
michael@0 54
michael@0 55 state.restore();
michael@0 56 return buf;
michael@0 57 }
michael@0 58
michael@0 59 /***************************************************************************/
michael@0 60
michael@0 61 static void
michael@0 62 xpcDumpEvalErrorReporter(JSContext *cx, const char *message,
michael@0 63 JSErrorReport *report)
michael@0 64 {
michael@0 65 DebugDump("Error: %s\n", message);
michael@0 66 }
michael@0 67
michael@0 68 bool
michael@0 69 xpc_DumpEvalInJSStackFrame(JSContext* cx, uint32_t frameno, const char* text)
michael@0 70 {
michael@0 71 if (!cx || !text) {
michael@0 72 DebugDump("%s", "invalid params passed to xpc_DumpEvalInJSStackFrame!\n");
michael@0 73 return false;
michael@0 74 }
michael@0 75
michael@0 76 DebugDump("js[%d]> %s\n", frameno, text);
michael@0 77
michael@0 78 uint32_t num = 0;
michael@0 79
michael@0 80 JSAbstractFramePtr frame = JSNullFramePtr();
michael@0 81
michael@0 82 JSBrokenFrameIterator iter(cx);
michael@0 83 while (!iter.done()) {
michael@0 84 if (num == frameno) {
michael@0 85 frame = iter.abstractFramePtr();
michael@0 86 break;
michael@0 87 }
michael@0 88 ++iter;
michael@0 89 num++;
michael@0 90 }
michael@0 91
michael@0 92 if (!frame) {
michael@0 93 DebugDump("%s", "invalid frame number!\n");
michael@0 94 return false;
michael@0 95 }
michael@0 96
michael@0 97 JS::AutoSaveExceptionState exceptionState(cx);
michael@0 98 JSErrorReporter older = JS_SetErrorReporter(cx, xpcDumpEvalErrorReporter);
michael@0 99
michael@0 100 JS::RootedValue rval(cx);
michael@0 101 JSString* str;
michael@0 102 JSAutoByteString bytes;
michael@0 103 if (frame.evaluateInStackFrame(cx, text, strlen(text), "eval", 1, &rval) &&
michael@0 104 nullptr != (str = ToString(cx, rval)) &&
michael@0 105 bytes.encodeLatin1(cx, str)) {
michael@0 106 DebugDump("%s\n", bytes.ptr());
michael@0 107 } else {
michael@0 108 DebugDump("%s", "eval failed!\n");
michael@0 109 }
michael@0 110
michael@0 111 JS_SetErrorReporter(cx, older);
michael@0 112 exceptionState.restore();
michael@0 113 return true;
michael@0 114 }
michael@0 115
michael@0 116 /***************************************************************************/
michael@0 117
michael@0 118 JSTrapStatus
michael@0 119 xpc_DebuggerKeywordHandler(JSContext *cx, JSScript *script, jsbytecode *pc,
michael@0 120 jsval *rval, void *closure)
michael@0 121 {
michael@0 122 static const char line[] =
michael@0 123 "------------------------------------------------------------------------\n";
michael@0 124 DebugDump("%s", line);
michael@0 125 DebugDump("%s", "Hit JavaScript \"debugger\" keyword. JS call stack...\n");
michael@0 126 xpc_DumpJSStack(cx, true, true, false);
michael@0 127 DebugDump("%s", line);
michael@0 128 return JSTRAP_CONTINUE;
michael@0 129 }
michael@0 130
michael@0 131 bool xpc_InstallJSDebuggerKeywordHandler(JSRuntime* rt)
michael@0 132 {
michael@0 133 return JS_SetDebuggerHandler(rt, xpc_DebuggerKeywordHandler, nullptr);
michael@0 134 }

mercurial