bool WrapperAnswer::RecvGetOwnPropertyDescriptor(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs, PPropertyDescriptor* out) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); EmptyDesc(out); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("%s.getOwnPropertyDescriptor(%s)", ReceiverObj(objId), Identifier(idVar)); RootedId id(cx); if (!fromJSIDVariant(cx, idVar, &id)) return fail(jsapi, rs); Rooted<PropertyDescriptor> desc(cx); if (!JS_GetOwnPropertyDescriptorById(cx, obj, id, &desc)) return fail(jsapi, rs); if (!fromDescriptor(cx, desc, out)) return fail(jsapi, rs); return ok(rs); }
bool WrapperAnswer::RecvRegExpToShared(const ObjectId& objId, ReturnStatus* rs, nsString* source, uint32_t* flags) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); RootedString sourceJSStr(cx, JS_GetRegExpSource(cx, obj)); if (!sourceJSStr) return fail(jsapi, rs); nsAutoJSString sourceStr; if (!sourceStr.init(cx, sourceJSStr)) return fail(jsapi, rs); source->Assign(sourceStr); *flags = JS_GetRegExpFlags(cx, obj); return ok(rs); }
bool WrapperAnswer::RecvIsArray(const ObjectId& objId, ReturnStatus* rs, uint32_t* ans) { *ans = uint32_t(IsArrayAnswer::NotArray); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("%s.isArray()", ReceiverObj(objId)); IsArrayAnswer answer; if (!JS::IsArray(cx, obj, &answer)) return fail(jsapi, rs); *ans = uint32_t(answer); return ok(rs); }
nsresult MediaKeyStatusMap::UpdateInternal(const nsTArray<CDMCaps::KeyStatus>& keys) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mParent))) { return NS_ERROR_FAILURE; } jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> map(cx, mMap); if (!JS::MapClear(cx, map)) { return NS_ERROR_FAILURE; } for (size_t i = 0; i < keys.Length(); i++) { const auto& ks = keys[i]; JS::Rooted<JS::Value> key(cx); JS::Rooted<JS::Value> val(cx); if (!ToJSValue(cx, TypedArrayCreator<ArrayBuffer>(ks.mId), &key) || !ToJSString(cx, ks.mStatus, &val) || !JS::MapSet(cx, map, key, val)) { return NS_ERROR_OUT_OF_MEMORY; } } return NS_OK; }
bool WrapperAnswer::RecvInstanceOf(const ObjectId& objId, const JSIID& iid, ReturnStatus* rs, bool* instanceof) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); *instanceof = false; RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("%s.instanceOf()", ReceiverObj(objId)); nsID nsiid; ConvertID(iid, &nsiid); nsresult rv = xpc::HasInstance(cx, obj, &nsiid, instanceof); if (rv != NS_OK) return fail(jsapi, rs); return ok(rs); }
bool WrapperAnswer::RecvGetBuiltinClass(const ObjectId& objId, ReturnStatus* rs, uint32_t* classValue) { *classValue = js::ESClass_Other; AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("%s.getBuiltinClass()", ReceiverObj(objId)); js::ESClassValue cls; if (!js::GetBuiltinClass(cx, obj, &cls)) return fail(jsapi, rs); *classValue = cls; return ok(rs); }
nsresult nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding) { // We want to pre-compile our implementation's members against a "prototype context". Then when we actually // bind the prototype to a real xbl instance, we'll clone the pre-compiled JS into the real instance's // context. AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(xpc::CompilationScope()))) return NS_ERROR_FAILURE; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); mPrecompiledMemberHolder = JS_NewObjectWithGivenProto(cx, nullptr, nullptr); if (!mPrecompiledMemberHolder) return NS_ERROR_OUT_OF_MEMORY; // Now that we have a class object installed, we walk our member list and compile each of our // properties and methods in turn. JS::Rooted<JSObject*> rootedHolder(cx, mPrecompiledMemberHolder); for (nsXBLProtoImplMember* curr = mMembers; curr; curr = curr->GetNext()) { nsresult rv = curr->CompileMember(jsapi, mClassName, rootedHolder); if (NS_FAILED(rv)) { DestroyMembers(); return rv; } } return NS_OK; }
bool WrapperAnswer::RecvHasOwn(const ObjectId& objId, const JSIDVariant& idVar, ReturnStatus* rs, bool* foundp) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); *foundp = false; RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("%s.hasOwn(%s)", ReceiverObj(objId), Identifier(idVar)); RootedId id(cx); if (!fromJSIDVariant(cx, idVar, &id)) return fail(jsapi, rs); if (!JS_HasOwnPropertyById(cx, obj, id, foundp)) return fail(jsapi, rs); return ok(rs); }
bool WrapperAnswer::RecvDefineProperty(const ObjectId& objId, const JSIDVariant& idVar, const PPropertyDescriptor& descriptor, ReturnStatus* rs) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("define %s[%s]", ReceiverObj(objId), Identifier(idVar)); RootedId id(cx); if (!fromJSIDVariant(cx, idVar, &id)) return fail(jsapi, rs); Rooted<PropertyDescriptor> desc(cx); if (!toDescriptor(cx, descriptor, &desc)) return fail(jsapi, rs); ObjectOpResult success; if (!JS_DefinePropertyById(cx, obj, id, desc, success)) return fail(jsapi, rs); return ok(rs, success); }
bool WrapperAnswer::RecvGetPropertyKeys(const ObjectId& objId, const uint32_t& flags, ReturnStatus* rs, nsTArray<JSIDVariant>* ids) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("%s.getPropertyKeys()", ReceiverObj(objId)); AutoIdVector props(cx); if (!js::GetPropertyKeys(cx, obj, flags, &props)) return fail(jsapi, rs); for (size_t i = 0; i < props.length(); i++) { JSIDVariant id; if (!toJSIDVariant(cx, props[i], &id)) return fail(jsapi, rs); ids->AppendElement(id); } return ok(rs); }
bool WrapperAnswer::RecvGetPrototype(const ObjectId& objId, ReturnStatus* rs, ObjectOrNullVariant* result) { *result = NullVariant(); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); JS::RootedObject proto(cx); if (!JS_GetPrototype(cx, obj, &proto)) return fail(jsapi, rs); if (!toObjectOrNullVariant(cx, proto, result)) return fail(jsapi, rs); LOG("getPrototype(%s)", ReceiverObj(objId)); return ok(rs); }
void ThrowAndReport(nsPIDOMWindow* aWindow, nsresult aRv, const char* aMessage) { MOZ_ASSERT(aRv != NS_ERROR_UNCATCHABLE_EXCEPTION, "Doesn't make sense to report uncatchable exceptions!"); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(aWindow))) { return; } jsapi.TakeOwnershipOfErrorReporting(); Throw(jsapi.cx(), aRv, aMessage); }
bool WrapperAnswer::RecvClassName(const ObjectId& objId, nsCString* name) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) { // This is very unfortunate, but we have no choice. return "<dead CPOW>"; } LOG("%s.className()", ReceiverObj(objId)); *name = js::ObjectClassName(cx, obj); return true; }
bool WrapperAnswer::RecvPreventExtensions(const ObjectId& objId, ReturnStatus* rs) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); ObjectOpResult success; if (!JS_PreventExtensions(cx, obj, success)) return fail(jsapi, rs); LOG("%s.preventExtensions()", ReceiverObj(objId)); return ok(rs, success); }
bool WrapperAnswer::RecvIsExtensible(const ObjectId& objId, ReturnStatus* rs, bool* result) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); *result = false; RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("%s.isExtensible()", ReceiverObj(objId)); bool extensible; if (!JS_IsExtensible(cx, obj, &extensible)) return fail(jsapi, rs); *result = !!extensible; return ok(rs); }
bool WrapperAnswer::RecvDOMInstanceOf(const ObjectId& objId, const int& prototypeID, const int& depth, ReturnStatus* rs, bool* instanceof) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); *instanceof = false; RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("%s.domInstanceOf()", ReceiverObj(objId)); bool tmp; if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp)) return fail(jsapi, rs); *instanceof = tmp; return ok(rs); }
bool WrapperAnswer::RecvHasInstance(const ObjectId& objId, const JSVariant& vVar, ReturnStatus* rs, bool* bp) { AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects()))) return false; jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); RootedObject obj(cx, findObjectById(cx, objId)); if (!obj) return fail(jsapi, rs); LOG("%s.hasInstance(%s)", ReceiverObj(objId), InVariant(vVar)); RootedValue val(cx); if (!fromVariant(cx, vVar, &val)) return fail(jsapi, rs); if (!JS_HasInstance(cx, obj, val, bp)) return fail(jsapi, rs); return ok(rs); }
nsresult nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget, nsIDOMEvent* aEvent) { nsresult rv = NS_ERROR_FAILURE; // Prevent default action? if (mType & NS_HANDLER_TYPE_PREVENTDEFAULT) { aEvent->PreventDefault(); // If we prevent default, then it's okay for // mHandlerElement and mHandlerText to be null rv = NS_OK; } if (!mHandlerElement) // This works for both types of handlers. In both cases, the union's var should be defined. return rv; // See if our event receiver is a content node (and not us). bool isXULKey = !!(mType & NS_HANDLER_TYPE_XUL); bool isXBLCommand = !!(mType & NS_HANDLER_TYPE_XBL_COMMAND); NS_ASSERTION(!(isXULKey && isXBLCommand), "can't be both a key and xbl command handler"); // XUL handlers and commands shouldn't be triggered by non-trusted // events. if (isXULKey || isXBLCommand) { bool trustedEvent = false; aEvent->GetIsTrusted(&trustedEvent); if (!trustedEvent) return NS_OK; } if (isXBLCommand) { return DispatchXBLCommand(aTarget, aEvent); } // If we're executing on a XUL key element, just dispatch a command // event at the element. It will take care of retargeting it to its // command element, if applicable, and executing the event handler. if (isXULKey) { return DispatchXULKeyCommand(aEvent); } // Look for a compiled handler on the element. // Should be compiled and bound with "on" in front of the name. nsCOMPtr<nsIAtom> onEventAtom = do_GetAtom(NS_LITERAL_STRING("onxbl") + nsDependentAtomString(mEventName)); // Compile the handler and bind it to the element. nsCOMPtr<nsIScriptGlobalObject> boundGlobal; nsCOMPtr<nsPIWindowRoot> winRoot(do_QueryInterface(aTarget)); nsCOMPtr<nsPIDOMWindow> window; if (winRoot) { window = winRoot->GetWindow(); } if (window) { window = window->GetCurrentInnerWindow(); NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED); boundGlobal = do_QueryInterface(window->GetPrivateRoot()); } else boundGlobal = do_QueryInterface(aTarget); if (!boundGlobal) { nsCOMPtr<nsIDocument> boundDocument(do_QueryInterface(aTarget)); if (!boundDocument) { // We must be an element. nsCOMPtr<nsIContent> content(do_QueryInterface(aTarget)); if (!content) return NS_OK; boundDocument = content->OwnerDoc(); } boundGlobal = do_QueryInterface(boundDocument->GetScopeObject()); } if (!boundGlobal) return NS_OK; nsISupports *scriptTarget; if (winRoot) { scriptTarget = boundGlobal; } else { scriptTarget = aTarget; } // We're about to create a new JSEventHandler, which means that we need to // Initiatize an AutoJSAPI with aTarget's bound global to make sure any errors // are reported to the correct place. AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(boundGlobal))) { return NS_OK; } jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> handler(cx); rv = EnsureEventHandler(jsapi, onEventAtom, &handler); NS_ENSURE_SUCCESS(rv, rv); JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI()); JS::Rooted<JSObject*> globalObject(cx, boundGlobal->GetGlobalJSObject()); JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId)); NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY); // Bind it to the bound element. Note that if we're using a separate XBL scope, // we'll actually be binding the event handler to a cross-compartment wrapper // to the bound element's reflector. // First, enter our XBL scope. This is where the generic handler should have // been compiled, above. JSAutoCompartment ac(cx, scopeObject); JS::Rooted<JSObject*> genericHandler(cx, handler.get()); bool ok = JS_WrapObject(cx, &genericHandler); NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); MOZ_ASSERT(!js::IsCrossCompartmentWrapper(genericHandler)); // Build a scope chain in the XBL scope. nsRefPtr<Element> targetElement = do_QueryObject(scriptTarget); JS::AutoObjectVector scopeChain(cx); ok = nsJSUtils::GetScopeChainForElement(cx, targetElement, scopeChain); NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); // Next, clone the generic handler with our desired scope chain. JS::Rooted<JSObject*> bound(cx, JS::CloneFunctionObject(cx, genericHandler, scopeChain)); NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE); nsRefPtr<EventHandlerNonNull> handlerCallback = new EventHandlerNonNull(nullptr, bound, /* aIncumbentGlobal = */ nullptr); TypedEventHandler typedHandler(handlerCallback); // Execute it. nsCOMPtr<JSEventHandler> jsEventHandler; rv = NS_NewJSEventHandler(scriptTarget, onEventAtom, typedHandler, getter_AddRefs(jsEventHandler)); NS_ENSURE_SUCCESS(rv, rv); // Handle the event. jsEventHandler->HandleEvent(aEvent); jsEventHandler->Disconnect(); return NS_OK; }
nsresult EventListenerManager::CompileEventHandlerInternal(Listener* aListener, const nsAString* aBody, Element* aElement) { MOZ_ASSERT(aListener->GetJSEventHandler()); MOZ_ASSERT(aListener->mHandlerIsString, "Why are we compiling a non-string JS listener?"); JSEventHandler* jsEventHandler = aListener->GetJSEventHandler(); MOZ_ASSERT(!jsEventHandler->GetTypedEventHandler().HasEventHandler(), "What is there to compile?"); nsresult result = NS_OK; nsCOMPtr<nsIDocument> doc; nsCOMPtr<nsIScriptGlobalObject> global = GetScriptGlobalAndDocument(getter_AddRefs(doc)); NS_ENSURE_STATE(global); // Activate JSAPI, and make sure that exceptions are reported on the right // Window. AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(global))) { return NS_ERROR_UNEXPECTED; } jsapi.TakeOwnershipOfErrorReporting(); JSContext* cx = jsapi.cx(); nsCOMPtr<nsIAtom> typeAtom = aListener->mTypeAtom; nsIAtom* attrName = typeAtom; // Flag us as not a string so we don't keep trying to compile strings which // can't be compiled. aListener->mHandlerIsString = false; // mTarget may not be an Element if it's a window and we're // getting an inline event listener forwarded from <html:body> or // <html:frameset> or <xul:window> or the like. // XXX I don't like that we have to reference content from // here. The alternative is to store the event handler string on // the JSEventHandler itself, and that still doesn't address // the arg names issue. nsCOMPtr<Element> element = do_QueryInterface(mTarget); MOZ_ASSERT(element || aBody, "Where will we get our body?"); nsAutoString handlerBody; const nsAString* body = aBody; if (!aBody) { if (aListener->mTypeAtom == nsGkAtoms::onSVGLoad) { attrName = nsGkAtoms::onload; } else if (aListener->mTypeAtom == nsGkAtoms::onSVGUnload) { attrName = nsGkAtoms::onunload; } else if (aListener->mTypeAtom == nsGkAtoms::onSVGResize) { attrName = nsGkAtoms::onresize; } else if (aListener->mTypeAtom == nsGkAtoms::onSVGScroll) { attrName = nsGkAtoms::onscroll; } else if (aListener->mTypeAtom == nsGkAtoms::onSVGZoom) { attrName = nsGkAtoms::onzoom; } else if (aListener->mTypeAtom == nsGkAtoms::onbeginEvent) { attrName = nsGkAtoms::onbegin; } else if (aListener->mTypeAtom == nsGkAtoms::onrepeatEvent) { attrName = nsGkAtoms::onrepeat; } else if (aListener->mTypeAtom == nsGkAtoms::onendEvent) { attrName = nsGkAtoms::onend; } element->GetAttr(kNameSpaceID_None, attrName, handlerBody); body = &handlerBody; aElement = element; } aListener = nullptr; uint32_t lineNo = 0; nsAutoCString url (NS_LITERAL_CSTRING("-moz-evil:lying-event-listener")); MOZ_ASSERT(body); MOZ_ASSERT(aElement); nsIURI *uri = aElement->OwnerDoc()->GetDocumentURI(); if (uri) { uri->GetSpec(url); lineNo = 1; } nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mTarget); uint32_t argCount; const char **argNames; nsContentUtils::GetEventArgNames(aElement->GetNameSpaceID(), typeAtom, win, &argCount, &argNames); JSAddonId *addonId = MapURIToAddonID(uri); // Wrap the event target, so that we can use it as the scope for the event // handler. Note that mTarget is different from aElement in the <body> case, // where mTarget is a Window. // // The wrapScope doesn't really matter here, because the target will create // its reflector in the proper scope, and then we'll enter that compartment. JS::Rooted<JSObject*> wrapScope(cx, global->GetGlobalJSObject()); JS::Rooted<JS::Value> v(cx); { JSAutoCompartment ac(cx, wrapScope); nsresult rv = nsContentUtils::WrapNative(cx, mTarget, &v, /* aAllowWrapping = */ false); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } if (addonId) { JS::Rooted<JSObject*> vObj(cx, &v.toObject()); JS::Rooted<JSObject*> addonScope(cx, xpc::GetAddonScope(cx, vObj, addonId)); if (!addonScope) { return NS_ERROR_FAILURE; } JSAutoCompartment ac(cx, addonScope); // Wrap our event target into the addon scope, since that's where we want to // do all our work. if (!JS_WrapValue(cx, &v)) { return NS_ERROR_FAILURE; } } JS::Rooted<JSObject*> target(cx, &v.toObject()); JSAutoCompartment ac(cx, target); // Now that we've entered the compartment we actually care about, create our // scope chain. Note that we start with |element|, not aElement, because // mTarget is different from aElement in the <body> case, where mTarget is a // Window, and in that case we do not want the scope chain to include the body // or the document. JS::AutoObjectVector scopeChain(cx); if (!nsJSUtils::GetScopeChainForElement(cx, element, scopeChain)) { return NS_ERROR_OUT_OF_MEMORY; } nsDependentAtomString str(attrName); // Most of our names are short enough that we don't even have to malloc // the JS string stuff, so don't worry about playing games with // refcounting XPCOM stringbuffers. JS::Rooted<JSString*> jsStr(cx, JS_NewUCStringCopyN(cx, str.BeginReading(), str.Length())); NS_ENSURE_TRUE(jsStr, NS_ERROR_OUT_OF_MEMORY); // Get the reflector for |aElement|, so that we can pass to setElement. if (NS_WARN_IF(!GetOrCreateDOMReflector(cx, target, aElement, &v))) { return NS_ERROR_FAILURE; } JS::CompileOptions options(cx); options.setIntroductionType("eventHandler") .setFileAndLine(url.get(), lineNo) .setVersion(JSVERSION_DEFAULT) .setElement(&v.toObject()) .setElementAttributeName(jsStr); JS::Rooted<JSObject*> handler(cx); result = nsJSUtils::CompileFunction(jsapi, scopeChain, options, nsAtomCString(typeAtom), argCount, argNames, *body, handler.address()); NS_ENSURE_SUCCESS(result, result); NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE); if (jsEventHandler->EventName() == nsGkAtoms::onerror && win) { nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback = new OnErrorEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr); jsEventHandler->SetHandler(handlerCallback); } else if (jsEventHandler->EventName() == nsGkAtoms::onbeforeunload && win) { nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback = new OnBeforeUnloadEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr); jsEventHandler->SetHandler(handlerCallback); } else { nsRefPtr<EventHandlerNonNull> handlerCallback = new EventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr); jsEventHandler->SetHandler(handlerCallback); } return result; }