js/xpconnect/src/XPCThrower.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:ce4ff9c2f8da
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
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
7 /* Code for throwing errors into JavaScript. */
8
9 #include "xpcprivate.h"
10 #include "XPCWrapper.h"
11 #include "jsprf.h"
12 #include "mozilla/dom/BindingUtils.h"
13 #include "mozilla/dom/Exceptions.h"
14
15 using namespace mozilla;
16 using namespace mozilla::dom;
17
18 bool XPCThrower::sVerbose = true;
19
20 // static
21 void
22 XPCThrower::Throw(nsresult rv, JSContext* cx)
23 {
24 const char* format;
25 if (JS_IsExceptionPending(cx))
26 return;
27 if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
28 format = "";
29 dom::Throw(cx, rv, format);
30 }
31
32 namespace xpc {
33
34 bool
35 Throw(JSContext *cx, nsresult rv)
36 {
37 XPCThrower::Throw(rv, cx);
38 return false;
39 }
40
41 } // namespace xpc
42
43 /*
44 * If there has already been an exception thrown, see if we're throwing the
45 * same sort of exception, and if we are, don't clobber the old one. ccx
46 * should be the current call context.
47 */
48 // static
49 bool
50 XPCThrower::CheckForPendingException(nsresult result, JSContext *cx)
51 {
52 nsCOMPtr<nsIException> e = XPCJSRuntime::Get()->GetPendingException();
53 if (!e)
54 return false;
55 XPCJSRuntime::Get()->SetPendingException(nullptr);
56
57 nsresult e_result;
58 if (NS_FAILED(e->GetResult(&e_result)) || e_result != result)
59 return false;
60
61 if (!ThrowExceptionObject(cx, e))
62 JS_ReportOutOfMemory(cx);
63 return true;
64 }
65
66 // static
67 void
68 XPCThrower::Throw(nsresult rv, XPCCallContext& ccx)
69 {
70 char* sz;
71 const char* format;
72
73 if (CheckForPendingException(rv, ccx))
74 return;
75
76 if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
77 format = "";
78
79 sz = (char*) format;
80
81 if (sz && sVerbose)
82 Verbosify(ccx, &sz, false);
83
84 dom::Throw(ccx, rv, sz);
85
86 if (sz && sz != format)
87 JS_smprintf_free(sz);
88 }
89
90
91 // static
92 void
93 XPCThrower::ThrowBadResult(nsresult rv, nsresult result, XPCCallContext& ccx)
94 {
95 char* sz;
96 const char* format;
97 const char* name;
98
99 /*
100 * If there is a pending exception when the native call returns and
101 * it has the same error result as returned by the native call, then
102 * the native call may be passing through an error from a previous JS
103 * call. So we'll just throw that exception into our JS.
104 */
105
106 if (CheckForPendingException(result, ccx))
107 return;
108
109 // else...
110
111 if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format) || !format)
112 format = "";
113
114 if (nsXPCException::NameAndFormatForNSResult(result, &name, nullptr) && name)
115 sz = JS_smprintf("%s 0x%x (%s)", format, result, name);
116 else
117 sz = JS_smprintf("%s 0x%x", format, result);
118
119 if (sz && sVerbose)
120 Verbosify(ccx, &sz, true);
121
122 dom::Throw(ccx, result, sz);
123
124 if (sz)
125 JS_smprintf_free(sz);
126 }
127
128 // static
129 void
130 XPCThrower::ThrowBadParam(nsresult rv, unsigned paramNum, XPCCallContext& ccx)
131 {
132 char* sz;
133 const char* format;
134
135 if (!nsXPCException::NameAndFormatForNSResult(rv, nullptr, &format))
136 format = "";
137
138 sz = JS_smprintf("%s arg %d", format, paramNum);
139
140 if (sz && sVerbose)
141 Verbosify(ccx, &sz, true);
142
143 dom::Throw(ccx, rv, sz);
144
145 if (sz)
146 JS_smprintf_free(sz);
147 }
148
149
150 // static
151 void
152 XPCThrower::Verbosify(XPCCallContext& ccx,
153 char** psz, bool own)
154 {
155 char* sz = nullptr;
156
157 if (ccx.HasInterfaceAndMember()) {
158 XPCNativeInterface* iface = ccx.GetInterface();
159 jsid id = ccx.GetMember()->GetName();
160 JSAutoByteString bytes;
161 const char *name = JSID_IS_VOID(id) ? "Unknown" : bytes.encodeLatin1(ccx, JSID_TO_STRING(id));
162 if (!name) {
163 name = "";
164 }
165 sz = JS_smprintf("%s [%s.%s]", *psz, iface->GetNameString(), name);
166 }
167
168 if (sz) {
169 if (own)
170 JS_smprintf_free(*psz);
171 *psz = sz;
172 }
173 }

mercurial