nsresult nsJSUtils::EvaluateString(JSContext* aCx, JS::SourceBufferHolder& aSrcBuf, JS::Handle<JSObject*> aEvaluationGlobal, JS::CompileOptions& aCompileOptions, const EvaluateOptions& aEvaluateOptions, JS::MutableHandle<JS::Value> aRetValue, void **aOffThreadToken) { PROFILER_LABEL("nsJSUtils", "EvaluateString", js::ProfileEntry::Category::JS); MOZ_ASSERT(JS::ContextOptionsRef(aCx).autoJSAPIOwnsErrorReporting(), "Caller must own error reporting"); MOZ_ASSERT_IF(aCompileOptions.versionSet, aCompileOptions.version != JSVERSION_UNKNOWN); MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, !aCompileOptions.noScriptRval); MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext()); MOZ_ASSERT(aSrcBuf.get()); MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aEvaluationGlobal) == aEvaluationGlobal); MOZ_ASSERT_IF(aOffThreadToken, aCompileOptions.noScriptRval); MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(nsContentUtils::IsInMicroTask()); // Unfortunately, the JS engine actually compiles scripts with a return value // in a different, less efficient way. Furthermore, it can't JIT them in many // cases. So we need to be explicitly told whether the caller cares about the // return value. Callers can do this by calling the other overload of // EvaluateString() which calls this function with // aCompileOptions.noScriptRval set to true. aRetValue.setUndefined(); nsresult rv = NS_OK; nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); NS_ENSURE_TRUE(ssm->ScriptAllowed(aEvaluationGlobal), NS_OK); bool ok = true; // Scope the JSAutoCompartment so that we can later wrap the return value // into the caller's cx. { JSAutoCompartment ac(aCx, aEvaluationGlobal); // Now make sure to wrap the scope chain into the right compartment. JS::AutoObjectVector scopeChain(aCx); if (!scopeChain.reserve(aEvaluateOptions.scopeChain.length())) { return NS_ERROR_OUT_OF_MEMORY; } for (size_t i = 0; i < aEvaluateOptions.scopeChain.length(); ++i) { JS::ExposeObjectToActiveJS(aEvaluateOptions.scopeChain[i]); scopeChain.infallibleAppend(aEvaluateOptions.scopeChain[i]); if (!JS_WrapObject(aCx, scopeChain[i])) { ok = false; break; } } if (ok && aOffThreadToken) { JS::Rooted<JSScript*> script(aCx, JS::FinishOffThreadScript(aCx, JS_GetRuntime(aCx), *aOffThreadToken)); *aOffThreadToken = nullptr; // Mark the token as having been finished. if (script) { ok = JS_ExecuteScript(aCx, scopeChain, script); } else { ok = false; } } else if (ok) { ok = JS::Evaluate(aCx, scopeChain, aCompileOptions, aSrcBuf, aRetValue); } if (ok && aEvaluateOptions.coerceToString && !aRetValue.isUndefined()) { JS::Rooted<JS::Value> value(aCx, aRetValue); JSString* str = JS::ToString(aCx, value); ok = !!str; aRetValue.set(ok ? JS::StringValue(str) : JS::UndefinedValue()); } } if (!ok) { if (JS_IsExceptionPending(aCx)) { rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW; } else { rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE; } if (!aCompileOptions.noScriptRval) { aRetValue.setUndefined(); } } // Wrap the return value into whatever compartment aCx was in. if (ok && !aCompileOptions.noScriptRval) { if (!JS_WrapValue(aCx, aRetValue)) { return NS_ERROR_OUT_OF_MEMORY; } } return rv; }
// Define a shadowing property on |this| for the XBL field defined by the // contents of the callee's reserved slots. If the property was defined, // *installed will be true, and idp will be set to the property name that was // defined. static JSBool InstallXBLField(JSContext* cx, JS::Handle<JSObject*> callee, JS::Handle<JSObject*> thisObj, JS::MutableHandle<jsid> idp, bool* installed) { *installed = false; // First ensure |this| is a reasonable XBL bound node. // // FieldAccessorGuard already determined whether |thisObj| was acceptable as // |this| in terms of not throwing a TypeError. Assert this for good measure. MOZ_ASSERT(ValueHasISupportsPrivate(JS::ObjectValue(*thisObj))); // But there are some cases where we must accept |thisObj| but not install a // property on it, or otherwise touch it. Hence this split of |this|-vetting // duties. nsISupports* native = nsContentUtils::XPConnect()->GetNativeOfWrapper(cx, thisObj); if (!native) { // Looks like whatever |thisObj| is it's not our nsIContent. It might well // be the proto our binding installed, however, where the private is the // nsXBLDocumentInfo, so just baul out quietly. Do NOT throw an exception // here. // // We could make this stricter by checking the class maybe, but whatever. return true; } nsCOMPtr<nsIContent> xblNode = do_QueryInterface(native); if (!xblNode) { xpc::Throw(cx, NS_ERROR_UNEXPECTED); return false; } // Now that |this| is okay, actually install the field. // Because of the possibility (due to XBL binding inheritance, because each // XBL binding lives in its own global object) that |this| might be in a // different compartment from the callee (not to mention that this method can // be called with an arbitrary |this| regardless of how insane XBL is), and // because in this method we've entered |this|'s compartment (see in // Field[GS]etter where we attempt a cross-compartment call), we must enter // the callee's compartment to access its reserved slots. nsXBLPrototypeBinding* protoBinding; nsDependentJSString fieldName; { JSAutoCompartment ac(cx, callee); JS::Rooted<JSObject*> xblProto(cx); xblProto = &js::GetFunctionNativeReserved(callee, XBLPROTO_SLOT).toObject(); JS::Rooted<JS::Value> name(cx, js::GetFunctionNativeReserved(callee, FIELD_SLOT)); JSFlatString* fieldStr = JS_ASSERT_STRING_IS_FLAT(name.toString()); fieldName.init(fieldStr); MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp.address())); // If a separate XBL scope is being used, the callee is not same-compartment // with the xbl prototype, and the object is a cross-compartment wrapper. xblProto = js::UncheckedUnwrap(xblProto); JSAutoCompartment ac2(cx, xblProto); JS::Value slotVal = ::JS_GetReservedSlot(xblProto, 0); protoBinding = static_cast<nsXBLPrototypeBinding*>(slotVal.toPrivate()); MOZ_ASSERT(protoBinding); } nsXBLProtoImplField* field = protoBinding->FindField(fieldName); MOZ_ASSERT(field); // This mirrors code in nsXBLProtoImpl::InstallImplementation nsIScriptGlobalObject* global = xblNode->OwnerDoc()->GetScriptGlobalObject(); if (!global) { return true; } nsCOMPtr<nsIScriptContext> context = global->GetContext(); if (!context) { return true; } nsresult rv = field->InstallField(context, thisObj, protoBinding->DocURI(), installed); if (NS_SUCCEEDED(rv)) { return true; } if (!::JS_IsExceptionPending(cx)) { xpc::Throw(cx, rv); } return false; }
NS_IMETHODIMP MobileMessageManager::Send(JS::Handle<JS::Value> aNumber, const nsAString& aMessage, JS::Handle<JS::Value> aSendParams, JSContext* aCx, uint8_t aArgc, JS::MutableHandle<JS::Value> aReturn) { if (!aNumber.isString() && !JS_IsArrayObject(aCx, aNumber)) { return NS_ERROR_INVALID_ARG; } nsresult rv; nsIScriptContext* sc = GetContextForEventHandlers(&rv); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_STATE(sc); JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx)); mozilla::Maybe<JSAutoCompartment> ac; if (!global) { global = sc->GetWindowProxy(); ac.construct(aCx, global); } nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID); NS_ENSURE_TRUE(smsService, NS_ERROR_FAILURE); // Use the default one unless |aSendParams.serviceId| is available. uint32_t serviceId; rv = smsService->GetSmsDefaultServiceId(&serviceId); NS_ENSURE_SUCCESS(rv, rv); if (aArgc == 1) { JS::Rooted<JS::Value> param(aCx, aSendParams); RootedDictionary<SmsSendParameters> sendParams(aCx); if (!sendParams.Init(aCx, param)) { return NS_ERROR_TYPE_ERR; } if (sendParams.mServiceId.WasPassed()) { serviceId = sendParams.mServiceId.Value(); } } if (aNumber.isString()) { JS::Rooted<JSString*> str(aCx, aNumber.toString()); return Send(aCx, global, serviceId, str, aMessage, aReturn.address()); } // Must be an array then. JS::Rooted<JSObject*> numbers(aCx, &aNumber.toObject()); uint32_t size; if (!JS_GetArrayLength(aCx, numbers, &size)) { return NS_ERROR_FAILURE; } JS::AutoValueVector requests(aCx); if (!requests.resize(size)) { return NS_ERROR_FAILURE; } JS::Rooted<JS::Value> number(aCx); JS::Rooted<JSString*> str(aCx); for (uint32_t i = 0; i < size; ++i) { if (!JS_GetElement(aCx, numbers, i, &number)) { return NS_ERROR_INVALID_ARG; } str = JS::ToString(aCx, number); if (!str) { return NS_ERROR_FAILURE; } nsresult rv = Send(aCx, global, serviceId, str, aMessage, &requests[i]); NS_ENSURE_SUCCESS(rv, rv); } JS::Rooted<JSObject*> obj(aCx); obj = JS_NewArrayObject(aCx, requests); if (!obj) { return NS_ERROR_FAILURE; } aReturn.setObject(*obj); return NS_OK; }
bool WindowNamedPropertiesHandler::getOwnPropertyDescriptor(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId, JS::MutableHandle<JSPropertyDescriptor> aDesc, unsigned aFlags) { if (!JSID_IS_STRING(aId)) { // Nothing to do if we're resolving a non-string property. return true; } JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, aProxy)); if (HasPropertyOnPrototype(aCx, aProxy, aId)) { return true; } nsDependentJSString str(aId); // Grab the DOM window. XPCWrappedNative* wrapper = XPCWrappedNative::Get(global); nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrappedNative(wrapper); MOZ_ASSERT(piWin); nsGlobalWindow* win = static_cast<nsGlobalWindow*>(piWin.get()); if (win->GetLength() > 0) { nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str); if (childWin && ShouldExposeChildWindow(str, childWin)) { // We found a subframe of the right name. Shadowing via |var foo| in // global scope is still allowed, since |var| only looks up |own| // properties. But unqualified shadowing will fail, per-spec. JS::Rooted<JS::Value> v(aCx); if (!WrapObject(aCx, aProxy, childWin, &v)) { return false; } aDesc.object().set(aProxy); aDesc.value().set(v); aDesc.setAttributes(JSPROP_ENUMERATE); return true; } } // The rest of this function is for HTML documents only. nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(win->GetExtantDoc()); if (!htmlDoc) { return true; } nsHTMLDocument* document = static_cast<nsHTMLDocument*>(htmlDoc.get()); Element* element = document->GetElementById(str); if (element) { JS::Rooted<JS::Value> v(aCx); if (!WrapObject(aCx, aProxy, element, &v)) { return false; } aDesc.object().set(aProxy); aDesc.value().set(v); aDesc.setAttributes(JSPROP_ENUMERATE); return true; } nsWrapperCache* cache; nsISupports* result = document->ResolveName(str, &cache); if (!result) { return true; } JS::Rooted<JS::Value> v(aCx); if (!WrapObject(aCx, aProxy, result, cache, nullptr, &v)) { return false; } aDesc.object().set(aProxy); aDesc.value().set(v); aDesc.setAttributes(JSPROP_ENUMERATE); return true; }
nsresult nsJSUtils::EvaluateString(JSContext* aCx, JS::SourceBufferHolder& aSrcBuf, JS::Handle<JSObject*> aScopeObject, JS::CompileOptions& aCompileOptions, const EvaluateOptions& aEvaluateOptions, JS::MutableHandle<JS::Value> aRetValue, void **aOffThreadToken) { PROFILER_LABEL("nsJSUtils", "EvaluateString", js::ProfileEntry::Category::JS); MOZ_ASSERT_IF(aCompileOptions.versionSet, aCompileOptions.version != JSVERSION_UNKNOWN); MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, aEvaluateOptions.needResult); MOZ_ASSERT_IF(!aEvaluateOptions.reportUncaught, aEvaluateOptions.needResult); MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext()); MOZ_ASSERT(aSrcBuf.get()); // Unfortunately, the JS engine actually compiles scripts with a return value // in a different, less efficient way. Furthermore, it can't JIT them in many // cases. So we need to be explicitly told whether the caller cares about the // return value. Callers can do this by calling the other overload of // EvaluateString() which calls this function with aEvaluateOptions.needResult // set to false. aRetValue.setUndefined(); JS::ExposeObjectToActiveJS(aScopeObject); nsAutoMicroTask mt; nsresult rv = NS_OK; bool ok = false; nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); NS_ENSURE_TRUE(ssm->ScriptAllowed(js::GetGlobalForObjectCrossCompartment(aScopeObject)), NS_OK); mozilla::Maybe<AutoDontReportUncaught> dontReport; if (!aEvaluateOptions.reportUncaught) { // We need to prevent AutoLastFrameCheck from reporting and clearing // any pending exceptions. dontReport.emplace(aCx); } // Scope the JSAutoCompartment so that we can later wrap the return value // into the caller's cx. { JSAutoCompartment ac(aCx, aScopeObject); JS::Rooted<JSObject*> rootedScope(aCx, aScopeObject); if (aOffThreadToken) { JS::Rooted<JSScript*> script(aCx, JS::FinishOffThreadScript(aCx, JS_GetRuntime(aCx), *aOffThreadToken)); *aOffThreadToken = nullptr; // Mark the token as having been finished. if (script) { if (aEvaluateOptions.needResult) { ok = JS_ExecuteScript(aCx, rootedScope, script, aRetValue); } else { ok = JS_ExecuteScript(aCx, rootedScope, script); } } else { ok = false; } } else { if (aEvaluateOptions.needResult) { ok = JS::Evaluate(aCx, rootedScope, aCompileOptions, aSrcBuf, aRetValue); } else { ok = JS::Evaluate(aCx, rootedScope, aCompileOptions, aSrcBuf); } } if (ok && aEvaluateOptions.coerceToString && !aRetValue.isUndefined()) { JS::Rooted<JS::Value> value(aCx, aRetValue); JSString* str = JS::ToString(aCx, value); ok = !!str; aRetValue.set(ok ? JS::StringValue(str) : JS::UndefinedValue()); } } if (!ok) { if (aEvaluateOptions.reportUncaught) { ReportPendingException(aCx); if (aEvaluateOptions.needResult) { aRetValue.setUndefined(); } } else { rv = JS_IsExceptionPending(aCx) ? NS_ERROR_FAILURE : NS_ERROR_OUT_OF_MEMORY; JS::Rooted<JS::Value> exn(aCx); JS_GetPendingException(aCx, &exn); if (aEvaluateOptions.needResult) { aRetValue.set(exn); } JS_ClearPendingException(aCx); } } // Wrap the return value into whatever compartment aCx was in. if (aEvaluateOptions.needResult) { JS::Rooted<JS::Value> v(aCx, aRetValue); if (!JS_WrapValue(aCx, &v)) { return NS_ERROR_OUT_OF_MEMORY; } aRetValue.set(v); } return rv; }
NS_IMETHODIMP MmsMessage::GetAttachments(JSContext* aCx, JS::MutableHandle<JS::Value> aAttachments) { uint32_t length = mAttachments.Length(); JS::Rooted<JSObject*> attachments( aCx, JS_NewArrayObject(aCx, length)); NS_ENSURE_TRUE(attachments, NS_ERROR_OUT_OF_MEMORY); for (uint32_t i = 0; i < length; ++i) { const Attachment &attachment = mAttachments[i]; JS::Rooted<JSObject*> attachmentObj(aCx, JS_NewPlainObject(aCx)); NS_ENSURE_TRUE(attachmentObj, NS_ERROR_OUT_OF_MEMORY); JS::Rooted<JSString*> tmpJsStr(aCx); // Get |attachment.mId|. tmpJsStr = JS_NewUCStringCopyN(aCx, attachment.id.get(), attachment.id.Length()); NS_ENSURE_TRUE(tmpJsStr, NS_ERROR_OUT_OF_MEMORY); if (!JS_DefineProperty(aCx, attachmentObj, "id", tmpJsStr, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } // Get |attachment.mLocation|. tmpJsStr = JS_NewUCStringCopyN(aCx, attachment.location.get(), attachment.location.Length()); NS_ENSURE_TRUE(tmpJsStr, NS_ERROR_OUT_OF_MEMORY); if (!JS_DefineProperty(aCx, attachmentObj, "location", tmpJsStr, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } // Get |attachment.mContent|. // Duplicating the File with the correct parent object. nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx)); MOZ_ASSERT(global); nsRefPtr<File> newBlob = new File(global, attachment.content->Impl()); JS::Rooted<JS::Value> val(aCx); if (!GetOrCreateDOMReflector(aCx, newBlob, &val)) { return NS_ERROR_FAILURE; } if (!JS_DefineProperty(aCx, attachmentObj, "content", val, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } if (!JS_DefineElement(aCx, attachments, i, attachmentObj, JSPROP_ENUMERATE)) { return NS_ERROR_FAILURE; } } aAttachments.setObject(*attachments); return NS_OK; }
nsresult nsXBLPrototypeHandler::EnsureEventHandler(AutoJSAPI& jsapi, nsIAtom* aName, JS::MutableHandle<JSObject*> aHandler) { JSContext* cx = jsapi.cx(); // Check to see if we've already compiled this JS::Rooted<JSObject*> globalObject(cx, JS::CurrentGlobalOrNull(cx)); nsCOMPtr<nsPIDOMWindowInner> pWindow = xpc::WindowOrNull(globalObject)->AsInner(); if (pWindow) { JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this)); if (cachedHandler) { JS::ExposeObjectToActiveJS(cachedHandler); aHandler.set(cachedHandler); NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE); return NS_OK; } } // Ensure that we have something to compile nsDependentString handlerText(mHandlerText); NS_ENSURE_TRUE(!handlerText.IsEmpty(), NS_ERROR_FAILURE); JSAddonId* addonId = MapURIToAddonID(mPrototypeBinding->DocURI()); JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, addonId)); NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY); nsAutoCString bindingURI; mPrototypeBinding->DocURI()->GetSpec(bindingURI); uint32_t argCount; const char **argNames; nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, false, &argCount, &argNames); // Compile the event handler in the xbl scope. JSAutoCompartment ac(cx, scopeObject); JS::CompileOptions options(cx); options.setFileAndLine(bindingURI.get(), mLineNumber) .setVersion(JSVERSION_LATEST); JS::Rooted<JSObject*> handlerFun(cx); JS::AutoObjectVector emptyVector(cx); nsresult rv = nsJSUtils::CompileFunction(jsapi, emptyVector, options, nsAtomCString(aName), argCount, argNames, handlerText, handlerFun.address()); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(handlerFun, NS_ERROR_FAILURE); // Wrap the handler into the content scope, since we're about to stash it // on the DOM window and such. JSAutoCompartment ac2(cx, globalObject); bool ok = JS_WrapObject(cx, &handlerFun); NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); aHandler.set(handlerFun); NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE); if (pWindow) { pWindow->CacheXBLPrototypeHandler(this, aHandler); } return NS_OK; }
// static nsresult Key::DecodeJSValInternal(const unsigned char*& aPos, const unsigned char* aEnd, JSContext* aCx, uint8_t aTypeOffset, JS::MutableHandle<JS::Value> aVal, uint16_t aRecursionDepth) { NS_ENSURE_TRUE(aRecursionDepth < MaxRecursionDepth, NS_ERROR_DOM_INDEXEDDB_DATA_ERR); if (*aPos - aTypeOffset >= eArray) { JS::Rooted<JSObject*> array(aCx, JS_NewArrayObject(aCx, 0, nullptr)); if (!array) { NS_WARNING("Failed to make array!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } aTypeOffset += eMaxType; if (aTypeOffset == eMaxType * MaxArrayCollapse) { ++aPos; aTypeOffset = 0; } uint32_t index = 0; JS::Rooted<JS::Value> val(aCx); while (aPos < aEnd && *aPos - aTypeOffset != eTerminator) { nsresult rv = DecodeJSValInternal(aPos, aEnd, aCx, aTypeOffset, &val, aRecursionDepth + 1); NS_ENSURE_SUCCESS(rv, rv); aTypeOffset = 0; if (!JS_SetElement(aCx, array, index++, &val)) { NS_WARNING("Failed to set array element!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } } NS_ASSERTION(aPos >= aEnd || (*aPos % eMaxType) == eTerminator, "Should have found end-of-array marker"); ++aPos; aVal.setObject(*array); } else if (*aPos - aTypeOffset == eString) { nsString key; DecodeString(aPos, aEnd, key); if (!xpc::StringToJsval(aCx, key, aVal)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } } else if (*aPos - aTypeOffset == eDate) { double msec = static_cast<double>(DecodeNumber(aPos, aEnd)); JSObject* date = JS_NewDateObjectMsec(aCx, msec); if (!date) { NS_WARNING("Failed to make date!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } aVal.setObject(*date); } else if (*aPos - aTypeOffset == eFloat) { aVal.setDouble(DecodeNumber(aPos, aEnd)); } else { NS_NOTREACHED("Unknown key type!"); } return NS_OK; }
JSBool JavaObject::setPropertyWrapper(JSContext* ctx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSBool strict, JS::MutableHandle<JS::Value> vp) { jsval rval = vp.get(); return JavaObject::setProperty(ctx, obj, id, strict, &rval); }
nsresult nsXBLPrototypeHandler::EnsureEventHandler(nsIScriptGlobalObject* aGlobal, nsIScriptContext *aBoundContext, nsIAtom *aName, JS::MutableHandle<JSObject*> aHandler) { AutoPushJSContext cx(aBoundContext->GetNativeContext()); // Check to see if we've already compiled this nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aGlobal); if (pWindow) { JS::Rooted<JSObject*> cachedHandler(cx, pWindow->GetCachedXBLPrototypeHandler(this)); if (cachedHandler) { JS::ExposeObjectToActiveJS(cachedHandler); aHandler.set(cachedHandler); NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE); return NS_OK; } } // Ensure that we have something to compile nsDependentString handlerText(mHandlerText); NS_ENSURE_TRUE(!handlerText.IsEmpty(), NS_ERROR_FAILURE); JS::Rooted<JSObject*> globalObject(cx, aGlobal->GetGlobalJSObject()); JS::Rooted<JSObject*> scopeObject(cx, xpc::GetXBLScope(cx, globalObject)); NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY); nsAutoCString bindingURI; mPrototypeBinding->DocURI()->GetSpec(bindingURI); uint32_t argCount; const char **argNames; nsContentUtils::GetEventArgNames(kNameSpaceID_XBL, aName, &argCount, &argNames); // Compile the event handler in the xbl scope. JSAutoCompartment ac(cx, scopeObject); JS::CompileOptions options(cx); options.setFileAndLine(bindingURI.get(), mLineNumber) .setVersion(JSVERSION_LATEST); JS::Rooted<JSObject*> rootedNull(cx); // See bug 781070. JS::Rooted<JSObject*> handlerFun(cx); nsresult rv = nsJSUtils::CompileFunction(cx, rootedNull, options, nsAtomCString(aName), argCount, argNames, handlerText, handlerFun.address()); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(handlerFun, NS_ERROR_FAILURE); // Wrap the handler into the content scope, since we're about to stash it // on the DOM window and such. JSAutoCompartment ac2(cx, globalObject); bool ok = JS_WrapObject(cx, handlerFun.address()); NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); aHandler.set(handlerFun); NS_ENSURE_TRUE(aHandler, NS_ERROR_FAILURE); if (pWindow) { pWindow->CacheXBLPrototypeHandler(this, aHandler); } return NS_OK; }
void WorkerDebuggerGlobalScope::GetGlobal(JSContext* aCx, JS::MutableHandle<JSObject*> aGlobal) { aGlobal.set(mWorkerPrivate->GetOrCreateGlobalScope(aCx)->GetWrapper()); }