1 : /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
2 : /* vim: set ts=2 et sw=2 tw=80: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Web Workers.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * The Mozilla Foundation.
20 : * Portions created by the Initial Developer are Copyright (C) 2011
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Ben Turner <bent.mozilla@gmail.com> (Original Author)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "mozilla/Util.h"
41 :
42 : #include "Exceptions.h"
43 :
44 : #include "jsapi.h"
45 : #include "jsfriendapi.h"
46 : #include "jsprf.h"
47 :
48 : #include "nsTraceRefcnt.h"
49 :
50 : #include "WorkerInlines.h"
51 :
52 : #define PROPERTY_FLAGS \
53 : (JSPROP_ENUMERATE | JSPROP_SHARED)
54 :
55 : #define CONSTANT_FLAGS \
56 : JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_PERMANENT | JSPROP_READONLY
57 :
58 : using namespace mozilla;
59 : USING_WORKERS_NAMESPACE
60 :
61 : namespace {
62 :
63 : class DOMException : public PrivatizableBase
64 : {
65 : static JSClass sClass;
66 : static JSPropertySpec sProperties[];
67 : static JSFunctionSpec sFunctions[];
68 : static JSPropertySpec sStaticProperties[];
69 :
70 : enum SLOT {
71 : SLOT_code = 0,
72 : SLOT_name,
73 :
74 : SLOT_COUNT
75 : };
76 :
77 : public:
78 : static JSObject*
79 0 : InitClass(JSContext* aCx, JSObject* aObj)
80 : {
81 : JSObject* proto = JS_InitClass(aCx, aObj, NULL, &sClass, Construct, 0,
82 : sProperties, sFunctions, sStaticProperties,
83 0 : NULL);
84 0 : if (proto && !JS_DefineProperties(aCx, proto, sStaticProperties)) {
85 0 : return NULL;
86 : }
87 :
88 0 : return proto;
89 : }
90 :
91 : static JSObject*
92 : Create(JSContext* aCx, int aCode);
93 :
94 : private:
95 0 : DOMException()
96 0 : {
97 0 : MOZ_COUNT_CTOR(mozilla::dom::workers::exceptions::DOMException);
98 0 : }
99 :
100 0 : ~DOMException()
101 : {
102 0 : MOZ_COUNT_DTOR(mozilla::dom::workers::exceptions::DOMException);
103 0 : }
104 :
105 : static JSBool
106 0 : Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
107 : {
108 : JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
109 0 : sClass.name);
110 0 : return false;
111 : }
112 :
113 : static void
114 0 : Finalize(JSContext* aCx, JSObject* aObj)
115 : {
116 0 : JS_ASSERT(JS_GetClass(aObj) == &sClass);
117 0 : delete GetJSPrivateSafeish<DOMException>(aObj);
118 0 : }
119 :
120 : static JSBool
121 0 : ToString(JSContext* aCx, unsigned aArgc, jsval* aVp)
122 : {
123 0 : JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
124 0 : if (!obj) {
125 0 : return false;
126 : }
127 :
128 0 : JSClass* classPtr = JS_GetClass(obj);
129 0 : if (classPtr != &sClass) {
130 : JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
131 : JSMSG_INCOMPATIBLE_PROTO, sClass.name, "toString",
132 0 : classPtr->name);
133 0 : return false;
134 : }
135 :
136 : char buf[100];
137 0 : JS_snprintf(buf, sizeof(buf), "%s: ", sClass.name);
138 :
139 0 : JSString* classString = JS_NewStringCopyZ(aCx, buf);
140 0 : if (!classString) {
141 0 : return false;
142 : }
143 :
144 0 : jsval name = JS_GetReservedSlot(obj, SLOT_name);
145 0 : JS_ASSERT(JSVAL_IS_STRING(name));
146 :
147 0 : JSString* out = JS_ConcatStrings(aCx, classString, JSVAL_TO_STRING(name));
148 0 : if (!out) {
149 0 : return false;
150 : }
151 :
152 0 : JS_SET_RVAL(aCx, aVp, STRING_TO_JSVAL(out));
153 0 : return true;
154 : }
155 :
156 : static JSBool
157 0 : GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
158 : {
159 0 : JS_ASSERT(JSID_IS_INT(aIdval));
160 :
161 0 : int32 slot = JSID_TO_INT(aIdval);
162 :
163 0 : JSClass* classPtr = JS_GetClass(aObj);
164 :
165 0 : if (classPtr != &sClass || !GetJSPrivateSafeish<DOMException>(aObj)) {
166 : JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
167 : JSMSG_INCOMPATIBLE_PROTO, sClass.name,
168 0 : sProperties[slot].name, classPtr->name);
169 0 : return false;
170 : }
171 :
172 0 : *aVp = JS_GetReservedSlot(aObj, slot);
173 0 : return true;
174 : }
175 :
176 : static JSBool
177 0 : GetConstant(JSContext* aCx, JSObject* aObj, jsid idval, jsval* aVp)
178 : {
179 0 : JS_ASSERT(JSID_IS_INT(idval));
180 0 : *aVp = INT_TO_JSVAL(JSID_TO_INT(idval));
181 0 : return true;
182 : }
183 : };
184 :
185 : JSClass DOMException::sClass = {
186 : "DOMException",
187 : JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
188 : JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
189 : JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
190 : JSCLASS_NO_OPTIONAL_MEMBERS
191 : };
192 :
193 : JSPropertySpec DOMException::sProperties[] = {
194 : { "code", SLOT_code, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
195 : { "name", SLOT_name, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
196 : { 0, 0, 0, NULL, NULL }
197 : };
198 :
199 : JSFunctionSpec DOMException::sFunctions[] = {
200 : JS_FN("toString", ToString, 0, 0),
201 : JS_FS_END
202 : };
203 :
204 : JSPropertySpec DOMException::sStaticProperties[] = {
205 :
206 : #define EXCEPTION_ENTRY(_name) \
207 : { #_name, _name, CONSTANT_FLAGS, GetConstant, NULL },
208 :
209 : // Make sure this one is always first.
210 : EXCEPTION_ENTRY(UNKNOWN_ERR)
211 :
212 : EXCEPTION_ENTRY(INDEX_SIZE_ERR)
213 : EXCEPTION_ENTRY(DOMSTRING_SIZE_ERR)
214 : EXCEPTION_ENTRY(HIERARCHY_REQUEST_ERR)
215 : EXCEPTION_ENTRY(WRONG_DOCUMENT_ERR)
216 : EXCEPTION_ENTRY(INVALID_CHARACTER_ERR)
217 : EXCEPTION_ENTRY(NO_DATA_ALLOWED_ERR)
218 : EXCEPTION_ENTRY(NO_MODIFICATION_ALLOWED_ERR)
219 : EXCEPTION_ENTRY(NOT_FOUND_ERR)
220 : EXCEPTION_ENTRY(NOT_SUPPORTED_ERR)
221 : EXCEPTION_ENTRY(INUSE_ATTRIBUTE_ERR)
222 : EXCEPTION_ENTRY(INVALID_STATE_ERR)
223 : EXCEPTION_ENTRY(SYNTAX_ERR)
224 : EXCEPTION_ENTRY(INVALID_MODIFICATION_ERR)
225 : EXCEPTION_ENTRY(NAMESPACE_ERR)
226 : EXCEPTION_ENTRY(INVALID_ACCESS_ERR)
227 : EXCEPTION_ENTRY(VALIDATION_ERR)
228 : EXCEPTION_ENTRY(TYPE_MISMATCH_ERR)
229 : EXCEPTION_ENTRY(SECURITY_ERR)
230 : EXCEPTION_ENTRY(NETWORK_ERR)
231 : EXCEPTION_ENTRY(ABORT_ERR)
232 : EXCEPTION_ENTRY(URL_MISMATCH_ERR)
233 : EXCEPTION_ENTRY(QUOTA_EXCEEDED_ERR)
234 : EXCEPTION_ENTRY(TIMEOUT_ERR)
235 : EXCEPTION_ENTRY(INVALID_NODE_TYPE_ERR)
236 : EXCEPTION_ENTRY(DATA_CLONE_ERR)
237 :
238 : #undef EXCEPTION_ENTRY
239 :
240 : { 0, 0, 0, NULL, NULL }
241 : };
242 :
243 : // static
244 : JSObject*
245 0 : DOMException::Create(JSContext* aCx, int aCode)
246 : {
247 0 : JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
248 0 : if (!obj) {
249 0 : return NULL;
250 : }
251 :
252 0 : size_t foundIndex = size_t(-1);
253 0 : for (size_t index = 0; index < ArrayLength(sStaticProperties) - 1; index++) {
254 0 : if (sStaticProperties[index].tinyid == aCode) {
255 0 : foundIndex = index;
256 0 : break;
257 : }
258 : }
259 :
260 0 : if (foundIndex == size_t(-1)) {
261 0 : foundIndex = 0;
262 : }
263 :
264 0 : JSString* name = JS_NewStringCopyZ(aCx, sStaticProperties[foundIndex].name);
265 0 : if (!name) {
266 0 : return NULL;
267 : }
268 :
269 0 : JS_SetReservedSlot(obj, SLOT_code, INT_TO_JSVAL(aCode));
270 0 : JS_SetReservedSlot(obj, SLOT_name, STRING_TO_JSVAL(name));
271 :
272 0 : DOMException* priv = new DOMException();
273 0 : SetJSPrivateSafeish(obj, priv);
274 :
275 0 : return obj;
276 : }
277 :
278 : class FileException : public PrivatizableBase
279 : {
280 : static JSClass sClass;
281 : static JSPropertySpec sProperties[];
282 : static JSPropertySpec sStaticProperties[];
283 :
284 : enum SLOT {
285 : SLOT_code = 0,
286 : SLOT_name,
287 :
288 : SLOT_COUNT
289 : };
290 :
291 : public:
292 : static JSObject*
293 0 : InitClass(JSContext* aCx, JSObject* aObj)
294 : {
295 : return JS_InitClass(aCx, aObj, NULL, &sClass, Construct, 0, sProperties,
296 0 : NULL, sStaticProperties, NULL);
297 : }
298 :
299 : static JSObject*
300 : Create(JSContext* aCx, int aCode);
301 :
302 : private:
303 0 : FileException()
304 0 : {
305 0 : MOZ_COUNT_CTOR(mozilla::dom::workers::exceptions::FileException);
306 0 : }
307 :
308 0 : ~FileException()
309 : {
310 0 : MOZ_COUNT_DTOR(mozilla::dom::workers::exceptions::FileException);
311 0 : }
312 :
313 : static JSBool
314 0 : Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
315 : {
316 : JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
317 0 : sClass.name);
318 0 : return false;
319 : }
320 :
321 : static void
322 0 : Finalize(JSContext* aCx, JSObject* aObj)
323 : {
324 0 : JS_ASSERT(JS_GetClass(aObj) == &sClass);
325 0 : delete GetJSPrivateSafeish<FileException>(aObj);
326 0 : }
327 :
328 : static JSBool
329 0 : GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
330 : {
331 0 : JS_ASSERT(JSID_IS_INT(aIdval));
332 :
333 0 : int32 slot = JSID_TO_INT(aIdval);
334 :
335 0 : JSClass* classPtr = JS_GetClass(aObj);
336 :
337 0 : if (classPtr != &sClass || !GetJSPrivateSafeish<FileException>(aObj)) {
338 : JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
339 : JSMSG_INCOMPATIBLE_PROTO, sClass.name,
340 0 : sProperties[slot].name, classPtr->name);
341 0 : return false;
342 : }
343 :
344 0 : *aVp = JS_GetReservedSlot(aObj, slot);
345 0 : return true;
346 : }
347 :
348 : static JSBool
349 0 : GetConstant(JSContext* aCx, JSObject* aObj, jsid idval, jsval* aVp)
350 : {
351 0 : JS_ASSERT(JSID_IS_INT(idval));
352 0 : *aVp = INT_TO_JSVAL(JSID_TO_INT(idval));
353 0 : return true;
354 : }
355 : };
356 :
357 : JSClass FileException::sClass = {
358 : "FileException",
359 : JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
360 : JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
361 : JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
362 : JSCLASS_NO_OPTIONAL_MEMBERS
363 : };
364 :
365 : JSPropertySpec FileException::sProperties[] = {
366 : { "code", SLOT_code, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
367 : { "name", SLOT_name, PROPERTY_FLAGS, GetProperty, js_GetterOnlyPropertyStub },
368 : { 0, 0, 0, NULL, NULL }
369 : };
370 :
371 : JSPropertySpec FileException::sStaticProperties[] = {
372 :
373 : #define EXCEPTION_ENTRY(_name) \
374 : { #_name, FILE_##_name, CONSTANT_FLAGS, GetConstant, NULL },
375 :
376 : EXCEPTION_ENTRY(NOT_FOUND_ERR)
377 : EXCEPTION_ENTRY(SECURITY_ERR)
378 : EXCEPTION_ENTRY(ABORT_ERR)
379 : EXCEPTION_ENTRY(NOT_READABLE_ERR)
380 : EXCEPTION_ENTRY(ENCODING_ERR)
381 :
382 : #undef EXCEPTION_ENTRY
383 :
384 : { 0, 0, 0, NULL, NULL }
385 : };
386 :
387 : // static
388 : JSObject*
389 0 : FileException::Create(JSContext* aCx, int aCode)
390 : {
391 0 : JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
392 0 : if (!obj) {
393 0 : return NULL;
394 : }
395 :
396 0 : size_t foundIndex = size_t(-1);
397 0 : for (size_t index = 0; index < ArrayLength(sStaticProperties) - 1; index++) {
398 0 : if (sStaticProperties[index].tinyid == aCode) {
399 0 : foundIndex = index;
400 0 : break;
401 : }
402 : }
403 :
404 0 : JS_ASSERT(foundIndex != size_t(-1));
405 :
406 0 : JSString* name = JS_NewStringCopyZ(aCx, sStaticProperties[foundIndex].name);
407 0 : if (!name) {
408 0 : return NULL;
409 : }
410 :
411 0 : JS_SetReservedSlot(obj, SLOT_code, INT_TO_JSVAL(aCode));
412 0 : JS_SetReservedSlot(obj, SLOT_name, STRING_TO_JSVAL(name));
413 :
414 0 : FileException* priv = new FileException();
415 0 : SetJSPrivateSafeish(obj, priv);
416 :
417 0 : return obj;
418 : }
419 :
420 : } // anonymous namespace
421 :
422 : BEGIN_WORKERS_NAMESPACE
423 :
424 : namespace exceptions {
425 :
426 : bool
427 0 : InitClasses(JSContext* aCx, JSObject* aGlobal)
428 : {
429 0 : return DOMException::InitClass(aCx, aGlobal) &&
430 0 : FileException::InitClass(aCx, aGlobal);
431 : }
432 :
433 : void
434 0 : ThrowDOMExceptionForCode(JSContext* aCx, int aCode)
435 : {
436 0 : JSObject* exception = DOMException::Create(aCx, aCode);
437 0 : JS_ASSERT(exception);
438 :
439 0 : JS_SetPendingException(aCx, OBJECT_TO_JSVAL(exception));
440 0 : }
441 :
442 : void
443 0 : ThrowFileExceptionForCode(JSContext* aCx, int aCode)
444 : {
445 0 : JSObject* exception = FileException::Create(aCx, aCode);
446 0 : JS_ASSERT(exception);
447 :
448 0 : JS_SetPendingException(aCx, OBJECT_TO_JSVAL(exception));
449 0 : }
450 :
451 : } // namespace exceptions
452 :
453 : END_WORKERS_NAMESPACE
|