NS_IMETHODIMP nsJSCID::Construct(nsIXPConnectWrappedNative* wrapper, JSContext* cx, JSObject* objArg, const CallArgs& args, bool* _retval) { RootedObject obj(cx, objArg); XPCJSContext* xpccx = nsXPConnect::GetContextInstance(); if (!xpccx) return NS_ERROR_FAILURE; // 'push' a call context and call on it RootedId name(cx, xpccx->GetStringID(XPCJSContext::IDX_CREATE_INSTANCE)); XPCCallContext ccx(cx, obj, nullptr, name, args.length(), args.array(), args.rval().address()); *_retval = XPCWrappedNative::CallMethod(ccx); return NS_OK; }
static bool DefinePropertyIfFound(XPCCallContext& ccx, HandleObject obj, HandleId idArg, XPCNativeSet* set, XPCNativeInterface* ifaceArg, XPCNativeMember* member, XPCWrappedNativeScope* scope, bool reflectToStringAndToSource, XPCWrappedNative* wrapperToReflectInterfaceNames, XPCWrappedNative* wrapperToReflectDoubleWrap, XPCNativeScriptableInfo* scriptableInfo, unsigned propFlags, bool* resolved) { RootedId id(ccx, idArg); RefPtr<XPCNativeInterface> iface = ifaceArg; XPCJSContext* xpccx = ccx.GetContext(); bool found; const char* name; propFlags |= JSPROP_RESOLVING; if (set) { if (iface) found = true; else found = set->FindMember(id, &member, &iface); } else found = (nullptr != (member = iface->FindMember(id))); if (!found) { if (reflectToStringAndToSource) { JSNative call; uint32_t flags = 0; if (scriptableInfo) { nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface( scriptableInfo->GetCallback()); if (classInfo) { nsresult rv = classInfo->GetFlags(&flags); if (NS_FAILED(rv)) return Throw(rv, ccx); } } bool overwriteToString = !(flags & nsIClassInfo::DOM_OBJECT) || Preferences::GetBool("dom.XPCToStringForDOMClasses", false); if(id == xpccx->GetStringID(XPCJSContext::IDX_TO_STRING) && overwriteToString) { call = XPC_WN_Shared_ToString; name = xpccx->GetStringName(XPCJSContext::IDX_TO_STRING); } else if (id == xpccx->GetStringID(XPCJSContext::IDX_TO_SOURCE)) { call = XPC_WN_Shared_ToSource; name = xpccx->GetStringName(XPCJSContext::IDX_TO_SOURCE); } else if (id == SYMBOL_TO_JSID( JS::GetWellKnownSymbol(ccx, JS::SymbolCode::toPrimitive))) { call = XPC_WN_Shared_toPrimitive; name = "[Symbol.toPrimitive]"; } else { call = nullptr; } if (call) { RootedFunction fun(ccx, JS_NewFunction(ccx, call, 0, 0, name)); if (!fun) { JS_ReportOutOfMemory(ccx); return false; } AutoResolveName arn(ccx, id); if (resolved) *resolved = true; RootedObject value(ccx, JS_GetFunctionObject(fun)); return JS_DefinePropertyById(ccx, obj, id, value, propFlags & ~JSPROP_ENUMERATE); } } // This *might* be a tearoff name that is not yet part of our // set. Let's lookup the name and see if it is the name of an // interface. Then we'll see if the object actually *does* this // interface and add a tearoff as necessary. if (wrapperToReflectInterfaceNames) { JSAutoByteString name; RefPtr<XPCNativeInterface> iface2; XPCWrappedNativeTearOff* to; RootedObject jso(ccx); nsresult rv = NS_OK; if (JSID_IS_STRING(id) && name.encodeLatin1(ccx, JSID_TO_STRING(id)) && (iface2 = XPCNativeInterface::GetNewOrUsed(name.ptr()), iface2) && nullptr != (to = wrapperToReflectInterfaceNames-> FindTearOff(iface2, true, &rv)) && nullptr != (jso = to->GetJSObject())) { AutoResolveName arn(ccx, id); if (resolved) *resolved = true; return JS_DefinePropertyById(ccx, obj, id, jso, propFlags & ~JSPROP_ENUMERATE); } else if (NS_FAILED(rv) && rv != NS_ERROR_NO_INTERFACE) { return Throw(rv, ccx); } } // This *might* be a double wrapped JSObject if (wrapperToReflectDoubleWrap && id == xpccx->GetStringID(XPCJSContext::IDX_WRAPPED_JSOBJECT) && GetDoubleWrappedJSObject(ccx, wrapperToReflectDoubleWrap)) { // We build and add a getter function. // A security check is done on a per-get basis. JSFunction* fun; id = xpccx->GetStringID(XPCJSContext::IDX_WRAPPED_JSOBJECT); name = xpccx->GetStringName(XPCJSContext::IDX_WRAPPED_JSOBJECT); fun = JS_NewFunction(ccx, XPC_WN_DoubleWrappedGetter, 0, 0, name); if (!fun) return false; RootedObject funobj(ccx, JS_GetFunctionObject(fun)); if (!funobj) return false; propFlags |= JSPROP_GETTER | JSPROP_SHARED; propFlags &= ~JSPROP_ENUMERATE; AutoResolveName arn(ccx, id); if (resolved) *resolved = true; return JS_DefinePropertyById(ccx, obj, id, UndefinedHandleValue, propFlags, JS_DATA_TO_FUNC_PTR(JSNative, funobj.get()), nullptr); } if (resolved) *resolved = false; return true; } if (!member) { if (wrapperToReflectInterfaceNames) { XPCWrappedNativeTearOff* to = wrapperToReflectInterfaceNames->FindTearOff(iface, true); if (!to) return false; RootedObject jso(ccx, to->GetJSObject()); if (!jso) return false; AutoResolveName arn(ccx, id); if (resolved) *resolved = true; return JS_DefinePropertyById(ccx, obj, id, jso, propFlags & ~JSPROP_ENUMERATE); } if (resolved) *resolved = false; return true; } if (member->IsConstant()) { RootedValue val(ccx); AutoResolveName arn(ccx, id); if (resolved) *resolved = true; return member->GetConstantValue(ccx, iface, val.address()) && JS_DefinePropertyById(ccx, obj, id, val, propFlags); } if (scope->HasInterposition()) { Rooted<PropertyDescriptor> desc(ccx); if (!xpc::InterposeProperty(ccx, obj, iface->GetIID(), id, &desc)) return false; if (desc.object()) { AutoResolveName arn(ccx, id); if (resolved) *resolved = true; desc.attributesRef() |= JSPROP_RESOLVING; return JS_DefinePropertyById(ccx, obj, id, desc); } } if (id == xpccx->GetStringID(XPCJSContext::IDX_TO_STRING) || id == xpccx->GetStringID(XPCJSContext::IDX_TO_SOURCE) || (scriptableInfo && scriptableInfo->GetFlags().DontEnumQueryInterface() && id == xpccx->GetStringID(XPCJSContext::IDX_QUERY_INTERFACE))) propFlags &= ~JSPROP_ENUMERATE; RootedValue funval(ccx); if (!member->NewFunctionObject(ccx, iface, obj, funval.address())) return false; if (member->IsMethod()) { AutoResolveName arn(ccx, id); if (resolved) *resolved = true; return JS_DefinePropertyById(ccx, obj, id, funval, propFlags); } // else... MOZ_ASSERT(member->IsAttribute(), "way broken!"); propFlags |= JSPROP_GETTER | JSPROP_SHARED; propFlags &= ~JSPROP_READONLY; JSObject* funobj = funval.toObjectOrNull(); JSNative getter = JS_DATA_TO_FUNC_PTR(JSNative, funobj); JSNative setter; if (member->IsWritableAttribute()) { propFlags |= JSPROP_SETTER; setter = JS_DATA_TO_FUNC_PTR(JSNative, funobj); } else { setter = nullptr; } AutoResolveName arn(ccx, id); if (resolved) *resolved = true; return JS_DefinePropertyById(ccx, obj, id, UndefinedHandleValue, propFlags, getter, setter); }