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 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is mozilla.org code.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * The Mozilla Foundation.
21 : * Portions created by the Initial Developer are Copyright (C) 2010
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * Ben Newman <b{enjam,newma}n@mozilla.com> (original author)
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #include "mozilla/jsipc/ObjectWrapperParent.h"
42 : #include "mozilla/jsipc/ContextWrapperParent.h"
43 : #include "mozilla/jsipc/CPOWTypes.h"
44 : #include "mozilla/unused.h"
45 : #include "nsJSUtils.h"
46 :
47 : #include "jsutil.h"
48 : #include "jsfriendapi.h"
49 :
50 : using namespace mozilla::jsipc;
51 :
52 : namespace {
53 :
54 : // Only need one reserved slot because the ObjectWrapperParent* is
55 : // stored in the private slot.
56 : static const unsigned sFlagsSlot = 0;
57 : static const unsigned sNumSlots = 1;
58 : static const unsigned CPOW_FLAG_RESOLVING = 1 << 0;
59 :
60 : class AutoResolveFlag
61 : {
62 : JSObject* mObj;
63 : unsigned mOldFlags;
64 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
65 :
66 0 : static unsigned GetFlags(JSObject* obj) {
67 0 : jsval v = JS_GetReservedSlot(obj, sFlagsSlot);
68 0 : return JSVAL_TO_INT(v);
69 : }
70 :
71 0 : static unsigned SetFlags(JSObject* obj, unsigned flags) {
72 0 : unsigned oldFlags = GetFlags(obj);
73 0 : if (oldFlags != flags)
74 0 : JS_SetReservedSlot(obj, sFlagsSlot, INT_TO_JSVAL(flags));
75 0 : return oldFlags;
76 : }
77 :
78 : public:
79 :
80 0 : AutoResolveFlag(JSObject* obj
81 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
82 : : mObj(obj)
83 0 : , mOldFlags(SetFlags(obj, GetFlags(obj) | CPOW_FLAG_RESOLVING))
84 : {
85 0 : JS_GUARD_OBJECT_NOTIFIER_INIT;
86 0 : }
87 :
88 0 : ~AutoResolveFlag() {
89 0 : SetFlags(mObj, mOldFlags);
90 0 : }
91 :
92 0 : static JSBool IsSet(JSObject* obj) {
93 0 : return GetFlags(obj) & CPOW_FLAG_RESOLVING;
94 : }
95 :
96 : };
97 :
98 : class StatusMemberOwner
99 0 : {
100 : OperationStatus mStatus;
101 : public:
102 0 : StatusMemberOwner() : mStatus(JS_FALSE) {}
103 0 : OperationStatus* StatusPtr() {
104 0 : return &mStatus;
105 : }
106 : };
107 :
108 : typedef AutoCheckOperationBase<StatusMemberOwner> ACOBase;
109 :
110 : class AutoCheckOperation : public ACOBase
111 0 : {
112 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
113 : public:
114 0 : AutoCheckOperation(JSContext* cx,
115 : ObjectWrapperParent* owp
116 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
117 0 : : ACOBase(cx, owp)
118 : {
119 0 : JS_GUARD_OBJECT_NOTIFIER_INIT;
120 0 : }
121 : };
122 :
123 : }
124 :
125 : void
126 0 : ObjectWrapperParent::CheckOperation(JSContext* cx,
127 : OperationStatus* status)
128 : {
129 0 : NS_PRECONDITION(status->type() != OperationStatus::T__None,
130 : "Checking an uninitialized operation.");
131 :
132 0 : switch (status->type()) {
133 : case OperationStatus::TJSVariant:
134 : {
135 : jsval thrown;
136 0 : if (jsval_from_JSVariant(cx, status->get_JSVariant(), &thrown))
137 0 : JS_SetPendingException(cx, thrown);
138 0 : *status = JS_FALSE;
139 : }
140 0 : break;
141 : case OperationStatus::TJSBool:
142 0 : if (!status->get_JSBool() && !JS_IsExceptionPending(cx)) {
143 0 : NS_WARNING("CPOW operation failed without setting an exception.");
144 : }
145 0 : break;
146 : default:
147 0 : NS_NOTREACHED("Invalid or uninitialized OperationStatus type.");
148 0 : break;
149 : }
150 0 : }
151 :
152 : template <typename RType>
153 : static RType
154 0 : with_error(JSContext* cx,
155 : RType rval,
156 : const char* error = NULL)
157 : {
158 0 : if (!JS_IsExceptionPending(cx))
159 0 : JS_ReportError(cx, error ? error : "Unspecified CPOW error");
160 0 : return rval;
161 : }
162 :
163 : const js::Class ObjectWrapperParent::sCPOW_JSClass = {
164 : "CrossProcessObjectWrapper",
165 : JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE |
166 : JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(sNumSlots),
167 : ObjectWrapperParent::CPOW_AddProperty,
168 : ObjectWrapperParent::CPOW_DelProperty,
169 : ObjectWrapperParent::CPOW_GetProperty,
170 : ObjectWrapperParent::CPOW_SetProperty,
171 : (JSEnumerateOp) ObjectWrapperParent::CPOW_NewEnumerate,
172 : (JSResolveOp) ObjectWrapperParent::CPOW_NewResolve,
173 : ObjectWrapperParent::CPOW_Convert,
174 : ObjectWrapperParent::CPOW_Finalize,
175 : nsnull, // checkAccess
176 : ObjectWrapperParent::CPOW_Call,
177 : ObjectWrapperParent::CPOW_Construct,
178 : ObjectWrapperParent::CPOW_HasInstance,
179 : nsnull, // trace
180 : {
181 : ObjectWrapperParent::CPOW_Equality,
182 : nsnull, // outerObject
183 : nsnull, // innerObject
184 : nsnull, // iteratorObject
185 : nsnull, // wrappedObject
186 : }
187 : };
188 :
189 : void
190 0 : ObjectWrapperParent::ActorDestroy(ActorDestroyReason)
191 : {
192 0 : if (mObj) {
193 0 : JS_SetPrivate(mObj, NULL);
194 0 : mObj = NULL;
195 : }
196 0 : }
197 :
198 : ContextWrapperParent*
199 0 : ObjectWrapperParent::Manager()
200 : {
201 0 : PContextWrapperParent* pcwp = PObjectWrapperParent::Manager();
202 0 : return static_cast<ContextWrapperParent*>(pcwp);
203 : }
204 :
205 : JSObject*
206 0 : ObjectWrapperParent::GetJSObject(JSContext* cx) const
207 : {
208 0 : if (!mObj) {
209 0 : js::Class *clasp = const_cast<js::Class *>(&ObjectWrapperParent::sCPOW_JSClass);
210 0 : mObj = JS_NewObject(cx, js::Jsvalify(clasp), NULL, NULL);
211 0 : if (mObj) {
212 0 : JS_SetPrivate(mObj, (void*)this);
213 0 : JS_SetReservedSlot(mObj, sFlagsSlot, JSVAL_ZERO);
214 : }
215 : }
216 0 : return mObj;
217 : }
218 :
219 : static ObjectWrapperParent*
220 0 : Unwrap(JSObject* obj)
221 : {
222 0 : while (js::GetObjectClass(obj) != &ObjectWrapperParent::sCPOW_JSClass)
223 0 : if (!(obj = js::GetObjectProto(obj)))
224 0 : return NULL;
225 :
226 : ObjectWrapperParent* self =
227 0 : static_cast<ObjectWrapperParent*>(JS_GetPrivate(obj));
228 :
229 0 : NS_ASSERTION(!self || self->GetJSObjectOrNull() == obj,
230 : "Wrapper and wrapped object disagree?");
231 :
232 0 : return self;
233 : }
234 :
235 : /*static*/ bool
236 0 : ObjectWrapperParent::jsval_to_JSVariant(JSContext* cx, jsval from,
237 : JSVariant* to)
238 : {
239 0 : switch (JS_TypeOfValue(cx, from)) {
240 : case JSTYPE_VOID:
241 0 : *to = void_t();
242 0 : return true;
243 : case JSTYPE_NULL:
244 0 : if (from != JSVAL_NULL)
245 0 : return false;
246 : // fall through
247 : case JSTYPE_FUNCTION:
248 : // CPOWs can fool JS_TypeOfValue into returning JSTYPE_FUNCTION
249 : // because they have a call hook, but CPOWs are really objects, so
250 : // fall through to the JSTYPE_OBJECT case:
251 : case JSTYPE_OBJECT:
252 : {
253 : PObjectWrapperParent* powp;
254 0 : if (!JSObject_to_PObjectWrapperParent(JSVAL_TO_OBJECT(from), &powp))
255 0 : return with_error(cx, false, "Cannot pass parent-created object to child");
256 0 : *to = powp;
257 : }
258 0 : return true;
259 : case JSTYPE_STRING:
260 : {
261 0 : nsDependentJSString depStr;
262 0 : if (!depStr.init(cx, from))
263 0 : return false;
264 0 : *to = depStr;
265 : }
266 0 : return true;
267 : case JSTYPE_NUMBER:
268 0 : if (JSVAL_IS_INT(from))
269 0 : *to = JSVAL_TO_INT(from);
270 0 : else if (JSVAL_IS_DOUBLE(from))
271 0 : *to = JSVAL_TO_DOUBLE(from);
272 0 : else return false;
273 0 : return true;
274 : case JSTYPE_BOOLEAN:
275 0 : *to = !!JSVAL_TO_BOOLEAN(from);
276 0 : return true;
277 : case JSTYPE_XML:
278 0 : return with_error(cx, false, "CPOWs currently cannot handle JSTYPE_XML");
279 : default:
280 0 : return with_error(cx, false, "Bad jsval type");
281 : }
282 : }
283 :
284 : /*static*/ bool
285 0 : ObjectWrapperParent::jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
286 : jsval* to)
287 : {
288 0 : switch (from.type()) {
289 : case JSVariant::Tvoid_t:
290 0 : *to = JSVAL_VOID;
291 0 : return true;
292 : case JSVariant::TPObjectWrapperParent:
293 0 : return jsval_from_PObjectWrapperParent(cx, from.get_PObjectWrapperParent(), to);
294 : case JSVariant::TnsString:
295 : {
296 0 : JSString* str = JS_NewUCStringCopyZ(cx, from.get_nsString().BeginReading());
297 0 : if (!str)
298 0 : return false;
299 0 : *to = STRING_TO_JSVAL(str);
300 0 : return true;
301 : }
302 : case JSVariant::Tint:
303 0 : *to = INT_TO_JSVAL(from.get_int());
304 0 : return true;
305 : case JSVariant::Tdouble:
306 0 : return !!JS_NewNumberValue(cx, from.get_double(), to);
307 : case JSVariant::Tbool:
308 0 : *to = BOOLEAN_TO_JSVAL(from.get_bool());
309 0 : return true;
310 : default:
311 0 : return false;
312 : }
313 : }
314 :
315 : /*static*/ bool
316 0 : ObjectWrapperParent::
317 : JSObject_to_PObjectWrapperParent(JSObject* from, PObjectWrapperParent** to)
318 : {
319 0 : if (!from) {
320 0 : *to = NULL;
321 0 : return true;
322 : }
323 0 : ObjectWrapperParent* owp = Unwrap(from);
324 0 : if (!owp)
325 0 : return false;
326 0 : *to = owp;
327 0 : return true;
328 : }
329 :
330 : /*static*/ bool
331 0 : ObjectWrapperParent::
332 : JSObject_from_PObjectWrapperParent(JSContext* cx,
333 : const PObjectWrapperParent* from,
334 : JSObject** to)
335 : {
336 : const ObjectWrapperParent* owp =
337 0 : static_cast<const ObjectWrapperParent*>(from);
338 : *to = owp
339 : ? owp->GetJSObject(cx)
340 0 : : JSVAL_TO_OBJECT(JSVAL_NULL);
341 0 : return true;
342 : }
343 :
344 : /*static*/ bool
345 0 : ObjectWrapperParent::
346 : jsval_from_PObjectWrapperParent(JSContext* cx,
347 : const PObjectWrapperParent* from,
348 : jsval* to)
349 : {
350 : JSObject* obj;
351 0 : if (!JSObject_from_PObjectWrapperParent(cx, from, &obj))
352 0 : return false;
353 0 : *to = OBJECT_TO_JSVAL(obj);
354 0 : return true;
355 : }
356 :
357 : static bool
358 0 : jsid_from_int(JSContext* cx, int from, jsid* to)
359 : {
360 0 : jsval v = INT_TO_JSVAL(from);
361 0 : return JS_ValueToId(cx, v, to);
362 : }
363 :
364 : static bool
365 0 : jsid_from_nsString(JSContext* cx, const nsString& from, jsid* to)
366 : {
367 0 : JSString* str = JS_NewUCStringCopyZ(cx, from.BeginReading());
368 0 : if (!str)
369 0 : return false;
370 0 : return JS_ValueToId(cx, STRING_TO_JSVAL(str), to);
371 : }
372 :
373 : static bool
374 0 : jsval_to_nsString(JSContext* cx, jsid from, nsString* to)
375 : {
376 : JSString* str;
377 : const jschar* chars;
378 : jsval idval;
379 0 : if (JS_IdToValue(cx, from, &idval) &&
380 : (str = JS_ValueToString(cx, idval)) &&
381 : (chars = JS_GetStringCharsZ(cx, str))) {
382 0 : *to = chars;
383 0 : return true;
384 : }
385 0 : return false;
386 : }
387 :
388 : /*static*/ JSBool
389 0 : ObjectWrapperParent::CPOW_AddProperty(JSContext *cx, JSObject *obj, jsid id,
390 : jsval *vp)
391 : {
392 : CPOW_LOG(("Calling CPOW_AddProperty (%s)...",
393 : JSVAL_TO_CSTR(cx, id)));
394 :
395 0 : ObjectWrapperParent* self = Unwrap(obj);
396 0 : if (!self)
397 0 : return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_AddProperty");
398 :
399 0 : if (AutoResolveFlag::IsSet(obj))
400 0 : return JS_TRUE;
401 :
402 0 : AutoCheckOperation aco(cx, self);
403 :
404 0 : nsString in_id;
405 :
406 0 : if (!jsval_to_nsString(cx, id, &in_id))
407 0 : return JS_FALSE;
408 :
409 0 : return (self->Manager()->RequestRunToCompletion() &&
410 : self->CallAddProperty(in_id,
411 0 : aco.StatusPtr()) &&
412 0 : aco.Ok());
413 : }
414 :
415 : /*static*/ JSBool
416 0 : ObjectWrapperParent::CPOW_GetProperty(JSContext *cx, JSObject *obj, jsid id,
417 : jsval *vp)
418 : {
419 : CPOW_LOG(("Calling CPOW_GetProperty (%s)...",
420 : JSVAL_TO_CSTR(cx, id)));
421 :
422 0 : ObjectWrapperParent* self = Unwrap(obj);
423 0 : if (!self)
424 0 : return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_GetProperty");
425 :
426 0 : AutoCheckOperation aco(cx, self);
427 :
428 0 : nsString in_id;
429 :
430 0 : if (!jsval_to_nsString(cx, id, &in_id))
431 0 : return JS_FALSE;
432 :
433 0 : JSVariant out_v;
434 :
435 0 : return (self->Manager()->RequestRunToCompletion() &&
436 : self->CallGetProperty(in_id,
437 0 : aco.StatusPtr(), &out_v) &&
438 0 : aco.Ok() &&
439 0 : self->jsval_from_JSVariant(cx, out_v, vp));
440 : }
441 :
442 : /*static*/ JSBool
443 0 : ObjectWrapperParent::CPOW_SetProperty(JSContext *cx, JSObject *obj, jsid id,
444 : JSBool strict, jsval *vp)
445 : {
446 : CPOW_LOG(("Calling CPOW_SetProperty (%s)...",
447 : JSVAL_TO_CSTR(cx, id)));
448 :
449 0 : ObjectWrapperParent* self = Unwrap(obj);
450 0 : if (!self)
451 0 : return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_SetProperty");
452 :
453 0 : AutoCheckOperation aco(cx, self);
454 :
455 0 : nsString in_id;
456 0 : JSVariant in_v;
457 :
458 0 : if (!jsval_to_nsString(cx, id, &in_id) ||
459 0 : !self->jsval_to_JSVariant(cx, *vp, &in_v))
460 0 : return JS_FALSE;
461 :
462 0 : JSVariant out_v;
463 :
464 0 : return (self->Manager()->RequestRunToCompletion() &&
465 : self->CallSetProperty(in_id, in_v,
466 0 : aco.StatusPtr(), &out_v) &&
467 0 : aco.Ok() &&
468 0 : self->jsval_from_JSVariant(cx, out_v, vp));
469 : }
470 :
471 : /*static*/ JSBool
472 0 : ObjectWrapperParent::CPOW_DelProperty(JSContext *cx, JSObject *obj, jsid id,
473 : jsval *vp)
474 : {
475 : CPOW_LOG(("Calling CPOW_DelProperty (%s)...",
476 : JSVAL_TO_CSTR(cx, id)));
477 :
478 0 : ObjectWrapperParent* self = Unwrap(obj);
479 0 : if (!self)
480 0 : return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_DelProperty");
481 :
482 0 : AutoCheckOperation aco(cx, self);
483 :
484 0 : nsString in_id;
485 :
486 0 : if (!jsval_to_nsString(cx, id, &in_id))
487 0 : return JS_FALSE;
488 :
489 0 : JSVariant out_v;
490 :
491 0 : return (self->Manager()->RequestRunToCompletion() &&
492 : self->CallDelProperty(in_id,
493 0 : aco.StatusPtr(), &out_v) &&
494 0 : aco.Ok() &&
495 0 : jsval_from_JSVariant(cx, out_v, vp));
496 : }
497 :
498 : JSBool
499 0 : ObjectWrapperParent::NewEnumerateInit(JSContext* cx, jsval* statep, jsid* idp)
500 : {
501 0 : AutoCheckOperation aco(cx, this);
502 :
503 0 : JSVariant out_state;
504 : int out_id;
505 :
506 0 : return (CallNewEnumerateInit(aco.StatusPtr(), &out_state, &out_id) &&
507 0 : aco.Ok() &&
508 0 : jsval_from_JSVariant(cx, out_state, statep) &&
509 0 : (!idp || jsid_from_int(cx, out_id, idp)));
510 : }
511 :
512 : JSBool
513 0 : ObjectWrapperParent::NewEnumerateNext(JSContext* cx, jsval* statep, jsid* idp)
514 : {
515 0 : AutoCheckOperation aco(cx, this);
516 :
517 0 : JSVariant in_state;
518 :
519 0 : if (!jsval_to_JSVariant(cx, *statep, &in_state))
520 0 : return JS_FALSE;
521 :
522 0 : JSVariant out_state;
523 0 : nsString out_id;
524 :
525 0 : if (CallNewEnumerateNext(in_state,
526 0 : aco.StatusPtr(), &out_state, &out_id) &&
527 0 : aco.Ok() &&
528 0 : jsval_from_JSVariant(cx, out_state, statep) &&
529 0 : jsid_from_nsString(cx, out_id, idp))
530 : {
531 0 : JSObject* obj = GetJSObject(cx);
532 0 : AutoResolveFlag arf(obj);
533 : return JS_DefinePropertyById(cx, obj, *idp, JSVAL_VOID, NULL, NULL,
534 0 : JSPROP_ENUMERATE);
535 : }
536 0 : return JS_FALSE;
537 : }
538 :
539 : JSBool
540 0 : ObjectWrapperParent::NewEnumerateDestroy(JSContext* cx, jsval state)
541 : {
542 0 : AutoCheckOperation aco(cx, this);
543 :
544 0 : JSVariant in_state;
545 :
546 0 : if (!jsval_to_JSVariant(cx, state, &in_state))
547 0 : return JS_FALSE;
548 :
549 0 : return SendNewEnumerateDestroy(in_state);
550 : }
551 :
552 : /*static*/ JSBool
553 0 : ObjectWrapperParent::CPOW_NewEnumerate(JSContext *cx, JSObject *obj,
554 : JSIterateOp enum_op, jsval *statep,
555 : jsid *idp)
556 : {
557 : CPOW_LOG(("Calling CPOW_NewEnumerate..."));
558 :
559 0 : ObjectWrapperParent* self = Unwrap(obj);
560 0 : if (!self)
561 0 : return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_NewEnumerate");
562 :
563 0 : switch (enum_op) {
564 : case JSENUMERATE_INIT:
565 : case JSENUMERATE_INIT_ALL:
566 0 : self->Manager()->RequestRunToCompletion();
567 0 : return self->NewEnumerateInit(cx, statep, idp);
568 : case JSENUMERATE_NEXT:
569 0 : return self->NewEnumerateNext(cx, statep, idp);
570 : case JSENUMERATE_DESTROY:
571 0 : return self->NewEnumerateDestroy(cx, *statep);
572 : }
573 :
574 : NS_NOTREACHED("Unknown enum_op value in CPOW_NewEnumerate");
575 : return JS_FALSE;
576 : }
577 :
578 : /*static*/ JSBool
579 0 : ObjectWrapperParent::CPOW_NewResolve(JSContext *cx, JSObject *obj, jsid id,
580 : unsigned flags, JSObject **objp)
581 : {
582 : CPOW_LOG(("Calling CPOW_NewResolve (%s)...",
583 : JSVAL_TO_CSTR(cx, id)));
584 :
585 0 : ObjectWrapperParent* self = Unwrap(obj);
586 0 : if (!self)
587 0 : return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_NewResolve");
588 :
589 0 : AutoCheckOperation aco(cx, self);
590 :
591 0 : nsString in_id;
592 :
593 0 : if (!jsval_to_nsString(cx, id, &in_id))
594 0 : return JS_FALSE;
595 :
596 : PObjectWrapperParent* out_pobj;
597 :
598 0 : if (!self->Manager()->RequestRunToCompletion() ||
599 : !self->CallNewResolve(in_id, flags,
600 0 : aco.StatusPtr(), &out_pobj) ||
601 0 : !aco.Ok() ||
602 0 : !JSObject_from_PObjectWrapperParent(cx, out_pobj, objp))
603 0 : return JS_FALSE;
604 :
605 0 : if (*objp) {
606 0 : AutoResolveFlag arf(*objp);
607 : JS_DefinePropertyById(cx, *objp, id, JSVAL_VOID, NULL, NULL,
608 0 : JSPROP_ENUMERATE);
609 : }
610 0 : return JS_TRUE;
611 : }
612 :
613 : /*static*/ JSBool
614 0 : ObjectWrapperParent::CPOW_Convert(JSContext *cx, JSObject *obj, JSType type,
615 : jsval *vp)
616 : {
617 : CPOW_LOG(("Calling CPOW_Convert (to %s)...",
618 : JS_GetTypeName(cx, type)));
619 :
620 0 : ObjectWrapperParent* self = Unwrap(obj);
621 0 : if (!self)
622 0 : return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_Convert");
623 :
624 0 : *vp = OBJECT_TO_JSVAL(obj);
625 :
626 0 : return JS_TRUE;
627 : }
628 :
629 : /*static*/ void
630 0 : ObjectWrapperParent::CPOW_Finalize(JSContext* cx, JSObject* obj)
631 : {
632 : CPOW_LOG(("Calling CPOW_Finalize..."));
633 :
634 0 : ObjectWrapperParent* self = Unwrap(obj);
635 0 : if (self) {
636 0 : self->mObj = NULL;
637 0 : unused << ObjectWrapperParent::Send__delete__(self);
638 : }
639 0 : }
640 :
641 : /*static*/ JSBool
642 0 : ObjectWrapperParent::CPOW_Call(JSContext* cx, unsigned argc, jsval* vp)
643 : {
644 : CPOW_LOG(("Calling CPOW_Call..."));
645 :
646 0 : JSObject* thisobj = JS_THIS_OBJECT(cx, vp);
647 0 : if (!thisobj)
648 0 : return JS_FALSE;
649 :
650 : ObjectWrapperParent* function =
651 0 : Unwrap(JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
652 0 : if (!function)
653 0 : return with_error(cx, JS_FALSE, "Could not unwrap CPOW function");
654 :
655 0 : AutoCheckOperation aco(cx, function);
656 :
657 0 : ObjectWrapperParent* receiver = Unwrap(thisobj);
658 0 : if (!receiver) {
659 : // Substitute child global for parent global object.
660 : // TODO First make sure we're really replacing the global object?
661 : ContextWrapperParent* manager =
662 0 : static_cast<ContextWrapperParent*>(function->Manager());
663 0 : receiver = manager->GetGlobalObjectWrapper();
664 : }
665 :
666 0 : InfallibleTArray<JSVariant> in_argv(argc);
667 0 : jsval* argv = JS_ARGV(cx, vp);
668 0 : for (unsigned i = 0; i < argc; i++)
669 0 : if (!jsval_to_JSVariant(cx, argv[i], in_argv.AppendElement()))
670 0 : return JS_FALSE;
671 :
672 0 : JSVariant out_rval;
673 :
674 0 : return (function->Manager()->RequestRunToCompletion() &&
675 : function->CallCall(receiver, in_argv,
676 0 : aco.StatusPtr(), &out_rval) &&
677 0 : aco.Ok() &&
678 0 : jsval_from_JSVariant(cx, out_rval, vp));
679 : }
680 :
681 : /*static*/ JSBool
682 0 : ObjectWrapperParent::CPOW_Construct(JSContext* cx, unsigned argc, jsval* vp)
683 : {
684 : CPOW_LOG(("Calling CPOW_Construct..."));
685 :
686 0 : ObjectWrapperParent* constructor = Unwrap(JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
687 0 : if (!constructor)
688 0 : return with_error(cx, JS_FALSE, "Could not unwrap CPOW constructor function");
689 :
690 0 : AutoCheckOperation aco(cx, constructor);
691 :
692 0 : InfallibleTArray<JSVariant> in_argv(argc);
693 0 : jsval* argv = JS_ARGV(cx, vp);
694 0 : for (unsigned i = 0; i < argc; i++)
695 0 : if (!jsval_to_JSVariant(cx, argv[i], in_argv.AppendElement()))
696 0 : return JS_FALSE;
697 :
698 : PObjectWrapperParent* out_powp;
699 :
700 0 : return (constructor->Manager()->RequestRunToCompletion() &&
701 0 : constructor->CallConstruct(in_argv, aco.StatusPtr(), &out_powp) &&
702 0 : aco.Ok() &&
703 0 : jsval_from_PObjectWrapperParent(cx, out_powp, vp));
704 : }
705 :
706 : /*static*/ JSBool
707 0 : ObjectWrapperParent::CPOW_HasInstance(JSContext *cx, JSObject *obj, const jsval *v,
708 : JSBool *bp)
709 : {
710 : CPOW_LOG(("Calling CPOW_HasInstance..."));
711 :
712 0 : *bp = JS_FALSE;
713 :
714 0 : ObjectWrapperParent* self = Unwrap(obj);
715 0 : if (!self)
716 0 : return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_HasInstance");
717 :
718 0 : AutoCheckOperation aco(cx, self);
719 :
720 0 : JSVariant in_v;
721 :
722 0 : if (!jsval_to_JSVariant(cx, *v, &in_v))
723 0 : return JS_FALSE;
724 :
725 0 : return (self->Manager()->RequestRunToCompletion() &&
726 : self->CallHasInstance(in_v,
727 0 : aco.StatusPtr(), bp) &&
728 0 : aco.Ok());
729 : }
730 :
731 : /*static*/ JSBool
732 0 : ObjectWrapperParent::CPOW_Equality(JSContext *cx, JSObject *obj, const jsval *v,
733 : JSBool *bp)
734 : {
735 : CPOW_LOG(("Calling CPOW_Equality..."));
736 :
737 0 : *bp = JS_FALSE;
738 :
739 0 : ObjectWrapperParent* self = Unwrap(obj);
740 0 : if (!self)
741 0 : return with_error(cx, JS_FALSE, "Unwrapping failed in CPOW_Equality");
742 :
743 0 : if (JSVAL_IS_PRIMITIVE(*v))
744 0 : return JS_TRUE;
745 :
746 0 : ObjectWrapperParent* other = Unwrap(JSVAL_TO_OBJECT(*v));
747 0 : if (!other)
748 0 : return JS_TRUE;
749 :
750 0 : *bp = (self == other);
751 :
752 0 : return JS_TRUE;
753 : }
|