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/. */
7 /* JavaScript JSClasses and JSOps for our Wrapped Native JS Objects. */
9 #include "xpcprivate.h"
11 #include "mozilla/dom/BindingUtils.h"
12 #include "mozilla/Preferences.h"
13 #include "nsIAddonInterposition.h"
14 #include "AddonWrapper.h"
16 using namespace mozilla
;
19 /***************************************************************************/
21 // All of the exceptions thrown into JS from this file go through here.
22 // That makes this a nice place to set a breakpoint.
24 static bool Throw(nsresult errNum
, JSContext
* cx
)
26 XPCThrower::Throw(errNum
, cx
);
30 // Handy macro used in many callback stub below.
32 #define THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper) \
35 return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); \
36 if (!wrapper->IsValid()) \
37 return Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx); \
40 /***************************************************************************/
43 ToStringGuts(XPCCallContext
& ccx
)
46 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
49 sz
= wrapper
->ToString(ccx
.GetTearOff());
51 sz
= JS_smprintf("[xpconnect wrapped native prototype]");
54 JS_ReportOutOfMemory(ccx
);
58 JSString
* str
= JS_NewStringCopyZ(ccx
, sz
);
63 ccx
.SetRetVal(STRING_TO_JSVAL(str
));
67 /***************************************************************************/
70 XPC_WN_Shared_ToString(JSContext
* cx
, unsigned argc
, jsval
* vp
)
72 CallArgs args
= CallArgsFromVp(argc
, vp
);
73 RootedObject
obj(cx
, JS_THIS_OBJECT(cx
, vp
));
77 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
79 return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO
, cx
);
80 ccx
.SetName(ccx
.GetRuntime()->GetStringID(XPCJSRuntime::IDX_TO_STRING
));
81 ccx
.SetArgsAndResultPtr(args
.length(), args
.array(), vp
);
82 return ToStringGuts(ccx
);
86 XPC_WN_Shared_ToSource(JSContext
* cx
, unsigned argc
, jsval
* vp
)
88 CallArgs args
= CallArgsFromVp(argc
, vp
);
89 static const char empty
[] = "({})";
90 JSString
* str
= JS_NewStringCopyN(cx
, empty
, sizeof(empty
)-1);
93 args
.rval().setString(str
);
98 /***************************************************************************/
100 // A "double wrapped object" is a user JSObject that has been wrapped as a
101 // wrappedJS in order to be used by native code and then re-wrapped by a
102 // wrappedNative wrapper to be used by JS code. One might think of it as:
103 // wrappedNative(wrappedJS(underlying_JSObject))
104 // This is done (as opposed to just unwrapping the wrapped JS and automatically
105 // returning the underlying JSObject) so that JS callers will see what looks
106 // Like any other xpcom object - and be limited to use its interfaces.
108 // See the comment preceding nsIXPCWrappedJSObjectGetter in nsIXPConnect.idl.
111 GetDoubleWrappedJSObject(XPCCallContext
& ccx
, XPCWrappedNative
* wrapper
)
113 RootedObject
obj(ccx
);
114 nsCOMPtr
<nsIXPConnectWrappedJS
>
115 underware
= do_QueryInterface(wrapper
->GetIdentityObject());
117 RootedObject
mainObj(ccx
, underware
->GetJSObject());
119 RootedId
id(ccx
, ccx
.GetRuntime()->
120 GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT
));
122 JSAutoCompartment
ac(ccx
, mainObj
);
124 RootedValue
val(ccx
);
125 if (JS_GetPropertyById(ccx
, mainObj
, id
, &val
) &&
126 !val
.isPrimitive()) {
127 obj
= val
.toObjectOrNull();
134 // This is the getter native function we use to handle 'wrappedJSObject' for
135 // double wrapped JSObjects.
138 XPC_WN_DoubleWrappedGetter(JSContext
* cx
, unsigned argc
, jsval
* vp
)
140 CallArgs args
= CallArgsFromVp(argc
, vp
);
142 RootedObject
obj(cx
, JS_THIS_OBJECT(cx
, vp
));
146 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
147 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
148 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
150 MOZ_ASSERT(JS_TypeOfValue(cx
, args
.calleev()) == JSTYPE_FUNCTION
, "bad function");
152 RootedObject
realObject(cx
, GetDoubleWrappedJSObject(ccx
, wrapper
));
154 // This is pretty unexpected at this point. The object originally
155 // responded to this get property call and now gives no object.
156 // XXX Should this throw something at the caller?
157 args
.rval().setNull();
161 // It is a double wrapped object. This should really never appear in
162 // content these days, but addons still do it - see bug 965921.
163 if (MOZ_UNLIKELY(!nsContentUtils::IsCallerChrome())) {
164 JS_ReportError(cx
, "Attempt to use .wrappedJSObject in untrusted code");
167 args
.rval().setObject(*realObject
);
168 return JS_WrapValue(cx
, args
.rval());
171 /***************************************************************************/
173 // This is our shared function to define properties on our JSObjects.
177 * We *never* set the tearoff names (e.g. nsIFoo) as JS_ENUMERATE.
178 * We *never* set toString or toSource as JS_ENUMERATE.
182 DefinePropertyIfFound(XPCCallContext
& ccx
,
186 XPCNativeInterface
* iface
,
187 XPCNativeMember
* member
,
188 XPCWrappedNativeScope
* scope
,
189 bool reflectToStringAndToSource
,
190 XPCWrappedNative
* wrapperToReflectInterfaceNames
,
191 XPCWrappedNative
* wrapperToReflectDoubleWrap
,
192 XPCNativeScriptableInfo
* scriptableInfo
,
196 RootedId
id(ccx
, idArg
);
197 XPCJSRuntime
* rt
= ccx
.GetRuntime();
205 found
= set
->FindMember(id
, &member
, &iface
);
207 found
= (nullptr != (member
= iface
->FindMember(id
)));
210 if (reflectToStringAndToSource
) {
214 if (scriptableInfo
) {
215 nsCOMPtr
<nsIClassInfo
> classInfo
= do_QueryInterface(
216 scriptableInfo
->GetCallback());
219 nsresult rv
= classInfo
->GetFlags(&flags
);
221 return Throw(rv
, ccx
);
225 bool overwriteToString
= !(flags
& nsIClassInfo::DOM_OBJECT
)
226 || Preferences::GetBool("dom.XPCToStringForDOMClasses", false);
228 if(id
== rt
->GetStringID(XPCJSRuntime::IDX_TO_STRING
)
229 && overwriteToString
)
231 call
= XPC_WN_Shared_ToString
;
232 name
= rt
->GetStringName(XPCJSRuntime::IDX_TO_STRING
);
233 id
= rt
->GetStringID(XPCJSRuntime::IDX_TO_STRING
);
234 } else if (id
== rt
->GetStringID(XPCJSRuntime::IDX_TO_SOURCE
)) {
235 call
= XPC_WN_Shared_ToSource
;
236 name
= rt
->GetStringName(XPCJSRuntime::IDX_TO_SOURCE
);
237 id
= rt
->GetStringID(XPCJSRuntime::IDX_TO_SOURCE
);
244 RootedFunction
fun(ccx
, JS_NewFunction(ccx
, call
, 0, 0, obj
, name
));
246 JS_ReportOutOfMemory(ccx
);
250 AutoResolveName
arn(ccx
, id
);
253 RootedObject
value(ccx
, JS_GetFunctionObject(fun
));
254 return JS_DefinePropertyById(ccx
, obj
, id
, value
,
255 propFlags
& ~JSPROP_ENUMERATE
);
258 // This *might* be a tearoff name that is not yet part of our
259 // set. Let's lookup the name and see if it is the name of an
260 // interface. Then we'll see if the object actually *does* this
261 // interface and add a tearoff as necessary.
263 if (wrapperToReflectInterfaceNames
) {
264 JSAutoByteString name
;
265 AutoMarkingNativeInterfacePtr
iface2(ccx
);
266 XPCWrappedNativeTearOff
* to
;
267 RootedObject
jso(ccx
);
270 if (JSID_IS_STRING(id
) &&
271 name
.encodeLatin1(ccx
, JSID_TO_STRING(id
)) &&
272 (iface2
= XPCNativeInterface::GetNewOrUsed(name
.ptr()), iface2
) &&
273 nullptr != (to
= wrapperToReflectInterfaceNames
->
274 FindTearOff(iface2
, true, &rv
)) &&
275 nullptr != (jso
= to
->GetJSObject()))
278 AutoResolveName
arn(ccx
, id
);
281 return JS_DefinePropertyById(ccx
, obj
, id
, jso
,
282 propFlags
& ~JSPROP_ENUMERATE
);
283 } else if (NS_FAILED(rv
) && rv
!= NS_ERROR_NO_INTERFACE
) {
284 return Throw(rv
, ccx
);
288 // This *might* be a double wrapped JSObject
289 if (wrapperToReflectDoubleWrap
&&
290 id
== rt
->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT
) &&
291 GetDoubleWrappedJSObject(ccx
, wrapperToReflectDoubleWrap
)) {
292 // We build and add a getter function.
293 // A security check is done on a per-get basis.
297 id
= rt
->GetStringID(XPCJSRuntime::IDX_WRAPPED_JSOBJECT
);
298 name
= rt
->GetStringName(XPCJSRuntime::IDX_WRAPPED_JSOBJECT
);
300 fun
= JS_NewFunction(ccx
, XPC_WN_DoubleWrappedGetter
,
306 RootedObject
funobj(ccx
, JS_GetFunctionObject(fun
));
310 propFlags
|= JSPROP_GETTER
| JSPROP_SHARED
;
311 propFlags
&= ~JSPROP_ENUMERATE
;
313 AutoResolveName
arn(ccx
, id
);
316 return JS_DefinePropertyById(ccx
, obj
, id
, UndefinedHandleValue
, propFlags
,
317 JS_DATA_TO_FUNC_PTR(JSPropertyOp
, funobj
.get()),
327 if (wrapperToReflectInterfaceNames
) {
328 XPCWrappedNativeTearOff
* to
=
329 wrapperToReflectInterfaceNames
->FindTearOff(iface
, true);
333 RootedObject
jso(ccx
, to
->GetJSObject());
337 AutoResolveName
arn(ccx
, id
);
340 return JS_DefinePropertyById(ccx
, obj
, id
, jso
,
341 propFlags
& ~JSPROP_ENUMERATE
);
348 if (member
->IsConstant()) {
349 RootedValue
val(ccx
);
350 AutoResolveName
arn(ccx
, id
);
353 return member
->GetConstantValue(ccx
, iface
, val
.address()) &&
354 JS_DefinePropertyById(ccx
, obj
, id
, val
, propFlags
);
357 if (scope
->HasInterposition()) {
358 Rooted
<JSPropertyDescriptor
> desc(ccx
);
359 if (!xpc::Interpose(ccx
, obj
, iface
->GetIID(), id
, &desc
))
363 AutoResolveName
arn(ccx
, id
);
366 return JS_DefinePropertyById(ccx
, obj
, id
, desc
.value(), desc
.attributes(),
367 desc
.getter(), desc
.setter());
371 if (id
== rt
->GetStringID(XPCJSRuntime::IDX_TO_STRING
) ||
372 id
== rt
->GetStringID(XPCJSRuntime::IDX_TO_SOURCE
) ||
374 scriptableInfo
->GetFlags().DontEnumQueryInterface() &&
375 id
== rt
->GetStringID(XPCJSRuntime::IDX_QUERY_INTERFACE
)))
376 propFlags
&= ~JSPROP_ENUMERATE
;
378 RootedValue
funval(ccx
);
379 if (!member
->NewFunctionObject(ccx
, iface
, obj
, funval
.address()))
382 if (member
->IsMethod()) {
383 AutoResolveName
arn(ccx
, id
);
386 return JS_DefinePropertyById(ccx
, obj
, id
, funval
, propFlags
);
391 MOZ_ASSERT(member
->IsAttribute(), "way broken!");
393 propFlags
|= JSPROP_GETTER
| JSPROP_SHARED
;
394 JSObject
* funobj
= funval
.toObjectOrNull();
395 JSPropertyOp getter
= JS_DATA_TO_FUNC_PTR(JSPropertyOp
, funobj
);
396 JSStrictPropertyOp setter
;
397 if (member
->IsWritableAttribute()) {
398 propFlags
|= JSPROP_SETTER
;
399 propFlags
&= ~JSPROP_READONLY
;
400 setter
= JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp
, funobj
);
402 setter
= js_GetterOnlyPropertyStub
;
405 AutoResolveName
arn(ccx
, id
);
409 return JS_DefinePropertyById(ccx
, obj
, id
, UndefinedHandleValue
, propFlags
, getter
, setter
);
412 /***************************************************************************/
413 /***************************************************************************/
416 XPC_WN_OnlyIWrite_AddPropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
, MutableHandleValue vp
)
418 XPCCallContext
ccx(JS_CALLER
, cx
, obj
, NullPtr(), id
);
419 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
420 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
422 // Allow only XPConnect to add/set the property
423 if (ccx
.GetResolveName() == id
)
426 return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN
, cx
);
430 XPC_WN_OnlyIWrite_SetPropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
, bool strict
,
431 MutableHandleValue vp
)
433 return XPC_WN_OnlyIWrite_AddPropertyStub(cx
, obj
, id
, vp
);
437 XPC_WN_CannotModifyPropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
,
438 MutableHandleValue vp
)
440 return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN
, cx
);
444 XPC_WN_CantDeletePropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
,
447 return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN
, cx
);
451 XPC_WN_CannotModifyStrictPropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
, bool strict
,
452 MutableHandleValue vp
)
454 return XPC_WN_CannotModifyPropertyStub(cx
, obj
, id
, vp
);
458 XPC_WN_Shared_Convert(JSContext
* cx
, HandleObject obj
, JSType type
, MutableHandleValue vp
)
460 if (type
== JSTYPE_OBJECT
) {
461 vp
.set(OBJECT_TO_JSVAL(obj
));
465 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
466 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
467 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
470 case JSTYPE_FUNCTION
:
472 if (!ccx
.GetTearOff()) {
473 XPCNativeScriptableInfo
* si
= wrapper
->GetScriptableInfo();
474 if (si
&& (si
->GetFlags().WantCall() ||
475 si
->GetFlags().WantConstruct())) {
476 vp
.set(OBJECT_TO_JSVAL(obj
));
481 return Throw(NS_ERROR_XPC_CANT_CONVERT_WN_TO_FUN
, cx
);
483 vp
.set(JS_GetNaNValue(cx
));
491 ccx
.SetName(ccx
.GetRuntime()->GetStringID(XPCJSRuntime::IDX_TO_STRING
));
492 ccx
.SetArgsAndResultPtr(0, nullptr, vp
.address());
494 XPCNativeMember
* member
= ccx
.GetMember();
495 if (member
&& member
->IsMethod()) {
496 if (!XPCWrappedNative::CallMethod(ccx
))
499 if (vp
.isPrimitive())
504 return ToStringGuts(ccx
);
507 NS_ERROR("bad type in conversion");
510 NS_NOTREACHED("huh?");
515 XPC_WN_Shared_Enumerate(JSContext
* cx
, HandleObject obj
)
517 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
518 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
519 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
521 // Since we aren't going to enumerate tearoff names and the prototype
522 // handles non-mutated members, we can do this potential short-circuit.
523 if (!wrapper
->HasMutatedSet())
526 XPCNativeSet
* set
= wrapper
->GetSet();
527 XPCNativeSet
* protoSet
= wrapper
->HasProto() ?
528 wrapper
->GetProto()->GetSet() : nullptr;
530 uint16_t interface_count
= set
->GetInterfaceCount();
531 XPCNativeInterface
** interfaceArray
= set
->GetInterfaceArray();
532 for (uint16_t i
= 0; i
< interface_count
; i
++) {
533 XPCNativeInterface
* iface
= interfaceArray
[i
];
534 uint16_t member_count
= iface
->GetMemberCount();
535 for (uint16_t k
= 0; k
< member_count
; k
++) {
536 XPCNativeMember
* member
= iface
->GetMemberAt(k
);
537 jsid name
= member
->GetName();
539 // Skip if this member is going to come from the proto.
542 protoSet
->FindMember(name
, nullptr, &index
) && index
== i
)
544 if (!xpc_ForcePropertyResolve(cx
, obj
, name
))
551 /***************************************************************************/
559 WrappedNativeFinalize(js::FreeOp
* fop
, JSObject
* obj
, WNHelperType helperType
)
561 const js::Class
* clazz
= js::GetObjectClass(obj
);
562 if (clazz
->flags
& JSCLASS_DOM_GLOBAL
) {
563 mozilla::dom::DestroyProtoAndIfaceCache(obj
);
565 nsISupports
* p
= static_cast<nsISupports
*>(xpc_GetJSPrivate(obj
));
569 XPCWrappedNative
* wrapper
= static_cast<XPCWrappedNative
*>(p
);
570 if (helperType
== WN_HELPER
)
571 wrapper
->GetScriptableCallback()->Finalize(wrapper
, js::CastToJSFreeOp(fop
), obj
);
572 wrapper
->FlatJSObjectFinalized();
576 XPC_WN_NoHelper_Finalize(js::FreeOp
* fop
, JSObject
* obj
)
578 WrappedNativeFinalize(fop
, obj
, WN_NOHELPER
);
582 * General comment about XPConnect tracing: Given a C++ object |wrapper| and its
583 * corresponding JS object |obj|, calling |wrapper->TraceSelf| will ask the JS
584 * engine to mark |obj|. Eventually, this will lead to the trace hook being
585 * called for |obj|. The trace hook should call |wrapper->TraceInside|, which
586 * should mark any JS objects held by |wrapper| as members.
590 MarkWrappedNative(JSTracer
* trc
, JSObject
* obj
)
592 const js::Class
* clazz
= js::GetObjectClass(obj
);
593 if (clazz
->flags
& JSCLASS_DOM_GLOBAL
) {
594 mozilla::dom::TraceProtoAndIfaceCache(trc
, obj
);
596 MOZ_ASSERT(IS_WN_CLASS(clazz
));
598 XPCWrappedNative
* wrapper
= XPCWrappedNative::Get(obj
);
599 if (wrapper
&& wrapper
->IsValid())
600 wrapper
->TraceInside(trc
);
604 XPCWrappedNative::Trace(JSTracer
* trc
, JSObject
* obj
)
606 MarkWrappedNative(trc
, obj
);
610 XPC_WN_NoHelper_Resolve(JSContext
* cx
, HandleObject obj
, HandleId id
)
612 XPCCallContext
ccx(JS_CALLER
, cx
, obj
, NullPtr(), id
);
613 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
614 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
616 XPCNativeSet
* set
= ccx
.GetSet();
620 // Don't resolve properties that are on our prototype.
621 if (ccx
.GetInterface() && !ccx
.GetStaticMemberIsLocal())
624 return DefinePropertyIfFound(ccx
, obj
, id
,
625 set
, nullptr, nullptr, wrapper
->GetScope(),
626 true, wrapper
, wrapper
, nullptr,
629 JSPROP_PERMANENT
, nullptr);
633 XPC_WN_OuterObject(JSContext
* cx
, HandleObject objArg
)
635 JSObject
* obj
= objArg
;
637 XPCWrappedNative
* wrapper
= XPCWrappedNative::Get(obj
);
639 Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO
, cx
);
644 if (!wrapper
->IsValid()) {
645 Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN
, cx
);
650 XPCNativeScriptableInfo
* si
= wrapper
->GetScriptableInfo();
651 if (si
&& si
->GetFlags().WantOuterObject()) {
652 RootedObject
newThis(cx
);
654 si
->GetCallback()->OuterObject(wrapper
, cx
, obj
, newThis
.address());
668 const XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass
= {
670 "XPCWrappedNative_NoHelper", // name;
672 JSCLASS_PRIVATE_IS_NSISUPPORTS
, // flags
674 /* Mandatory non-null function pointer members. */
675 XPC_WN_OnlyIWrite_AddPropertyStub
, // addProperty
676 XPC_WN_CantDeletePropertyStub
, // delProperty
677 JS_PropertyStub
, // getProperty
678 XPC_WN_OnlyIWrite_SetPropertyStub
, // setProperty
680 XPC_WN_Shared_Enumerate
, // enumerate
681 XPC_WN_NoHelper_Resolve
, // resolve
682 XPC_WN_Shared_Convert
, // convert
683 XPC_WN_NoHelper_Finalize
, // finalize
685 /* Optionally non-null members start here. */
687 nullptr, // construct
688 nullptr, // hasInstance
689 XPCWrappedNative::Trace
, // trace
694 nullptr, // outerObject
695 nullptr, // innerObject
696 nullptr, // iteratorObject
697 true, // isWrappedNative
702 nullptr, // lookupGeneric
703 nullptr, // lookupProperty
704 nullptr, // lookupElement
705 nullptr, // defineGeneric
706 nullptr, // defineProperty
707 nullptr, // defineElement
708 nullptr, // getGeneric
709 nullptr, // getProperty
710 nullptr, // getElement
711 nullptr, // setGeneric
712 nullptr, // setProperty
713 nullptr, // setElement
714 nullptr, // getGenericAttributes
715 nullptr, // setGenericAttributes
716 nullptr, // deleteGeneric
717 nullptr, nullptr, // watch/unwatch
719 XPC_WN_JSOp_Enumerate
,
720 XPC_WN_JSOp_ThisObject
,
723 0 // interfacesBitmap
727 /***************************************************************************/
730 XPC_WN_MaybeResolvingPropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
, MutableHandleValue vp
)
732 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
733 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
734 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
736 if (ccx
.GetResolvingWrapper() == wrapper
)
738 return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN
, cx
);
742 XPC_WN_MaybeResolvingStrictPropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
, bool strict
,
743 MutableHandleValue vp
)
745 return XPC_WN_MaybeResolvingPropertyStub(cx
, obj
, id
, vp
);
749 XPC_WN_MaybeResolvingDeletePropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
, bool* succeeded
)
751 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
752 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
753 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
755 if (ccx
.GetResolvingWrapper() == wrapper
) {
759 return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN
, cx
);
763 #define PRE_HELPER_STUB \
764 JSObject* unwrapped = js::CheckedUnwrap(obj, false); \
766 JS_ReportError(cx, "Permission denied to operate on object."); \
769 if (!IS_WN_REFLECTOR(unwrapped)) { \
770 return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx); \
772 XPCWrappedNative* wrapper = XPCWrappedNative::Get(unwrapped); \
773 THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper); \
774 bool retval = true; \
775 nsresult rv = wrapper->GetScriptableCallback()->
777 #define POST_HELPER_STUB \
779 return Throw(rv, cx); \
783 XPC_WN_Helper_AddProperty(JSContext
* cx
, HandleObject obj
, HandleId id
,
784 MutableHandleValue vp
)
787 AddProperty(wrapper
, cx
, obj
, id
, vp
.address(), &retval
);
792 XPC_WN_Helper_DelProperty(JSContext
* cx
, HandleObject obj
, HandleId id
,
797 DelProperty(wrapper
, cx
, obj
, id
, &retval
);
802 XPC_WN_Helper_GetProperty(JSContext
* cx
, HandleObject obj
, HandleId id
,
803 MutableHandleValue vp
)
806 GetProperty(wrapper
, cx
, obj
, id
, vp
.address(), &retval
);
811 XPC_WN_Helper_SetProperty(JSContext
* cx
, HandleObject obj
, HandleId id
, bool strict
,
812 MutableHandleValue vp
)
815 SetProperty(wrapper
, cx
, obj
, id
, vp
.address(), &retval
);
820 XPC_WN_Helper_Convert(JSContext
* cx
, HandleObject obj
, JSType type
, MutableHandleValue vp
)
823 Convert(wrapper
, cx
, obj
, type
, vp
.address(), &retval
);
828 XPC_WN_Helper_Call(JSContext
* cx
, unsigned argc
, jsval
* vp
)
830 JS::CallArgs args
= JS::CallArgsFromVp(argc
, vp
);
831 // N.B. we want obj to be the callee, not JS_THIS(cx, vp)
832 RootedObject
obj(cx
, &args
.callee());
834 XPCCallContext
ccx(JS_CALLER
, cx
, obj
, NullPtr(), JSID_VOIDHANDLE
, args
.length(),
835 args
.array(), args
.rval().address());
840 Call(wrapper
, cx
, obj
, args
, &retval
);
845 XPC_WN_Helper_Construct(JSContext
* cx
, unsigned argc
, jsval
* vp
)
847 JS::CallArgs args
= JS::CallArgsFromVp(argc
, vp
);
848 RootedObject
obj(cx
, &args
.callee());
852 XPCCallContext
ccx(JS_CALLER
, cx
, obj
, NullPtr(), JSID_VOIDHANDLE
, args
.length(),
853 args
.array(), args
.rval().address());
858 Construct(wrapper
, cx
, obj
, args
, &retval
);
863 XPC_WN_Helper_HasInstance(JSContext
* cx
, HandleObject obj
, MutableHandleValue valp
, bool* bp
)
867 HasInstance(wrapper
, cx
, obj
, valp
, &retval2
, &retval
);
873 XPC_WN_Helper_Finalize(js::FreeOp
* fop
, JSObject
* obj
)
875 WrappedNativeFinalize(fop
, obj
, WN_HELPER
);
879 XPC_WN_Helper_NewResolve(JSContext
* cx
, HandleObject obj
, HandleId id
,
880 MutableHandleObject objp
)
884 RootedObject
obj2FromScriptable(cx
);
885 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
886 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
887 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
889 RootedId
old(cx
, ccx
.SetResolveName(id
));
891 XPCNativeScriptableInfo
* si
= wrapper
->GetScriptableInfo();
892 if (si
&& si
->GetFlags().WantNewResolve()) {
893 XPCWrappedNative
* oldResolvingWrapper
;
894 bool allowPropMods
= si
->GetFlags().AllowPropModsDuringResolve();
897 oldResolvingWrapper
= ccx
.SetResolvingWrapper(wrapper
);
899 rv
= si
->GetCallback()->NewResolve(wrapper
, cx
, obj
, id
,
900 obj2FromScriptable
.address(), &retval
);
903 (void)ccx
.SetResolvingWrapper(oldResolvingWrapper
);
906 old
= ccx
.SetResolveName(old
);
907 MOZ_ASSERT(old
== id
, "bad nest");
910 return Throw(rv
, cx
);
913 if (obj2FromScriptable
) {
914 objp
.set(obj2FromScriptable
);
915 } else if (wrapper
->HasMutatedSet()) {
916 // We are here if scriptable did not resolve this property and
917 // it *might* be in the instance set but not the proto set.
919 XPCNativeSet
* set
= wrapper
->GetSet();
920 XPCNativeSet
* protoSet
= wrapper
->HasProto() ?
921 wrapper
->GetProto()->GetSet() : nullptr;
922 XPCNativeMember
* member
;
923 XPCNativeInterface
* iface
;
926 if (set
->FindMember(id
, &member
, &iface
, protoSet
, &IsLocal
) &&
928 XPCWrappedNative
* oldResolvingWrapper
;
930 XPCNativeScriptableFlags
siFlags(0);
932 siFlags
= si
->GetFlags();
935 siFlags
.DontEnumStaticProps() ? 0 : JSPROP_ENUMERATE
;
937 XPCWrappedNative
* wrapperForInterfaceNames
=
938 siFlags
.DontReflectInterfaceNames() ? nullptr : wrapper
;
941 oldResolvingWrapper
= ccx
.SetResolvingWrapper(wrapper
);
942 retval
= DefinePropertyIfFound(ccx
, obj
, id
,
946 wrapperForInterfaceNames
,
948 enumFlag
, &resolved
);
949 (void)ccx
.SetResolvingWrapper(oldResolvingWrapper
);
950 if (retval
&& resolved
)
958 /***************************************************************************/
961 Here are the enumerator cases:
963 set jsclass enumerate to stub (unless noted otherwise)
965 if ( helper wants new enumerate )
966 if ( DONT_ENUM_STATICS )
967 forward to scriptable enumerate
969 if ( set not mutated )
970 forward to scriptable enumerate
972 call shared enumerate
973 forward to scriptable enumerate
974 else if ( helper wants old enumerate )
976 if ( DONT_ENUM_STATICS )
977 call scriptable enumerate
980 if ( set not mutated )
981 call scriptable enumerate
984 call shared enumerate
985 call scriptable enumerate
988 else //... if ( helper wants NO enumerate )
989 if ( DONT_ENUM_STATICS )
990 use enumerate stub - don't use this JSOp thing at all
992 do shared enumerate - don't use this JSOp thing at all
996 XPC_WN_JSOp_Enumerate(JSContext
* cx
, HandleObject obj
, JSIterateOp enum_op
,
997 MutableHandleValue statep
, MutableHandleId idp
)
999 const js::Class
* clazz
= js::GetObjectClass(obj
);
1000 if (!IS_WN_CLASS(clazz
) || clazz
== &XPC_WN_NoHelper_JSClass
.base
) {
1001 // obj must be a prototype object or a wrapper w/o a
1002 // helper. Short circuit this call to the default
1005 return JS_EnumerateState(cx
, obj
, enum_op
, statep
, idp
);
1008 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
1009 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
1010 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
1012 XPCNativeScriptableInfo
* si
= wrapper
->GetScriptableInfo();
1014 return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO
, cx
);
1019 if (si
->GetFlags().WantNewEnumerate()) {
1020 if (((enum_op
== JSENUMERATE_INIT
&&
1021 !si
->GetFlags().DontEnumStaticProps()) ||
1022 enum_op
== JSENUMERATE_INIT_ALL
) &&
1023 wrapper
->HasMutatedSet() &&
1024 !XPC_WN_Shared_Enumerate(cx
, obj
)) {
1025 statep
.set(JSVAL_NULL
);
1029 // XXX Might we really need to wrap this call and *also* call
1030 // js_ObjectOps.enumerate ???
1032 rv
= si
->GetCallback()->
1033 NewEnumerate(wrapper
, cx
, obj
, enum_op
, statep
.address(), idp
.address(), &retval
);
1035 if ((enum_op
== JSENUMERATE_INIT
|| enum_op
== JSENUMERATE_INIT_ALL
) &&
1036 (NS_FAILED(rv
) || !retval
)) {
1037 statep
.set(JSVAL_NULL
);
1041 return Throw(rv
, cx
);
1045 if (si
->GetFlags().WantEnumerate()) {
1046 if (enum_op
== JSENUMERATE_INIT
|| enum_op
== JSENUMERATE_INIT_ALL
) {
1047 if ((enum_op
== JSENUMERATE_INIT_ALL
||
1048 !si
->GetFlags().DontEnumStaticProps()) &&
1049 wrapper
->HasMutatedSet() &&
1050 !XPC_WN_Shared_Enumerate(cx
, obj
)) {
1051 statep
.set(JSVAL_NULL
);
1054 rv
= si
->GetCallback()->
1055 Enumerate(wrapper
, cx
, obj
, &retval
);
1057 if (NS_FAILED(rv
) || !retval
)
1058 statep
.set(JSVAL_NULL
);
1061 return Throw(rv
, cx
);
1064 // Then fall through and call the default implementation...
1068 // else call js_ObjectOps.enumerate...
1070 return JS_EnumerateState(cx
, obj
, enum_op
, statep
, idp
);
1074 XPC_WN_JSOp_ThisObject(JSContext
* cx
, HandleObject obj
)
1076 return JS_ObjectToOuterObject(cx
, obj
);
1079 /***************************************************************************/
1082 XPCNativeScriptableInfo
*
1083 XPCNativeScriptableInfo::Construct(const XPCNativeScriptableCreateInfo
* sci
)
1085 MOZ_ASSERT(sci
, "bad param");
1086 MOZ_ASSERT(sci
->GetCallback(), "bad param");
1088 XPCNativeScriptableInfo
* newObj
=
1089 new XPCNativeScriptableInfo(sci
->GetCallback());
1093 char* name
= nullptr;
1094 if (NS_FAILED(sci
->GetCallback()->GetClassName(&name
)) || !name
) {
1101 XPCJSRuntime
* rt
= XPCJSRuntime::Get();
1102 XPCNativeScriptableSharedMap
* map
= rt
->GetNativeScriptableSharedMap();
1103 success
= map
->GetNewOrUsed(sci
->GetFlags(), name
,
1104 sci
->GetInterfacesBitmap(), newObj
);
1115 XPCNativeScriptableShared::PopulateJSClass()
1117 MOZ_ASSERT(mJSClass
.base
.name
, "bad state!");
1119 mJSClass
.base
.flags
= WRAPPER_SLOTS
|
1120 JSCLASS_PRIVATE_IS_NSISUPPORTS
|
1121 JSCLASS_NEW_RESOLVE
;
1123 if (mFlags
.IsGlobalObject())
1124 mJSClass
.base
.flags
|= XPCONNECT_GLOBAL_FLAGS
;
1126 JSPropertyOp addProperty
;
1127 if (mFlags
.WantAddProperty())
1128 addProperty
= XPC_WN_Helper_AddProperty
;
1129 else if (mFlags
.UseJSStubForAddProperty())
1130 addProperty
= JS_PropertyStub
;
1131 else if (mFlags
.AllowPropModsDuringResolve())
1132 addProperty
= XPC_WN_MaybeResolvingPropertyStub
;
1134 addProperty
= XPC_WN_CannotModifyPropertyStub
;
1135 mJSClass
.base
.addProperty
= addProperty
;
1137 JSDeletePropertyOp delProperty
;
1138 if (mFlags
.WantDelProperty())
1139 delProperty
= XPC_WN_Helper_DelProperty
;
1140 else if (mFlags
.UseJSStubForDelProperty())
1141 delProperty
= JS_DeletePropertyStub
;
1142 else if (mFlags
.AllowPropModsDuringResolve())
1143 delProperty
= XPC_WN_MaybeResolvingDeletePropertyStub
;
1145 delProperty
= XPC_WN_CantDeletePropertyStub
;
1146 mJSClass
.base
.delProperty
= delProperty
;
1148 if (mFlags
.WantGetProperty())
1149 mJSClass
.base
.getProperty
= XPC_WN_Helper_GetProperty
;
1151 mJSClass
.base
.getProperty
= JS_PropertyStub
;
1153 JSStrictPropertyOp setProperty
;
1154 if (mFlags
.WantSetProperty())
1155 setProperty
= XPC_WN_Helper_SetProperty
;
1156 else if (mFlags
.UseJSStubForSetProperty())
1157 setProperty
= JS_StrictPropertyStub
;
1158 else if (mFlags
.AllowPropModsDuringResolve())
1159 setProperty
= XPC_WN_MaybeResolvingStrictPropertyStub
;
1161 setProperty
= XPC_WN_CannotModifyStrictPropertyStub
;
1162 mJSClass
.base
.setProperty
= setProperty
;
1164 // We figure out most of the enumerate strategy at call time.
1166 if (mFlags
.WantNewEnumerate() || mFlags
.WantEnumerate() ||
1167 mFlags
.DontEnumStaticProps())
1168 mJSClass
.base
.enumerate
= JS_EnumerateStub
;
1170 mJSClass
.base
.enumerate
= XPC_WN_Shared_Enumerate
;
1172 // We have to figure out resolve strategy at call time
1173 mJSClass
.base
.resolve
= (JSResolveOp
) XPC_WN_Helper_NewResolve
;
1175 // We need to respect content-defined toString() hooks on Window objects.
1176 // In particular, js::DefaultValue checks for a convert stub, and the one
1177 // we would install below ignores anything implemented in JS.
1179 // We've always had this behavior for most XPCWrappedNative-implemented
1180 // objects. However, Window was special, because the outer-window proxy
1181 // had a null convert hook, which means that we'd end up with the default
1182 // JS-engine behavior (which respects toString() overrides). We've fixed
1183 // the convert hook on the outer-window proxy to invoke the defaultValue
1184 // hook on the proxy, which in this case invokes js::DefaultValue on the
1185 // target. So now we need to special-case this for Window to maintain
1186 // consistent behavior. This can go away once Window is on WebIDL bindings.
1188 // Note that WantOuterObject() is true if and only if this is a Window object.
1189 if (mFlags
.WantConvert())
1190 mJSClass
.base
.convert
= XPC_WN_Helper_Convert
;
1191 else if (mFlags
.WantOuterObject())
1192 mJSClass
.base
.convert
= JS_ConvertStub
;
1194 mJSClass
.base
.convert
= XPC_WN_Shared_Convert
;
1196 if (mFlags
.WantFinalize())
1197 mJSClass
.base
.finalize
= XPC_WN_Helper_Finalize
;
1199 mJSClass
.base
.finalize
= XPC_WN_NoHelper_Finalize
;
1201 js::ObjectOps
* ops
= &mJSClass
.base
.ops
;
1202 ops
->enumerate
= XPC_WN_JSOp_Enumerate
;
1203 ops
->thisObject
= XPC_WN_JSOp_ThisObject
;
1206 if (mFlags
.WantCall())
1207 mJSClass
.base
.call
= XPC_WN_Helper_Call
;
1208 if (mFlags
.WantConstruct())
1209 mJSClass
.base
.construct
= XPC_WN_Helper_Construct
;
1211 if (mFlags
.WantHasInstance())
1212 mJSClass
.base
.hasInstance
= XPC_WN_Helper_HasInstance
;
1214 if (mFlags
.IsGlobalObject())
1215 mJSClass
.base
.trace
= JS_GlobalObjectTraceHook
;
1217 mJSClass
.base
.trace
= XPCWrappedNative::Trace
;
1219 if (mFlags
.WantOuterObject())
1220 mJSClass
.base
.ext
.outerObject
= XPC_WN_OuterObject
;
1222 mJSClass
.base
.ext
.isWrappedNative
= true;
1225 /***************************************************************************/
1226 /***************************************************************************/
1228 // Compatibility hack.
1230 // XPConnect used to do all sorts of funny tricks to find the "correct"
1231 // |this| object for a given method (often to the detriment of proper
1232 // call/apply). When these tricks were removed, a fair amount of chrome
1233 // code broke, because it was relying on being able to grab methods off
1234 // some XPCOM object (like the nsITelemetry service) and invoke them without
1235 // a proper |this|. So, if it's quite clear that we're in this situation and
1236 // about to use a |this| argument that just won't work, fix things up.
1238 // This hack is only useful for getters/setters if someone sets an XPCOM object
1239 // as the prototype for a vanilla JS object and expects the XPCOM attributes to
1240 // work on the derived object, which we really don't want to support. But we
1241 // handle it anyway, for now, to minimize regression risk on an already-risky
1244 // This hack is mainly useful for the NoHelper JSClass. We also fix up
1245 // Components.utils because it implements nsIXPCScriptable (giving it a custom
1246 // JSClass) but not nsIClassInfo (which would put the methods on a prototype).
1248 #define IS_NOHELPER_CLASS(clasp) (clasp == &XPC_WN_NoHelper_JSClass.base)
1249 #define IS_CU_CLASS(clasp) (clasp->name[0] == 'n' && !strcmp(clasp->name, "nsXPCComponents_Utils"))
1251 MOZ_ALWAYS_INLINE JSObject
*
1252 FixUpThisIfBroken(JSObject
* obj
, JSObject
* funobj
)
1255 const js::Class
* parentClass
= js::GetObjectClass(js::GetObjectParent(funobj
));
1256 if (MOZ_UNLIKELY((IS_NOHELPER_CLASS(parentClass
) || IS_CU_CLASS(parentClass
)) &&
1257 (js::GetObjectClass(obj
) != parentClass
)))
1259 return js::GetObjectParent(funobj
);
1266 XPC_WN_CallMethod(JSContext
* cx
, unsigned argc
, jsval
* vp
)
1268 JS::CallArgs args
= JS::CallArgsFromVp(argc
, vp
);
1269 MOZ_ASSERT(JS_TypeOfValue(cx
, args
.calleev()) == JSTYPE_FUNCTION
, "bad function");
1270 RootedObject
funobj(cx
, &args
.callee());
1272 RootedObject
obj(cx
, JS_THIS_OBJECT(cx
, vp
));
1276 obj
= FixUpThisIfBroken(obj
, funobj
);
1277 XPCCallContext
ccx(JS_CALLER
, cx
, obj
, funobj
, JSID_VOIDHANDLE
, args
.length(),
1279 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
1280 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
1282 XPCNativeInterface
* iface
;
1283 XPCNativeMember
* member
;
1285 if (!XPCNativeMember::GetCallInfo(funobj
, &iface
, &member
))
1286 return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO
, cx
);
1287 ccx
.SetCallInfo(iface
, member
, false);
1288 return XPCWrappedNative::CallMethod(ccx
);
1292 XPC_WN_GetterSetter(JSContext
* cx
, unsigned argc
, jsval
* vp
)
1294 JS::CallArgs args
= JS::CallArgsFromVp(argc
, vp
);
1295 MOZ_ASSERT(JS_TypeOfValue(cx
, args
.calleev()) == JSTYPE_FUNCTION
, "bad function");
1296 RootedObject
funobj(cx
, &args
.callee());
1298 RootedObject
obj(cx
, JS_THIS_OBJECT(cx
, vp
));
1302 obj
= FixUpThisIfBroken(obj
, funobj
);
1303 XPCCallContext
ccx(JS_CALLER
, cx
, obj
, funobj
, JSID_VOIDHANDLE
, args
.length(),
1305 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
1306 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
1308 XPCNativeInterface
* iface
;
1309 XPCNativeMember
* member
;
1311 if (!XPCNativeMember::GetCallInfo(funobj
, &iface
, &member
))
1312 return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO
, cx
);
1314 if (args
.length() != 0 && member
->IsWritableAttribute()) {
1315 ccx
.SetCallInfo(iface
, member
, true);
1316 bool retval
= XPCWrappedNative::SetAttribute(ccx
);
1318 args
.rval().set(args
[0]);
1323 ccx
.SetCallInfo(iface
, member
, false);
1324 return XPCWrappedNative::GetAttribute(ccx
);
1327 /***************************************************************************/
1330 XPC_WN_Shared_Proto_Enumerate(JSContext
* cx
, HandleObject obj
)
1332 MOZ_ASSERT(js::GetObjectClass(obj
) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass
||
1333 js::GetObjectClass(obj
) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass
||
1334 js::GetObjectClass(obj
) == &XPC_WN_NoMods_WithCall_Proto_JSClass
||
1335 js::GetObjectClass(obj
) == &XPC_WN_NoMods_NoCall_Proto_JSClass
,
1337 XPCWrappedNativeProto
* self
=
1338 (XPCWrappedNativeProto
*) xpc_GetJSPrivate(obj
);
1342 if (self
->GetScriptableInfo() &&
1343 self
->GetScriptableInfo()->GetFlags().DontEnumStaticProps())
1346 XPCNativeSet
* set
= self
->GetSet();
1350 XPCCallContext
ccx(JS_CALLER
, cx
);
1354 uint16_t interface_count
= set
->GetInterfaceCount();
1355 XPCNativeInterface
** interfaceArray
= set
->GetInterfaceArray();
1356 for (uint16_t i
= 0; i
< interface_count
; i
++) {
1357 XPCNativeInterface
* iface
= interfaceArray
[i
];
1358 uint16_t member_count
= iface
->GetMemberCount();
1360 for (uint16_t k
= 0; k
< member_count
; k
++) {
1361 if (!xpc_ForcePropertyResolve(cx
, obj
, iface
->GetMemberAt(k
)->GetName()))
1370 XPC_WN_Shared_Proto_Finalize(js::FreeOp
* fop
, JSObject
* obj
)
1372 // This can be null if xpc shutdown has already happened
1373 XPCWrappedNativeProto
* p
= (XPCWrappedNativeProto
*) xpc_GetJSPrivate(obj
);
1375 p
->JSProtoObjectFinalized(fop
, obj
);
1379 XPC_WN_Shared_Proto_Trace(JSTracer
* trc
, JSObject
* obj
)
1381 // This can be null if xpc shutdown has already happened
1382 XPCWrappedNativeProto
* p
=
1383 (XPCWrappedNativeProto
*) xpc_GetJSPrivate(obj
);
1385 p
->TraceInside(trc
);
1388 /*****************************************************/
1391 XPC_WN_ModsAllowed_Proto_Resolve(JSContext
* cx
, HandleObject obj
, HandleId id
)
1393 MOZ_ASSERT(js::GetObjectClass(obj
) == &XPC_WN_ModsAllowed_WithCall_Proto_JSClass
||
1394 js::GetObjectClass(obj
) == &XPC_WN_ModsAllowed_NoCall_Proto_JSClass
,
1397 XPCWrappedNativeProto
* self
=
1398 (XPCWrappedNativeProto
*) xpc_GetJSPrivate(obj
);
1402 XPCCallContext
ccx(JS_CALLER
, cx
);
1406 XPCNativeScriptableInfo
* si
= self
->GetScriptableInfo();
1407 unsigned enumFlag
= (si
&& si
->GetFlags().DontEnumStaticProps()) ?
1408 0 : JSPROP_ENUMERATE
;
1410 return DefinePropertyIfFound(ccx
, obj
, id
,
1411 self
->GetSet(), nullptr, nullptr,
1413 true, nullptr, nullptr, si
,
1417 const js::Class XPC_WN_ModsAllowed_WithCall_Proto_JSClass
= {
1418 "XPC_WN_ModsAllowed_WithCall_Proto_JSClass", // name;
1419 WRAPPER_SLOTS
, // flags;
1421 /* Mandatory non-null function pointer members. */
1422 JS_PropertyStub
, // addProperty;
1423 JS_DeletePropertyStub
, // delProperty;
1424 JS_PropertyStub
, // getProperty;
1425 JS_StrictPropertyStub
, // setProperty;
1426 XPC_WN_Shared_Proto_Enumerate
, // enumerate;
1427 XPC_WN_ModsAllowed_Proto_Resolve
, // resolve;
1428 JS_ConvertStub
, // convert;
1429 XPC_WN_Shared_Proto_Finalize
, // finalize;
1431 /* Optionally non-null members start here. */
1433 nullptr, // construct;
1434 nullptr, // hasInstance;
1435 XPC_WN_Shared_Proto_Trace
, // trace;
1439 XPC_WN_WithCall_ObjectOps
1442 const js::Class XPC_WN_ModsAllowed_NoCall_Proto_JSClass
= {
1443 "XPC_WN_ModsAllowed_NoCall_Proto_JSClass", // name;
1444 WRAPPER_SLOTS
, // flags;
1446 /* Mandatory non-null function pointer members. */
1447 JS_PropertyStub
, // addProperty;
1448 JS_DeletePropertyStub
, // delProperty;
1449 JS_PropertyStub
, // getProperty;
1450 JS_StrictPropertyStub
, // setProperty;
1451 XPC_WN_Shared_Proto_Enumerate
, // enumerate;
1452 XPC_WN_ModsAllowed_Proto_Resolve
, // resolve;
1453 JS_ConvertStub
, // convert;
1454 XPC_WN_Shared_Proto_Finalize
, // finalize;
1456 /* Optionally non-null members start here. */
1458 nullptr, // construct;
1459 nullptr, // hasInstance;
1460 XPC_WN_Shared_Proto_Trace
, // trace;
1464 XPC_WN_NoCall_ObjectOps
1467 /***************************************************************************/
1470 XPC_WN_OnlyIWrite_Proto_AddPropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
,
1471 MutableHandleValue vp
)
1473 MOZ_ASSERT(js::GetObjectClass(obj
) == &XPC_WN_NoMods_WithCall_Proto_JSClass
||
1474 js::GetObjectClass(obj
) == &XPC_WN_NoMods_NoCall_Proto_JSClass
,
1477 XPCWrappedNativeProto
* self
=
1478 (XPCWrappedNativeProto
*) xpc_GetJSPrivate(obj
);
1482 XPCCallContext
ccx(JS_CALLER
, cx
);
1486 // Allow XPConnect to add the property only
1487 if (ccx
.GetResolveName() == id
)
1490 return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO
, cx
);
1494 XPC_WN_OnlyIWrite_Proto_SetPropertyStub(JSContext
* cx
, HandleObject obj
, HandleId id
, bool strict
,
1495 MutableHandleValue vp
)
1497 return XPC_WN_OnlyIWrite_Proto_AddPropertyStub(cx
, obj
, id
, vp
);
1501 XPC_WN_NoMods_Proto_Resolve(JSContext
* cx
, HandleObject obj
, HandleId id
)
1503 MOZ_ASSERT(js::GetObjectClass(obj
) == &XPC_WN_NoMods_WithCall_Proto_JSClass
||
1504 js::GetObjectClass(obj
) == &XPC_WN_NoMods_NoCall_Proto_JSClass
,
1507 XPCWrappedNativeProto
* self
=
1508 (XPCWrappedNativeProto
*) xpc_GetJSPrivate(obj
);
1512 XPCCallContext
ccx(JS_CALLER
, cx
);
1516 XPCNativeScriptableInfo
* si
= self
->GetScriptableInfo();
1517 unsigned enumFlag
= (si
&& si
->GetFlags().DontEnumStaticProps()) ?
1518 0 : JSPROP_ENUMERATE
;
1520 return DefinePropertyIfFound(ccx
, obj
, id
,
1521 self
->GetSet(), nullptr, nullptr,
1523 true, nullptr, nullptr, si
,
1529 const js::Class XPC_WN_NoMods_WithCall_Proto_JSClass
= {
1530 "XPC_WN_NoMods_WithCall_Proto_JSClass", // name;
1531 WRAPPER_SLOTS
, // flags;
1533 /* Mandatory non-null function pointer members. */
1534 XPC_WN_OnlyIWrite_Proto_AddPropertyStub
, // addProperty;
1535 XPC_WN_CantDeletePropertyStub
, // delProperty;
1536 JS_PropertyStub
, // getProperty;
1537 XPC_WN_OnlyIWrite_Proto_SetPropertyStub
, // setProperty;
1538 XPC_WN_Shared_Proto_Enumerate
, // enumerate;
1539 XPC_WN_NoMods_Proto_Resolve
, // resolve;
1540 JS_ConvertStub
, // convert;
1541 XPC_WN_Shared_Proto_Finalize
, // finalize;
1543 /* Optionally non-null members start here. */
1545 nullptr, // construct;
1546 nullptr, // hasInstance;
1547 XPC_WN_Shared_Proto_Trace
, // trace;
1551 XPC_WN_WithCall_ObjectOps
1554 const js::Class XPC_WN_NoMods_NoCall_Proto_JSClass
= {
1555 "XPC_WN_NoMods_NoCall_Proto_JSClass", // name;
1556 WRAPPER_SLOTS
, // flags;
1558 /* Mandatory non-null function pointer members. */
1559 XPC_WN_OnlyIWrite_Proto_AddPropertyStub
, // addProperty;
1560 XPC_WN_CantDeletePropertyStub
, // delProperty;
1561 JS_PropertyStub
, // getProperty;
1562 XPC_WN_OnlyIWrite_Proto_SetPropertyStub
, // setProperty;
1563 XPC_WN_Shared_Proto_Enumerate
, // enumerate;
1564 XPC_WN_NoMods_Proto_Resolve
, // resolve;
1565 JS_ConvertStub
, // convert;
1566 XPC_WN_Shared_Proto_Finalize
, // finalize;
1568 /* Optionally non-null members start here. */
1570 nullptr, // construct;
1571 nullptr, // hasInstance;
1572 XPC_WN_Shared_Proto_Trace
, // trace;
1576 XPC_WN_NoCall_ObjectOps
1579 /***************************************************************************/
1582 XPC_WN_TearOff_Enumerate(JSContext
* cx
, HandleObject obj
)
1584 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
1585 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
1586 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
1588 XPCWrappedNativeTearOff
* to
= ccx
.GetTearOff();
1589 XPCNativeInterface
* iface
;
1591 if (!to
|| nullptr == (iface
= to
->GetInterface()))
1592 return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO
, cx
);
1594 uint16_t member_count
= iface
->GetMemberCount();
1595 for (uint16_t k
= 0; k
< member_count
; k
++) {
1596 if (!xpc_ForcePropertyResolve(cx
, obj
, iface
->GetMemberAt(k
)->GetName()))
1604 XPC_WN_TearOff_Resolve(JSContext
* cx
, HandleObject obj
, HandleId id
)
1606 XPCCallContext
ccx(JS_CALLER
, cx
, obj
);
1607 XPCWrappedNative
* wrapper
= ccx
.GetWrapper();
1608 THROW_AND_RETURN_IF_BAD_WRAPPER(cx
, wrapper
);
1610 XPCWrappedNativeTearOff
* to
= ccx
.GetTearOff();
1611 XPCNativeInterface
* iface
;
1613 if (!to
|| nullptr == (iface
= to
->GetInterface()))
1614 return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO
, cx
);
1616 return DefinePropertyIfFound(ccx
, obj
, id
, nullptr, iface
, nullptr,
1617 wrapper
->GetScope(),
1618 true, nullptr, nullptr, nullptr,
1621 JSPROP_ENUMERATE
, nullptr);
1625 XPC_WN_TearOff_Finalize(js::FreeOp
* fop
, JSObject
* obj
)
1627 XPCWrappedNativeTearOff
* p
= (XPCWrappedNativeTearOff
*)
1628 xpc_GetJSPrivate(obj
);
1631 p
->JSObjectFinalized();
1634 const js::Class XPC_WN_Tearoff_JSClass
= {
1635 "WrappedNative_TearOff", // name;
1636 WRAPPER_SLOTS
, // flags;
1638 XPC_WN_OnlyIWrite_AddPropertyStub
, // addProperty;
1639 XPC_WN_CantDeletePropertyStub
, // delProperty;
1640 JS_PropertyStub
, // getProperty;
1641 XPC_WN_OnlyIWrite_SetPropertyStub
, // setProperty;
1642 XPC_WN_TearOff_Enumerate
, // enumerate;
1643 XPC_WN_TearOff_Resolve
, // resolve;
1644 XPC_WN_Shared_Convert
, // convert;
1645 XPC_WN_TearOff_Finalize
// finalize;