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 "base/basictypes.h"
42 :
43 : #include "mozilla/jsipc/ContextWrapperChild.h"
44 : #include "mozilla/jsipc/ObjectWrapperChild.h"
45 : #include "mozilla/jsipc/CPOWTypes.h"
46 :
47 : #include "jsapi.h"
48 : #include "nsAutoPtr.h"
49 : #include "nsTArray.h"
50 : #include "nsContentUtils.h"
51 : #include "nsIJSContextStack.h"
52 : #include "nsJSUtils.h"
53 :
54 : using namespace mozilla::jsipc;
55 : using namespace js;
56 :
57 : namespace {
58 :
59 : class AutoContextPusher {
60 :
61 : nsCxPusher mStack;
62 : JSAutoRequest mRequest;
63 : JSContext* const mContext;
64 : const uint32 mSavedOptions;
65 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
66 :
67 : public:
68 :
69 0 : AutoContextPusher(JSContext* cx
70 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
71 : : mRequest(cx)
72 : , mContext(cx)
73 0 : , mSavedOptions(JS_SetOptions(cx, (JS_GetOptions(cx) |
74 0 : JSOPTION_DONT_REPORT_UNCAUGHT)))
75 : {
76 0 : JS_GUARD_OBJECT_NOTIFIER_INIT;
77 0 : mStack.Push(cx, false);
78 0 : }
79 :
80 0 : ~AutoContextPusher() {
81 0 : mStack.Pop();
82 0 : JS_SetOptions(mContext, mSavedOptions);
83 0 : }
84 :
85 : };
86 :
87 : class StatusPtrOwner
88 : {
89 : OperationStatus* mStatusPtr;
90 : public:
91 0 : StatusPtrOwner() : mStatusPtr(NULL) {}
92 0 : void SetStatusPtr(OperationStatus* statusPtr) {
93 0 : mStatusPtr = statusPtr;
94 : // By default, initialize mStatusPtr to failure without an
95 : // exception. Doing so only when the union is uninitialized
96 : // allows AutoCheckOperation classes to be nested on the
97 : // stack, just in case AnswerConstruct, for example, calls
98 : // AnswerCall (as it once did, before there were unrelated
99 : // problems with that approach).
100 0 : if (mStatusPtr->type() == OperationStatus::T__None)
101 0 : *mStatusPtr = JS_FALSE;
102 0 : }
103 0 : OperationStatus* StatusPtr() {
104 0 : NS_ASSERTION(mStatusPtr, "Should have called SetStatusPtr by now.");
105 0 : return mStatusPtr;
106 : }
107 : };
108 :
109 : typedef AutoCheckOperationBase<StatusPtrOwner> ACOBase;
110 :
111 : class AutoCheckOperation : public ACOBase
112 0 : {
113 : JS_DECL_USE_GUARD_OBJECT_NOTIFIER
114 : public:
115 0 : AutoCheckOperation(ObjectWrapperChild* owc,
116 : OperationStatus* statusPtr
117 : JS_GUARD_OBJECT_NOTIFIER_PARAM)
118 0 : : ACOBase(NULL, owc)
119 : {
120 0 : JS_GUARD_OBJECT_NOTIFIER_INIT;
121 0 : SetStatusPtr(statusPtr);
122 0 : }
123 : };
124 : }
125 :
126 : void
127 0 : ObjectWrapperChild::CheckOperation(JSContext*,
128 : OperationStatus* status)
129 : {
130 0 : NS_PRECONDITION(status->type() != OperationStatus::T__None,
131 : "Checking an uninitialized operation.");
132 :
133 0 : JSContext* cx = Manager()->GetContext();
134 : jsval thrown;
135 :
136 0 : if (JS_GetPendingException(cx, &thrown)) {
137 0 : NS_ASSERTION(!(status->type() == OperationStatus::TJSBool &&
138 : status->get_JSBool()),
139 : "Operation succeeded but exception was thrown?");
140 0 : JSVariant exception;
141 0 : if (!jsval_to_JSVariant(cx, thrown, &exception))
142 0 : exception = void_t(); // XXX Useful?
143 0 : *status = exception;
144 0 : JS_ClearPendingException(cx);
145 : }
146 0 : }
147 :
148 0 : ObjectWrapperChild::ObjectWrapperChild(JSContext* cx, JSObject* obj)
149 0 : : mObj(obj)
150 : {
151 0 : JSAutoRequest request(cx);
152 : #ifdef DEBUG
153 : bool added =
154 : #endif
155 0 : JS_AddObjectRoot(cx, &mObj);
156 0 : NS_ASSERTION(added, "ObjectWrapperChild constructor failed to root JSObject*");
157 0 : }
158 :
159 : void
160 0 : ObjectWrapperChild::ActorDestroy(ActorDestroyReason why)
161 : {
162 0 : JSContext* cx = Manager()->GetContext();
163 0 : JSAutoRequest request(cx);
164 0 : JS_RemoveObjectRoot(cx, &mObj);
165 0 : }
166 :
167 : bool
168 0 : ObjectWrapperChild::JSObject_to_JSVariant(JSContext* cx, JSObject* from,
169 : JSVariant* to)
170 : {
171 0 : *to = Manager()->GetOrCreateWrapper(from);
172 0 : return true;
173 : }
174 :
175 : bool
176 0 : ObjectWrapperChild::jsval_to_JSVariant(JSContext* cx, jsval from, JSVariant* to)
177 : {
178 0 : switch (JS_TypeOfValue(cx, from)) {
179 : case JSTYPE_VOID:
180 0 : *to = void_t();
181 0 : return true;
182 : case JSTYPE_NULL:
183 0 : if (from != JSVAL_NULL)
184 0 : return false;
185 : // fall through
186 : case JSTYPE_FUNCTION:
187 : // fall through
188 : case JSTYPE_OBJECT:
189 0 : return JSObject_to_JSVariant(cx, JSVAL_TO_OBJECT(from), to);
190 : case JSTYPE_STRING:
191 : {
192 0 : nsDependentJSString depStr;
193 0 : if (!depStr.init(cx, from))
194 0 : return false;
195 0 : *to = depStr;
196 : }
197 0 : return true;
198 : case JSTYPE_NUMBER:
199 0 : if (JSVAL_IS_INT(from))
200 0 : *to = JSVAL_TO_INT(from);
201 0 : else if (JSVAL_IS_DOUBLE(from))
202 0 : *to = JSVAL_TO_DOUBLE(from);
203 0 : else return false;
204 0 : return true;
205 : case JSTYPE_BOOLEAN:
206 0 : *to = !!JSVAL_TO_BOOLEAN(from);
207 0 : return true;
208 : case JSTYPE_XML:
209 : // fall through
210 : default:
211 0 : return false;
212 : }
213 : }
214 :
215 : /*static*/ bool
216 0 : ObjectWrapperChild::
217 : JSObject_from_PObjectWrapperChild(JSContext*,
218 : const PObjectWrapperChild* from,
219 : JSObject** to)
220 : {
221 : const ObjectWrapperChild* owc =
222 0 : static_cast<const ObjectWrapperChild*>(from);
223 0 : *to = owc ? owc->mObj : NULL;
224 0 : return true;
225 : }
226 :
227 : /*static*/ bool
228 0 : ObjectWrapperChild::JSObject_from_JSVariant(JSContext* cx,
229 : const JSVariant& from,
230 : JSObject** to)
231 : {
232 0 : if (from.type() != JSVariant::TPObjectWrapperChild)
233 0 : return false;
234 : return JSObject_from_PObjectWrapperChild(cx,
235 0 : from.get_PObjectWrapperChild(),
236 0 : to);
237 : }
238 :
239 : /*static*/ bool
240 0 : ObjectWrapperChild::jsval_from_JSVariant(JSContext* cx, const JSVariant& from,
241 : jsval* to)
242 : {
243 0 : switch (from.type()) {
244 : case JSVariant::Tvoid_t:
245 0 : *to = JSVAL_VOID;
246 0 : return true;
247 : case JSVariant::TPObjectWrapperChild:
248 : {
249 : JSObject* obj;
250 0 : if (!JSObject_from_JSVariant(cx, from, &obj))
251 0 : return false;
252 0 : *to = OBJECT_TO_JSVAL(obj);
253 0 : return true;
254 : }
255 : case JSVariant::TnsString:
256 : {
257 0 : const nsString& str = from.get_nsString();
258 : JSString* s = JS_NewUCStringCopyN(cx,
259 : str.BeginReading(),
260 0 : str.Length());
261 0 : if (!s)
262 0 : return false;
263 0 : *to = STRING_TO_JSVAL(s);
264 : }
265 0 : return true;
266 : case JSVariant::Tint:
267 0 : *to = INT_TO_JSVAL(from.get_int());
268 0 : return true;
269 : case JSVariant::Tdouble:
270 0 : return !!JS_NewNumberValue(cx, from.get_double(), to);
271 : case JSVariant::Tbool:
272 0 : *to = BOOLEAN_TO_JSVAL(from.get_bool());
273 0 : return true;
274 : default:
275 0 : return false;
276 : }
277 : }
278 :
279 : ContextWrapperChild*
280 0 : ObjectWrapperChild::Manager()
281 : {
282 0 : PContextWrapperChild* pcwc = PObjectWrapperChild::Manager();
283 0 : return static_cast<ContextWrapperChild*>(pcwc);
284 : }
285 :
286 : static bool
287 0 : jsid_to_nsString(JSContext* cx, jsid from, nsString* to)
288 : {
289 0 : if (JSID_IS_STRING(from)) {
290 : size_t length;
291 0 : const jschar* chars = JS_GetInternedStringCharsAndLength(JSID_TO_STRING(from), &length);
292 0 : *to = nsDependentString(chars, length);
293 0 : return true;
294 : }
295 0 : return false;
296 : }
297 :
298 : static bool
299 0 : jsid_from_nsString(JSContext* cx, const nsString& from, jsid* to)
300 : {
301 0 : JSString* str = JS_NewUCStringCopyN(cx, from.BeginReading(), from.Length());
302 0 : if (!str)
303 0 : return false;
304 0 : return JS_ValueToId(cx, STRING_TO_JSVAL(str), to);
305 : }
306 :
307 : #if 0
308 : // The general schema for ObjectWrapperChild::Answer* methods:
309 : bool
310 : ObjectWrapperChild::AnswerSomething(/* in-parameters */
311 : /* out-parameters */)
312 : {
313 : // initialize out-parameters for failure
314 : JSContext* cx = Manager()->GetContext();
315 : AutoContextPusher acp(cx);
316 : // validate in-parameters, else return false
317 : // successfully perform local JS operations, else return true
318 : // perform out-parameter conversions, else return false
319 : return true;
320 : }
321 : // There's an important subtlety here: though a local JS operation may
322 : // fail, leaving out-parameters uninitialized, we must initialize all
323 : // out-parameters when reporting success (returning true) to the IPC
324 : // messaging system. See AnswerGetProperty for illustration.
325 : #endif
326 :
327 : bool
328 0 : ObjectWrapperChild::AnswerAddProperty(const nsString& id,
329 : OperationStatus* status)
330 : {
331 : jsid interned_id;
332 :
333 0 : JSContext* cx = Manager()->GetContext();
334 0 : AutoContextPusher acp(cx);
335 0 : AutoCheckOperation aco(this, status);
336 :
337 0 : if (!jsid_from_nsString(cx, id, &interned_id))
338 0 : return false;
339 :
340 : *status = JS_DefinePropertyById(cx, mObj, interned_id, JSVAL_VOID,
341 0 : NULL, NULL, 0);
342 0 : return true;
343 : }
344 :
345 : bool
346 0 : ObjectWrapperChild::AnswerGetProperty(const nsString& id,
347 : OperationStatus* status, JSVariant* vp)
348 : {
349 : jsid interned_id;
350 : jsval val;
351 :
352 0 : JSContext* cx = Manager()->GetContext();
353 0 : AutoContextPusher acp(cx);
354 0 : AutoCheckOperation aco(this, status);
355 :
356 0 : if (!jsid_from_nsString(cx, id, &interned_id))
357 0 : return false;
358 :
359 0 : *status = JS_GetPropertyById(cx, mObj, interned_id, &val);
360 :
361 : // Since we fully expect this call to jsval_to_JSVariant to return
362 : // true, we can't just leave vp uninitialized when JS_GetPropertyById
363 : // returns JS_FALSE. This pitfall could be avoided in general if IPDL
364 : // ensured that outparams were pre-initialized to some default value
365 : // (XXXfixme cjones?).
366 0 : return jsval_to_JSVariant(cx, aco.Ok() ? val : JSVAL_VOID, vp);
367 : }
368 :
369 : bool
370 0 : ObjectWrapperChild::AnswerSetProperty(const nsString& id, const JSVariant& v,
371 : OperationStatus* status, JSVariant* vp)
372 : {
373 : jsid interned_id;
374 : jsval val;
375 :
376 0 : *vp = v;
377 :
378 0 : JSContext* cx = Manager()->GetContext();
379 0 : AutoContextPusher acp(cx);
380 0 : AutoCheckOperation aco(this, status);
381 :
382 0 : if (!jsid_from_nsString(cx, id, &interned_id) ||
383 0 : !jsval_from_JSVariant(cx, v, &val))
384 0 : return false;
385 :
386 0 : *status = JS_SetPropertyById(cx, mObj, interned_id, &val);
387 :
388 0 : return jsval_to_JSVariant(cx, aco.Ok() ? val : JSVAL_VOID, vp);
389 : }
390 :
391 : bool
392 0 : ObjectWrapperChild::AnswerDelProperty(const nsString& id,
393 : OperationStatus* status, JSVariant* vp)
394 : {
395 : jsid interned_id;
396 : jsval val;
397 :
398 0 : JSContext* cx = Manager()->GetContext();
399 0 : AutoContextPusher acp(cx);
400 0 : AutoCheckOperation aco(this, status);
401 :
402 0 : if (!jsid_from_nsString(cx, id, &interned_id))
403 0 : return false;
404 :
405 0 : *status = JS_DeletePropertyById2(cx, mObj, interned_id, &val);
406 :
407 0 : return jsval_to_JSVariant(cx, aco.Ok() ? val : JSVAL_VOID, vp);
408 : }
409 :
410 : static const PRUint32 sNextIdIndexSlot = 0;
411 : static const PRUint32 sNumNewEnumerateStateSlots = 1;
412 :
413 : static void
414 0 : CPOW_NewEnumerateState_Finalize(JSContext* cx, JSObject* state)
415 : {
416 : nsTArray<nsString>* strIds =
417 0 : static_cast<nsTArray<nsString>*>(JS_GetPrivate(state));
418 :
419 0 : if (strIds) {
420 0 : delete strIds;
421 0 : JS_SetPrivate(state, NULL);
422 : }
423 0 : }
424 :
425 : // Similar to IteratorClass in XPCWrapper.cpp
426 : static const JSClass sCPOW_NewEnumerateState_JSClass = {
427 : "CPOW NewEnumerate State",
428 : JSCLASS_HAS_PRIVATE |
429 : JSCLASS_HAS_RESERVED_SLOTS(sNumNewEnumerateStateSlots),
430 : JS_PropertyStub, JS_PropertyStub,
431 : JS_PropertyStub, JS_StrictPropertyStub,
432 : JS_EnumerateStub, JS_ResolveStub,
433 : JS_ConvertStub, CPOW_NewEnumerateState_Finalize,
434 : JSCLASS_NO_OPTIONAL_MEMBERS
435 : };
436 :
437 : bool
438 0 : ObjectWrapperChild::AnswerNewEnumerateInit(/* no in-parameters */
439 : OperationStatus* status, JSVariant* statep, int* idp)
440 : {
441 0 : *idp = 0;
442 :
443 0 : JSContext* cx = Manager()->GetContext();
444 0 : AutoContextPusher acp(cx);
445 0 : AutoCheckOperation aco(this, status);
446 :
447 0 : JSClass* clasp = const_cast<JSClass*>(&sCPOW_NewEnumerateState_JSClass);
448 0 : JSObject* state = JS_NewObjectWithGivenProto(cx, clasp, NULL, NULL);
449 0 : if (!state)
450 0 : return false;
451 0 : AutoObjectRooter tvr(cx, state);
452 :
453 0 : for (JSObject* proto = mObj;
454 : proto;
455 : proto = JS_GetPrototype(proto))
456 : {
457 0 : AutoIdArray ids(cx, JS_Enumerate(cx, proto));
458 0 : for (size_t i = 0; i < ids.length(); ++i)
459 : JS_DefinePropertyById(cx, state, ids[i], JSVAL_VOID,
460 0 : NULL, NULL, JSPROP_ENUMERATE | JSPROP_SHARED);
461 : }
462 :
463 : InfallibleTArray<nsString>* strIds;
464 : {
465 0 : AutoIdArray ids(cx, JS_Enumerate(cx, state));
466 0 : if (!ids)
467 0 : return false;
468 0 : strIds = new InfallibleTArray<nsString>(ids.length());
469 0 : for (size_t i = 0; i < ids.length(); ++i)
470 0 : if (!jsid_to_nsString(cx, ids[i], strIds->AppendElement())) {
471 0 : delete strIds;
472 0 : return false;
473 : }
474 : }
475 0 : *idp = strIds->Length();
476 :
477 0 : JS_SetPrivate(state, strIds);
478 0 : JS_SetReservedSlot(state, sNextIdIndexSlot, JSVAL_ZERO);
479 :
480 0 : *status = JSObject_to_JSVariant(cx, state, statep);
481 :
482 0 : return true;
483 : }
484 :
485 : bool
486 0 : ObjectWrapperChild::AnswerNewEnumerateNext(const JSVariant& in_state,
487 : OperationStatus* status, JSVariant* statep, nsString* idp)
488 : {
489 : JSObject* state;
490 :
491 0 : *statep = in_state;
492 0 : idp->Truncate();
493 :
494 0 : JSContext* cx = Manager()->GetContext();
495 0 : AutoContextPusher acp(cx);
496 0 : AutoCheckOperation aco(this, status);
497 :
498 0 : if (!JSObject_from_JSVariant(cx, in_state, &state))
499 0 : return false;
500 :
501 : InfallibleTArray<nsString>* strIds =
502 0 : static_cast<InfallibleTArray<nsString>*>(JS_GetPrivate(state));
503 :
504 0 : if (!strIds)
505 0 : return false;
506 :
507 0 : jsval v = JS_GetReservedSlot(state, sNextIdIndexSlot);
508 :
509 0 : int32_t i = JSVAL_TO_INT(v);
510 0 : NS_ASSERTION(i >= 0, "Index of next jsid negative?");
511 0 : NS_ASSERTION(i <= strIds->Length(), "Index of next jsid too large?");
512 :
513 0 : if (size_t(i) == strIds->Length()) {
514 0 : *status = JS_TRUE;
515 0 : return JSObject_to_JSVariant(cx, NULL, statep);
516 : }
517 :
518 0 : *idp = strIds->ElementAt(i);
519 0 : JS_SetReservedSlot(state, sNextIdIndexSlot, INT_TO_JSVAL(i + 1));
520 0 : *status = JS_TRUE;
521 0 : return true;
522 : }
523 :
524 : bool
525 0 : ObjectWrapperChild::RecvNewEnumerateDestroy(const JSVariant& in_state)
526 : {
527 : JSObject* state;
528 :
529 0 : JSContext* cx = Manager()->GetContext();
530 0 : AutoContextPusher acp(cx);
531 :
532 0 : if (!JSObject_from_JSVariant(cx, in_state, &state))
533 0 : return false;
534 :
535 0 : CPOW_NewEnumerateState_Finalize(cx, state);
536 :
537 0 : return true;
538 : }
539 :
540 : bool
541 0 : ObjectWrapperChild::AnswerNewResolve(const nsString& id, const int& flags,
542 : OperationStatus* status, PObjectWrapperChild** obj2)
543 : {
544 : jsid interned_id;
545 :
546 0 : *obj2 = NULL;
547 :
548 0 : JSContext* cx = Manager()->GetContext();
549 0 : AutoContextPusher acp(cx);
550 0 : AutoCheckOperation aco(this, status);
551 :
552 0 : if (!jsid_from_nsString(cx, id, &interned_id))
553 0 : return false;
554 :
555 : CPOW_LOG(("new-resolving \"%s\"...",
556 : NS_ConvertUTF16toUTF8(id).get()));
557 :
558 : JSPropertyDescriptor desc;
559 0 : if (!JS_GetPropertyDescriptorById(cx, mObj, interned_id, flags, &desc))
560 0 : return true;
561 :
562 0 : *status = JS_TRUE;
563 :
564 0 : if (desc.obj)
565 0 : *obj2 = Manager()->GetOrCreateWrapper(desc.obj);
566 :
567 0 : return true;
568 : }
569 :
570 : bool
571 0 : ObjectWrapperChild::AnswerConvert(const JSType& type,
572 : OperationStatus* status, JSVariant* vp)
573 : {
574 : jsval v;
575 0 : JSContext* cx = Manager()->GetContext();
576 0 : AutoContextPusher acp(cx);
577 0 : AutoCheckOperation aco(this, status);
578 0 : *status = JS_ConvertValue(cx, OBJECT_TO_JSVAL(mObj), type, &v);
579 0 : return jsval_to_JSVariant(cx, aco.Ok() ? v : JSVAL_VOID, vp);
580 : }
581 :
582 : namespace {
583 : // Should be an overestimate of typical JS function arity.
584 : typedef nsAutoTArray<jsval, 5> AutoJSArgs;
585 : }
586 :
587 : bool
588 0 : ObjectWrapperChild::AnswerCall(PObjectWrapperChild* receiver, const InfallibleTArray<JSVariant>& argv,
589 : OperationStatus* status, JSVariant* rval)
590 : {
591 0 : JSContext* cx = Manager()->GetContext();
592 0 : AutoContextPusher acp(cx);
593 0 : AutoCheckOperation aco(this, status);
594 :
595 : JSObject* obj;
596 0 : if (!JSObject_from_PObjectWrapperChild(cx, receiver, &obj))
597 0 : return false;
598 :
599 0 : AutoJSArgs args;
600 0 : PRUint32 argc = argv.Length();
601 0 : jsval *jsargs = args.AppendElements(argc);
602 0 : if (!jsargs)
603 0 : return false;
604 0 : AutoArrayRooter tvr(cx, argc, jsargs);
605 :
606 0 : for (PRUint32 i = 0; i < argc; ++i)
607 0 : if (!jsval_from_JSVariant(cx, argv.ElementAt(i), jsargs + i))
608 0 : return false;
609 :
610 : jsval rv;
611 0 : *status = JS_CallFunctionValue(cx, obj, OBJECT_TO_JSVAL(mObj),
612 0 : argv.Length(), jsargs, &rv);
613 :
614 0 : return jsval_to_JSVariant(cx, aco.Ok() ? rv : JSVAL_VOID, rval);
615 : }
616 :
617 : bool
618 0 : ObjectWrapperChild::AnswerConstruct(const InfallibleTArray<JSVariant>& argv,
619 : OperationStatus* status, PObjectWrapperChild** rval)
620 : {
621 0 : JSContext* cx = Manager()->GetContext();
622 0 : AutoContextPusher acp(cx);
623 0 : AutoCheckOperation aco(this, status);
624 :
625 0 : AutoJSArgs args;
626 0 : PRUint32 argc = argv.Length();
627 0 : jsval* jsargs = args.AppendElements(argc);
628 0 : if (!jsargs)
629 0 : return false;
630 0 : AutoArrayRooter tvr(cx, argc, jsargs);
631 :
632 0 : for (PRUint32 i = 0; i < argc; ++i)
633 0 : if (!jsval_from_JSVariant(cx, argv.ElementAt(i), jsargs + i))
634 0 : return false;
635 :
636 0 : JSObject* obj = JS_New(cx, mObj, argc, jsargs);
637 :
638 0 : *status = !!obj;
639 0 : *rval = Manager()->GetOrCreateWrapper(obj);
640 :
641 0 : return true;
642 : }
643 :
644 : bool
645 0 : ObjectWrapperChild::AnswerHasInstance(const JSVariant& v,
646 : OperationStatus* status, JSBool* bp)
647 : {
648 : jsval candidate;
649 0 : JSContext* cx = Manager()->GetContext();
650 0 : AutoContextPusher acp(cx);
651 0 : AutoCheckOperation aco(this, status);
652 0 : if (!jsval_from_JSVariant(cx, v, &candidate))
653 0 : return false;
654 0 : *status = JS_HasInstance(cx, mObj, candidate, bp);
655 0 : return true;
656 : }
|