1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=4 sw=4 et tw=80:
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "WrapperOwner.h"
9 #include "JavaScriptLogging.h"
10 #include "mozilla/unused.h"
11 #include "mozilla/dom/BindingUtils.h"
12 #include "jsfriendapi.h"
13 #include "xpcprivate.h"
14 #include "CPOWTimer.h"
15 #include "WrapperFactory.h"
17 #include "nsIRemoteTagService.h"
21 using namespace mozilla
;
22 using namespace mozilla::jsipc
;
30 // The object tag is just some auxilliary information that clients can use
31 // however they see fit.
34 AuxCPOWData(ObjectId id
, bool isCallable
, bool isConstructor
, const nsACString
& objectTag
)
36 isCallable(isCallable
),
37 isConstructor(isConstructor
),
42 WrapperOwner::WrapperOwner(JSRuntime
* rt
)
43 : JavaScriptShared(rt
),
48 static inline AuxCPOWData
*
49 AuxCPOWDataOf(JSObject
* obj
)
51 MOZ_ASSERT(IsCPOW(obj
));
52 return static_cast<AuxCPOWData
*>(GetProxyExtra(obj
, 1).toPrivate());
55 static inline WrapperOwner
*
56 OwnerOf(JSObject
* obj
)
58 MOZ_ASSERT(IsCPOW(obj
));
59 return reinterpret_cast<WrapperOwner
*>(GetProxyExtra(obj
, 0).toPrivate());
63 WrapperOwner::idOfUnchecked(JSObject
* obj
)
65 MOZ_ASSERT(IsCPOW(obj
));
67 AuxCPOWData
* aux
= AuxCPOWDataOf(obj
);
68 MOZ_ASSERT(!aux
->id
.isNull());
73 WrapperOwner::idOf(JSObject
* obj
)
75 ObjectId objId
= idOfUnchecked(obj
);
76 MOZ_ASSERT(findCPOWById(objId
) == obj
);
80 class CPOWProxyHandler
: public BaseProxyHandler
83 MOZ_CONSTEXPR
CPOWProxyHandler()
84 : BaseProxyHandler(&family
) {}
86 virtual bool finalizeInBackground(Value priv
) const MOZ_OVERRIDE
{
90 virtual bool getOwnPropertyDescriptor(JSContext
* cx
, HandleObject proxy
, HandleId id
,
91 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
92 virtual bool defineProperty(JSContext
* cx
, HandleObject proxy
, HandleId id
,
93 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
94 virtual bool ownPropertyKeys(JSContext
* cx
, HandleObject proxy
,
95 AutoIdVector
& props
) const MOZ_OVERRIDE
;
96 virtual bool delete_(JSContext
* cx
, HandleObject proxy
, HandleId id
, bool* bp
) const MOZ_OVERRIDE
;
97 virtual bool enumerate(JSContext
* cx
, HandleObject proxy
, MutableHandleObject objp
) const MOZ_OVERRIDE
;
98 virtual bool preventExtensions(JSContext
* cx
, HandleObject proxy
, bool* succeeded
) const MOZ_OVERRIDE
;
99 virtual bool isExtensible(JSContext
* cx
, HandleObject proxy
, bool* extensible
) const MOZ_OVERRIDE
;
100 virtual bool has(JSContext
* cx
, HandleObject proxy
, HandleId id
, bool* bp
) const MOZ_OVERRIDE
;
101 virtual bool get(JSContext
* cx
, HandleObject proxy
, HandleObject receiver
,
102 HandleId id
, MutableHandleValue vp
) const MOZ_OVERRIDE
;
103 virtual bool set(JSContext
* cx
, JS::HandleObject proxy
, JS::HandleObject receiver
,
104 JS::HandleId id
, bool strict
, JS::MutableHandleValue vp
) const MOZ_OVERRIDE
;
105 virtual bool call(JSContext
* cx
, HandleObject proxy
, const CallArgs
& args
) const MOZ_OVERRIDE
;
106 virtual bool construct(JSContext
* cx
, HandleObject proxy
, const CallArgs
& args
) const MOZ_OVERRIDE
;
108 virtual bool getPropertyDescriptor(JSContext
* cx
, HandleObject proxy
, HandleId id
,
109 MutableHandle
<JSPropertyDescriptor
> desc
) const MOZ_OVERRIDE
;
110 virtual bool hasOwn(JSContext
* cx
, HandleObject proxy
, HandleId id
, bool* bp
) const MOZ_OVERRIDE
;
111 virtual bool getOwnEnumerablePropertyKeys(JSContext
* cx
, HandleObject proxy
,
112 AutoIdVector
& props
) const MOZ_OVERRIDE
;
113 virtual bool hasInstance(JSContext
* cx
, HandleObject proxy
,
114 MutableHandleValue v
, bool* bp
) const MOZ_OVERRIDE
;
115 virtual bool objectClassIs(HandleObject obj
, js::ESClassValue classValue
,
116 JSContext
* cx
) const MOZ_OVERRIDE
;
117 virtual const char* className(JSContext
* cx
, HandleObject proxy
) const MOZ_OVERRIDE
;
118 virtual bool regexp_toShared(JSContext
* cx
, HandleObject proxy
, RegExpGuard
* g
) const MOZ_OVERRIDE
;
119 virtual void finalize(JSFreeOp
* fop
, JSObject
* proxy
) const MOZ_OVERRIDE
;
120 virtual void objectMoved(JSObject
* proxy
, const JSObject
* old
) const MOZ_OVERRIDE
;
121 virtual bool isCallable(JSObject
* obj
) const MOZ_OVERRIDE
;
122 virtual bool isConstructor(JSObject
* obj
) const MOZ_OVERRIDE
;
124 static const char family
;
125 static const CPOWProxyHandler singleton
;
128 const char CPOWProxyHandler::family
= 0;
129 const CPOWProxyHandler
CPOWProxyHandler::singleton
;
131 #define FORWARD(call, args) \
132 WrapperOwner* owner = OwnerOf(proxy); \
133 if (!owner->active()) { \
134 JS_ReportError(cx, "cannot use a CPOW whose process is gone"); \
139 return owner->call args; \
143 CPOWProxyHandler::getPropertyDescriptor(JSContext
* cx
, HandleObject proxy
, HandleId id
,
144 MutableHandle
<JSPropertyDescriptor
> desc
) const
146 FORWARD(getPropertyDescriptor
, (cx
, proxy
, id
, desc
));
150 WrapperOwner::getPropertyDescriptor(JSContext
* cx
, HandleObject proxy
, HandleId id
,
151 MutableHandle
<JSPropertyDescriptor
> desc
)
153 ObjectId objId
= idOf(proxy
);
156 if (!toJSIDVariant(cx
, id
, &idVar
))
160 PPropertyDescriptor result
;
161 if (!SendGetPropertyDescriptor(objId
, idVar
, &status
, &result
))
169 return toDescriptor(cx
, result
, desc
);
173 CPOWProxyHandler::getOwnPropertyDescriptor(JSContext
* cx
, HandleObject proxy
, HandleId id
,
174 MutableHandle
<JSPropertyDescriptor
> desc
) const
176 FORWARD(getOwnPropertyDescriptor
, (cx
, proxy
, id
, desc
));
180 WrapperOwner::getOwnPropertyDescriptor(JSContext
* cx
, HandleObject proxy
, HandleId id
,
181 MutableHandle
<JSPropertyDescriptor
> desc
)
183 ObjectId objId
= idOf(proxy
);
186 if (!toJSIDVariant(cx
, id
, &idVar
))
190 PPropertyDescriptor result
;
191 if (!SendGetOwnPropertyDescriptor(objId
, idVar
, &status
, &result
))
199 return toDescriptor(cx
, result
, desc
);
203 CPOWProxyHandler::defineProperty(JSContext
* cx
, HandleObject proxy
, HandleId id
,
204 MutableHandle
<JSPropertyDescriptor
> desc
) const
206 FORWARD(defineProperty
, (cx
, proxy
, id
, desc
));
210 WrapperOwner::defineProperty(JSContext
* cx
, HandleObject proxy
, HandleId id
,
211 MutableHandle
<JSPropertyDescriptor
> desc
)
213 ObjectId objId
= idOf(proxy
);
216 if (!toJSIDVariant(cx
, id
, &idVar
))
219 PPropertyDescriptor descriptor
;
220 if (!fromDescriptor(cx
, desc
, &descriptor
))
224 if (!SendDefineProperty(objId
, idVar
, descriptor
, &status
))
229 return ok(cx
, status
);
233 CPOWProxyHandler::ownPropertyKeys(JSContext
* cx
, HandleObject proxy
,
234 AutoIdVector
& props
) const
236 FORWARD(ownPropertyKeys
, (cx
, proxy
, props
));
240 WrapperOwner::ownPropertyKeys(JSContext
* cx
, HandleObject proxy
, AutoIdVector
& props
)
242 return getPropertyKeys(cx
, proxy
, JSITER_OWNONLY
| JSITER_HIDDEN
| JSITER_SYMBOLS
, props
);
246 CPOWProxyHandler::delete_(JSContext
* cx
, HandleObject proxy
, HandleId id
, bool* bp
) const
248 FORWARD(delete_
, (cx
, proxy
, id
, bp
));
252 WrapperOwner::delete_(JSContext
* cx
, HandleObject proxy
, HandleId id
, bool* bp
)
254 ObjectId objId
= idOf(proxy
);
257 if (!toJSIDVariant(cx
, id
, &idVar
))
261 if (!SendDelete(objId
, idVar
, &status
, bp
))
266 return ok(cx
, status
);
270 CPOWProxyHandler::enumerate(JSContext
* cx
, HandleObject proxy
, MutableHandleObject objp
) const
272 // Using a CPOW for the Iterator would slow down for .. in performance, instead
273 // call the base hook, that will use our implementation of getOwnEnumerablePropertyKeys
274 // and follow the proto chain.
275 return BaseProxyHandler::enumerate(cx
, proxy
, objp
);
279 CPOWProxyHandler::has(JSContext
* cx
, HandleObject proxy
, HandleId id
, bool* bp
) const
281 FORWARD(has
, (cx
, proxy
, id
, bp
));
285 WrapperOwner::has(JSContext
* cx
, HandleObject proxy
, HandleId id
, bool* bp
)
287 ObjectId objId
= idOf(proxy
);
290 if (!toJSIDVariant(cx
, id
, &idVar
))
294 if (!SendHas(objId
, idVar
, &status
, bp
))
299 return ok(cx
, status
);
303 CPOWProxyHandler::hasOwn(JSContext
* cx
, HandleObject proxy
, HandleId id
, bool* bp
) const
305 FORWARD(hasOwn
, (cx
, proxy
, id
, bp
));
309 WrapperOwner::hasOwn(JSContext
* cx
, HandleObject proxy
, HandleId id
, bool* bp
)
311 ObjectId objId
= idOf(proxy
);
314 if (!toJSIDVariant(cx
, id
, &idVar
))
318 if (!SendHasOwn(objId
, idVar
, &status
, bp
))
323 return !!ok(cx
, status
);
327 CPOWProxyHandler::get(JSContext
* cx
, HandleObject proxy
, HandleObject receiver
,
328 HandleId id
, MutableHandleValue vp
) const
330 FORWARD(get
, (cx
, proxy
, receiver
, id
, vp
));
334 CPOWToString(JSContext
* cx
, unsigned argc
, Value
* vp
)
336 CallArgs args
= CallArgsFromVp(argc
, vp
);
337 RootedObject
callee(cx
, &args
.callee());
338 RootedValue
cpowValue(cx
);
339 if (!JS_GetProperty(cx
, callee
, "__cpow__", &cpowValue
))
342 if (!cpowValue
.isObject() || !IsCPOW(&cpowValue
.toObject())) {
343 JS_ReportError(cx
, "CPOWToString called on an incompatible object");
347 RootedObject
proxy(cx
, &cpowValue
.toObject());
348 FORWARD(toString
, (cx
, proxy
, args
));
352 WrapperOwner::toString(JSContext
* cx
, HandleObject cpow
, JS::CallArgs
& args
)
354 // Ask the other side to call its toString method. Update the callee so that
355 // it points to the CPOW and not to the synthesized CPOWToString function.
356 args
.setCallee(ObjectValue(*cpow
));
357 if (!callOrConstruct(cx
, cpow
, args
, false))
360 if (!args
.rval().isString())
363 RootedString
cpowResult(cx
, args
.rval().toString());
364 nsAutoJSString toStringResult
;
365 if (!toStringResult
.init(cx
, cpowResult
))
368 // We don't want to wrap toString() results for things like the location
369 // object, where toString() is supposed to return a URL and nothing else.
371 if (toStringResult
[0] == '[') {
372 result
.AppendLiteral("[object CPOW ");
373 result
+= toStringResult
;
374 result
.AppendLiteral("]");
376 result
+= toStringResult
;
379 JSString
* str
= JS_NewUCStringCopyN(cx
, result
.get(), result
.Length());
383 args
.rval().setString(str
);
388 WrapperOwner::get(JSContext
* cx
, HandleObject proxy
, HandleObject receiver
,
389 HandleId id
, MutableHandleValue vp
)
391 ObjectId objId
= idOf(proxy
);
393 ObjectVariant receiverVar
;
394 if (!toObjectVariant(cx
, receiver
, &receiverVar
))
398 if (!toJSIDVariant(cx
, id
, &idVar
))
403 if (!SendGet(objId
, receiverVar
, idVar
, &status
, &val
))
411 if (!fromVariant(cx
, val
, vp
))
414 if (idVar
.type() == JSIDVariant::TnsString
&&
415 idVar
.get_nsString().EqualsLiteral("toString")) {
416 RootedFunction
toString(cx
, JS_NewFunction(cx
, CPOWToString
, 0, 0, proxy
, "toString"));
420 RootedObject
toStringObj(cx
, JS_GetFunctionObject(toString
));
422 if (!JS_DefineProperty(cx
, toStringObj
, "__cpow__", vp
, JSPROP_PERMANENT
| JSPROP_READONLY
))
425 vp
.set(ObjectValue(*toStringObj
));
432 CPOWProxyHandler::set(JSContext
* cx
, JS::HandleObject proxy
, JS::HandleObject receiver
,
433 JS::HandleId id
, bool strict
, JS::MutableHandleValue vp
) const
435 FORWARD(set
, (cx
, proxy
, receiver
, id
, strict
, vp
));
439 WrapperOwner::set(JSContext
* cx
, JS::HandleObject proxy
, JS::HandleObject receiver
,
440 JS::HandleId id
, bool strict
, JS::MutableHandleValue vp
)
442 ObjectId objId
= idOf(proxy
);
444 ObjectVariant receiverVar
;
445 if (!toObjectVariant(cx
, receiver
, &receiverVar
))
449 if (!toJSIDVariant(cx
, id
, &idVar
))
453 if (!toVariant(cx
, vp
, &val
))
458 if (!SendSet(objId
, receiverVar
, idVar
, strict
, val
, &status
, &result
))
466 return fromVariant(cx
, result
, vp
);
470 CPOWProxyHandler::getOwnEnumerablePropertyKeys(JSContext
* cx
, HandleObject proxy
,
471 AutoIdVector
& props
) const
473 FORWARD(getOwnEnumerablePropertyKeys
, (cx
, proxy
, props
));
477 WrapperOwner::getOwnEnumerablePropertyKeys(JSContext
* cx
, HandleObject proxy
, AutoIdVector
& props
)
479 return getPropertyKeys(cx
, proxy
, JSITER_OWNONLY
, props
);
483 CPOWProxyHandler::preventExtensions(JSContext
* cx
, HandleObject proxy
, bool* succeeded
) const
485 FORWARD(preventExtensions
, (cx
, proxy
, succeeded
));
489 WrapperOwner::preventExtensions(JSContext
* cx
, HandleObject proxy
, bool* succeeded
)
491 ObjectId objId
= idOf(proxy
);
494 if (!SendPreventExtensions(objId
, &status
, succeeded
))
499 return ok(cx
, status
);
503 CPOWProxyHandler::isExtensible(JSContext
* cx
, HandleObject proxy
, bool* extensible
) const
505 FORWARD(isExtensible
, (cx
, proxy
, extensible
));
509 WrapperOwner::isExtensible(JSContext
* cx
, HandleObject proxy
, bool* extensible
)
511 ObjectId objId
= idOf(proxy
);
514 if (!SendIsExtensible(objId
, &status
, extensible
))
519 return ok(cx
, status
);
523 CPOWProxyHandler::call(JSContext
* cx
, HandleObject proxy
, const CallArgs
& args
) const
525 FORWARD(callOrConstruct
, (cx
, proxy
, args
, false));
529 CPOWProxyHandler::construct(JSContext
* cx
, HandleObject proxy
, const CallArgs
& args
) const
531 FORWARD(callOrConstruct
, (cx
, proxy
, args
, true));
535 WrapperOwner::callOrConstruct(JSContext
* cx
, HandleObject proxy
, const CallArgs
& args
,
538 ObjectId objId
= idOf(proxy
);
540 InfallibleTArray
<JSParam
> vals
;
541 AutoValueVector
outobjects(cx
);
544 for (size_t i
= 0; i
< args
.length() + 2; i
++) {
545 // The |this| value for constructors is a magic value that we won't be
546 // able to convert, so skip it.
547 if (i
== 1 && construct
)
548 v
= UndefinedValue();
552 RootedObject
obj(cx
, &v
.toObject());
553 if (xpc::IsOutObject(cx
, obj
)) {
554 // Make sure it is not an in-out object.
556 if (!JS_HasProperty(cx
, obj
, "value", &found
))
559 JS_ReportError(cx
, "in-out objects cannot be sent via CPOWs yet");
563 vals
.AppendElement(JSParam(void_t()));
564 if (!outobjects
.append(ObjectValue(*obj
)))
570 if (!toVariant(cx
, v
, &val
))
572 vals
.AppendElement(JSParam(val
));
577 InfallibleTArray
<JSParam
> outparams
;
578 if (!SendCallOrConstruct(objId
, vals
, construct
, &status
, &result
, &outparams
))
586 if (outparams
.Length() != outobjects
.length())
589 RootedObject
obj(cx
);
590 for (size_t i
= 0; i
< outparams
.Length(); i
++) {
591 // Don't bother doing anything for outparams that weren't set.
592 if (outparams
[i
].type() == JSParam::Tvoid_t
)
595 // Take the value the child process returned, and set it on the XPC
597 if (!fromVariant(cx
, outparams
[i
], &v
))
600 obj
= &outobjects
[i
].toObject();
601 if (!JS_SetProperty(cx
, obj
, "value", v
))
605 if (!fromVariant(cx
, result
, args
.rval()))
612 CPOWProxyHandler::hasInstance(JSContext
* cx
, HandleObject proxy
, MutableHandleValue v
, bool* bp
) const
614 FORWARD(hasInstance
, (cx
, proxy
, v
, bp
));
618 WrapperOwner::hasInstance(JSContext
* cx
, HandleObject proxy
, MutableHandleValue v
, bool* bp
)
620 ObjectId objId
= idOf(proxy
);
623 if (!toVariant(cx
, v
, &vVar
))
628 if (!SendHasInstance(objId
, vVar
, &status
, bp
))
633 return ok(cx
, status
);
637 CPOWProxyHandler::objectClassIs(HandleObject proxy
, js::ESClassValue classValue
, JSContext
* cx
) const
639 FORWARD(objectClassIs
, (cx
, proxy
, classValue
));
643 WrapperOwner::objectClassIs(JSContext
* cx
, HandleObject proxy
, js::ESClassValue classValue
)
645 ObjectId objId
= idOf(proxy
);
647 // This function is assumed infallible, so we just return false if the IPC
650 if (!SendObjectClassIs(objId
, classValue
, &result
))
659 CPOWProxyHandler::className(JSContext
* cx
, HandleObject proxy
) const
661 WrapperOwner
* parent
= OwnerOf(proxy
);
662 if (!parent
->active())
663 return "<dead CPOW>";
664 return parent
->className(cx
, proxy
);
668 WrapperOwner::className(JSContext
* cx
, HandleObject proxy
)
670 ObjectId objId
= idOf(proxy
);
673 if (!SendClassName(objId
, &name
))
678 return ToNewCString(name
);
682 CPOWProxyHandler::regexp_toShared(JSContext
* cx
, HandleObject proxy
, RegExpGuard
* g
) const
684 FORWARD(regexp_toShared
, (cx
, proxy
, g
));
688 WrapperOwner::regexp_toShared(JSContext
* cx
, HandleObject proxy
, RegExpGuard
* g
)
690 ObjectId objId
= idOf(proxy
);
695 if (!SendRegExpToShared(objId
, &status
, &source
, &flags
))
703 RootedObject
regexp(cx
);
704 RootedObject
global(cx
, JS::CurrentGlobalOrNull(cx
));
705 regexp
= JS_NewUCRegExpObject(cx
, global
, source
.get(), source
.Length(), flags
);
709 return js::RegExpToSharedNonInline(cx
, regexp
, g
);
713 CPOWProxyHandler::finalize(JSFreeOp
* fop
, JSObject
* proxy
) const
715 AuxCPOWData
* aux
= AuxCPOWDataOf(proxy
);
717 OwnerOf(proxy
)->drop(proxy
);
724 CPOWProxyHandler::objectMoved(JSObject
* proxy
, const JSObject
* old
) const
726 OwnerOf(proxy
)->updatePointer(proxy
, old
);
730 CPOWProxyHandler::isCallable(JSObject
* proxy
) const
732 AuxCPOWData
* aux
= AuxCPOWDataOf(proxy
);
733 return aux
->isCallable
;
737 CPOWProxyHandler::isConstructor(JSObject
* proxy
) const
739 AuxCPOWData
* aux
= AuxCPOWDataOf(proxy
);
740 return aux
->isConstructor
;
744 WrapperOwner::drop(JSObject
* obj
)
746 ObjectId objId
= idOf(obj
);
748 cpows_
.remove(objId
);
750 unused
<< SendDropObject(objId
);
755 WrapperOwner::updatePointer(JSObject
* obj
, const JSObject
* old
)
757 ObjectId objId
= idOfUnchecked(obj
);
758 MOZ_ASSERT(findCPOWById(objId
) == old
);
759 cpows_
.add(objId
, obj
);
765 if (!JavaScriptShared::init())
772 WrapperOwner::getPropertyKeys(JSContext
* cx
, HandleObject proxy
, uint32_t flags
, AutoIdVector
& props
)
774 ObjectId objId
= idOf(proxy
);
777 InfallibleTArray
<JSIDVariant
> ids
;
778 if (!SendGetPropertyKeys(objId
, flags
, &status
, &ids
))
786 for (size_t i
= 0; i
< ids
.Length(); i
++) {
788 if (!fromJSIDVariant(cx
, ids
[i
], &id
))
790 if (!props
.append(id
))
801 IsCPOW(JSObject
* obj
)
803 return IsProxy(obj
) && GetProxyHandler(obj
) == &CPOWProxyHandler::singleton
;
807 IsWrappedCPOW(JSObject
* obj
)
809 JSObject
* unwrapped
= js::UncheckedUnwrap(obj
, true);
812 return IsCPOW(unwrapped
);
816 GetWrappedCPOWTag(JSObject
* obj
, nsACString
& out
)
818 JSObject
* unwrapped
= js::UncheckedUnwrap(obj
, true);
819 MOZ_ASSERT(IsCPOW(unwrapped
));
821 AuxCPOWData
* aux
= AuxCPOWDataOf(unwrapped
);
823 out
= aux
->objectTag
;
827 InstanceOf(JSObject
* proxy
, const nsID
* id
, bool* bp
)
829 WrapperOwner
* parent
= OwnerOf(proxy
);
830 if (!parent
->active())
831 return NS_ERROR_UNEXPECTED
;
832 return parent
->instanceOf(proxy
, id
, bp
);
836 DOMInstanceOf(JSContext
* cx
, JSObject
* proxy
, int prototypeID
, int depth
, bool* bp
)
838 FORWARD(domInstanceOf
, (cx
, proxy
, prototypeID
, depth
, bp
));
841 } /* namespace jsipc */
842 } /* namespace mozilla */
845 WrapperOwner::instanceOf(JSObject
* obj
, const nsID
* id
, bool* bp
)
847 ObjectId objId
= idOf(obj
);
850 ConvertID(*id
, &iid
);
853 if (!SendInstanceOf(objId
, iid
, &status
, bp
))
854 return NS_ERROR_UNEXPECTED
;
856 if (status
.type() != ReturnStatus::TReturnSuccess
)
857 return NS_ERROR_UNEXPECTED
;
863 WrapperOwner::domInstanceOf(JSContext
* cx
, JSObject
* obj
, int prototypeID
, int depth
, bool* bp
)
865 ObjectId objId
= idOf(obj
);
868 if (!SendDOMInstanceOf(objId
, prototypeID
, depth
, &status
, bp
))
873 return ok(cx
, status
);
877 WrapperOwner::ActorDestroy(ActorDestroyReason why
)
882 unwaivedObjectIds_
.clear();
883 waivedObjectIds_
.clear();
887 WrapperOwner::ipcfail(JSContext
* cx
)
889 JS_ReportError(cx
, "child process crashed or timedout");
894 WrapperOwner::ok(JSContext
* cx
, const ReturnStatus
& status
)
896 if (status
.type() == ReturnStatus::TReturnSuccess
)
899 if (status
.type() == ReturnStatus::TReturnStopIteration
)
900 return JS_ThrowStopIteration(cx
);
903 if (!fromVariant(cx
, status
.get_ReturnException().exn(), &exn
))
906 JS_SetPendingException(cx
, exn
);
911 MakeRemoteObject(JSContext
* cx
, ObjectId id
, HandleObject obj
)
915 nsCOMPtr
<nsIRemoteTagService
> service
=
916 do_GetService("@mozilla.org/addons/remote-tag-service;1");
918 RootedValue
objVal(cx
, ObjectValue(*obj
));
919 service
->GetRemoteObjectTag(objVal
, objectTag
);
922 return RemoteObject(id
.serialize(),
924 JS::IsConstructor(obj
),
929 WrapperOwner::toObjectVariant(JSContext
* cx
, JSObject
* objArg
, ObjectVariant
* objVarp
)
931 RootedObject
obj(cx
, objArg
);
934 // We always save objects unwrapped in the CPOW table. If we stored
935 // wrappers, then the wrapper might be GCed while the target remained alive.
936 // Whenever operating on an object that comes from the table, we wrap it
937 // in findObjectById.
938 unsigned wrapperFlags
= 0;
939 obj
= js::UncheckedUnwrap(obj
, true, &wrapperFlags
);
940 if (obj
&& IsCPOW(obj
) && OwnerOf(obj
) == this) {
941 *objVarp
= LocalObject(idOf(obj
).serialize());
944 bool waiveXray
= wrapperFlags
& xpc::WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG
;
946 ObjectId id
= objectIdMap(waiveXray
).find(obj
);
948 MOZ_ASSERT(id
.hasXrayWaiver() == waiveXray
);
949 *objVarp
= MakeRemoteObject(cx
, id
, obj
);
953 // Need to call PreserveWrapper on |obj| in case it's a reflector.
954 // FIXME: What if it's an XPCWrappedNative?
955 if (mozilla::dom::IsDOMObject(obj
))
956 mozilla::dom::TryPreserveWrapper(obj
);
958 id
= ObjectId(nextSerialNumber_
++, waiveXray
);
959 if (!objects_
.add(id
, obj
))
961 if (!objectIdMap(waiveXray
).add(cx
, obj
, id
))
964 *objVarp
= MakeRemoteObject(cx
, id
, obj
);
969 WrapperOwner::fromObjectVariant(JSContext
* cx
, ObjectVariant objVar
)
971 if (objVar
.type() == ObjectVariant::TRemoteObject
) {
972 return fromRemoteObjectVariant(cx
, objVar
.get_RemoteObject());
974 return fromLocalObjectVariant(cx
, objVar
.get_LocalObject());
979 WrapperOwner::fromRemoteObjectVariant(JSContext
* cx
, RemoteObject objVar
)
981 ObjectId objId
= ObjectId::deserialize(objVar
.serializedId());
982 RootedObject
obj(cx
, findCPOWById(objId
));
985 // All CPOWs live in the privileged junk scope.
986 RootedObject
junkScope(cx
, xpc::PrivilegedJunkScope());
987 JSAutoCompartment
ac(cx
, junkScope
);
988 RootedValue
v(cx
, UndefinedValue());
989 obj
= NewProxyObject(cx
,
990 &CPOWProxyHandler::singleton
,
997 if (!cpows_
.add(objId
, obj
))
1000 // Incref once we know the decref will be called.
1003 AuxCPOWData
* aux
= new AuxCPOWData(objId
,
1004 objVar
.isCallable(),
1005 objVar
.isConstructor(),
1006 objVar
.objectTag());
1008 SetProxyExtra(obj
, 0, PrivateValue(this));
1009 SetProxyExtra(obj
, 1, PrivateValue(aux
));
1012 if (!JS_WrapObject(cx
, &obj
))
1018 WrapperOwner::fromLocalObjectVariant(JSContext
* cx
, LocalObject objVar
)
1020 ObjectId id
= ObjectId::deserialize(objVar
.serializedId());
1021 Rooted
<JSObject
*> obj(cx
, findObjectById(cx
, id
));
1024 if (!JS_WrapObject(cx
, &obj
))