void Promise::AppendNativeHandler(PromiseNativeHandler* aRunnable) { NS_ASSERT_OWNINGTHREAD(Promise); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mGlobal))) { // Our API doesn't allow us to return a useful error. Not like this should // happen anyway. return; } // The self-hosted promise js may keep the object we pass to it alive // for quite a while depending on when GC runs. Therefore, pass a shim // object instead. The shim will free its inner PromiseNativeHandler // after the promise has settled just like our previous c++ promises did. RefPtr<PromiseNativeHandlerShim> shim = new PromiseNativeHandlerShim(aRunnable); JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> handlerWrapper(cx); // Note: PromiseNativeHandler is NOT wrappercached. So we can't use // ToJSValue here, because it will try to do XPConnect wrapping on it, sadly. if (NS_WARN_IF(!shim->WrapObject(cx, nullptr, &handlerWrapper))) { // Again, no way to report errors. jsapi.ClearException(); return; } JS::Rooted<JSObject*> resolveFunc(cx); resolveFunc = CreateNativeHandlerFunction(cx, handlerWrapper, NativeHandlerTask::Resolve); if (NS_WARN_IF(!resolveFunc)) { jsapi.ClearException(); return; } JS::Rooted<JSObject*> rejectFunc(cx); rejectFunc = CreateNativeHandlerFunction(cx, handlerWrapper, NativeHandlerTask::Reject); if (NS_WARN_IF(!rejectFunc)) { jsapi.ClearException(); return; } JS::Rooted<JSObject*> promiseObj(cx, PromiseObj()); if (NS_WARN_IF(!JS::AddPromiseReactions(cx, promiseObj, resolveFunc, rejectFunc))) { jsapi.ClearException(); return; } }
nsresult TranslateChoices( JS::HandleValue aChoices, const nsTArray<PermissionRequest>& aPermissionRequests, nsTArray<PermissionChoice>& aTranslatedChoices) { if (aChoices.isNullOrUndefined()) { // No choice is specified. } else if (aChoices.isObject()) { // Iterate through all permission types. for (uint32_t i = 0; i < aPermissionRequests.Length(); ++i) { nsCString type = aPermissionRequests[i].type(); JS::Rooted<JSObject*> obj(RootingCx(), &aChoices.toObject()); // People really shouldn't be passing WindowProxy or Location // objects for the choices here. obj = js::CheckedUnwrapStatic(obj); if (!obj) { return NS_ERROR_FAILURE; } AutoJSAPI jsapi; jsapi.Init(); JSContext* cx = jsapi.cx(); JSAutoRealm ar(cx, obj); JS::Rooted<JS::Value> val(cx); if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) || !val.isString()) { // no setting for the permission type, clear exception and skip it jsapi.ClearException(); } else { nsAutoJSString choice; if (!choice.init(cx, val)) { jsapi.ClearException(); return NS_ERROR_FAILURE; } aTranslatedChoices.AppendElement(PermissionChoice(type, choice)); } } } else { MOZ_ASSERT(false, "SelectedChoices should be undefined or an JS object"); return NS_ERROR_FAILURE; } return NS_OK; }
NS_IMETHODIMP MobileConnectionCallback::NotifyGetCallForwardingSuccess(uint32_t aCount, nsIMobileCallForwardingOptions** aResults) { nsTArray<MozCallForwardingOptions> results; for (uint32_t i = 0; i < aCount; i++) { MozCallForwardingOptions result; int16_t pShort; nsString pString; bool pBool; aResults[i]->GetActive(&pBool); result.mActive.Construct(pBool); aResults[i]->GetAction(&pShort); if (pShort != nsIMobileConnection::CALL_FORWARD_ACTION_UNKNOWN) { result.mAction.Construct(pShort); } aResults[i]->GetReason(&pShort); if (pShort != nsIMobileConnection::CALL_FORWARD_REASON_UNKNOWN) { result.mReason.Construct(pShort); } aResults[i]->GetNumber(pString); result.mNumber.Construct(pString.get()); aResults[i]->GetTimeSeconds(&pShort); if (pShort >= 0) { result.mTimeSeconds.Construct(pShort); } aResults[i]->GetServiceClass(&pShort); if (pShort != nsIMobileConnection::ICC_SERVICE_CLASS_NONE) { result.mServiceClass.Construct(pShort); } results.AppendElement(result); } AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mWindow))) { return NS_ERROR_FAILURE; } JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> jsResult(cx); if (!ToJSValue(cx, results, &jsResult)) { jsapi.ClearException(); return NS_ERROR_TYPE_ERR; } return NotifySuccess(jsResult); }
void ProfileGatherer::Finish() { MOZ_ASSERT(NS_IsMainThread()); if (!mTicker) { // We somehow got called after we were cancelled! This shouldn't // be possible, but doing a belt-and-suspenders check to be sure. return; } UniquePtr<char[]> buf = mTicker->ToJSON(mSinceTime); nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) { DebugOnly<nsresult> rv = os->RemoveObserver(this, "profiler-subprocess"); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "RemoveObserver failed"); } AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mPromise->GlobalJSObject()))) { // We're really hosed if we can't get a JS context for some reason. Reset(); return; } JSContext* cx = jsapi.cx(); // Now parse the JSON so that we resolve with a JS Object. JS::RootedValue val(cx); { NS_ConvertUTF8toUTF16 js_string(nsDependentCString(buf.get())); if (!JS_ParseJSON(cx, static_cast<const char16_t*>(js_string.get()), js_string.Length(), &val)) { if (!jsapi.HasException()) { mPromise->MaybeReject(NS_ERROR_DOM_UNKNOWN_ERR); } else { JS::RootedValue exn(cx); DebugOnly<bool> gotException = jsapi.StealException(&exn); MOZ_ASSERT(gotException); jsapi.ClearException(); mPromise->MaybeReject(cx, exn); } } else { mPromise->MaybeResolve(val); } } Reset(); }
bool ParseSuccessfulReply(JS::MutableHandle<JS::Value> aValue) { aValue.setUndefined(); const BluetoothValue& v = mReply->get_BluetoothReplySuccess().value(); NS_ENSURE_TRUE(v.type() == BluetoothValue::TArrayOfuint8_t, false); AutoJSAPI jsapi; NS_ENSURE_TRUE(jsapi.Init(mDescriptor->GetParentObject()), false); JSContext* cx = jsapi.cx(); if (!ToJSValue(cx, v.get_ArrayOfuint8_t(), aValue)) { jsapi.ClearException(); return false; } return true; }
NS_IMETHODIMP MobileConnectionCallback::NotifyGetClirStatusSuccess(uint16_t aN, uint16_t aM) { MozClirStatus result; result.mN.Construct(aN); result.mM.Construct(aM); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mWindow))) { return NS_ERROR_FAILURE; } JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> jsResult(cx); if (!ToJSValue(cx, result, &jsResult)) { jsapi.ClearException(); return NS_ERROR_TYPE_ERR; } return NotifySuccess(jsResult); };
NS_IMETHODIMP MobileConnectionCallback::NotifyGetCallBarringSuccess(uint16_t aProgram, bool aEnabled, uint16_t aServiceClass) { MozCallBarringOptions result; result.mProgram.Construct().SetValue(aProgram); result.mEnabled.Construct().SetValue(aEnabled); result.mServiceClass.Construct().SetValue(aServiceClass); AutoJSAPI jsapi; if (NS_WARN_IF(!jsapi.Init(mWindow))) { return NS_ERROR_FAILURE; } JSContext* cx = jsapi.cx(); JS::Rooted<JS::Value> jsResult(cx); if (!ToJSValue(cx, result, &jsResult)) { jsapi.ClearException(); return NS_ERROR_TYPE_ERR; } return NotifySuccess(jsResult); }
// static JSObject* SimpleGlobalObject::Create(GlobalType globalType, JS::Handle<JS::Value> proto) { // We can't root our return value with our AutoJSAPI because the rooting // analysis thinks ~AutoJSAPI can GC. So we need to root in a scope outside // the lifetime of the AutoJSAPI. JS::Rooted<JSObject*> global(RootingCx()); { // Scope to ensure the AutoJSAPI destructor runs before we end up returning AutoJSAPI jsapi; jsapi.Init(); JSContext* cx = jsapi.cx(); JS::CompartmentOptions options; options.creationOptions() .setInvisibleToDebugger(true) // Put our SimpleGlobalObjects in the system zone, so we won't create // lots of zones for what are probably very short-lived // compartments. This should help them be GCed quicker and take up // less memory before they're GCed. .setZone(JS::SystemZone); if (NS_IsMainThread()) { nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create(); options.creationOptions().setTrace(xpc::TraceXPCGlobal); global = xpc::CreateGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass), nsJSPrincipals::get(principal), options); } else { global = JS_NewGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass), nullptr, JS::DontFireOnNewGlobalHook, options); } if (!global) { jsapi.ClearException(); return nullptr; } JSAutoCompartment ac(cx, global); // It's important to create the nsIGlobalObject for our new global before we // start trying to wrap things like the prototype into its compartment, // because the wrap operation relies on the global having its // nsIGlobalObject already. RefPtr<SimpleGlobalObject> globalObject = new SimpleGlobalObject(global, globalType); // Pass on ownership of globalObject to |global|. JS_SetPrivate(global, globalObject.forget().take()); if (proto.isObjectOrNull()) { JS::Rooted<JSObject*> protoObj(cx, proto.toObjectOrNull()); if (!JS_WrapObject(cx, &protoObj)) { jsapi.ClearException(); return nullptr; } if (!JS_SplicePrototype(cx, global, protoObj)) { jsapi.ClearException(); return nullptr; } } else if (!proto.isUndefined()) { // Bogus proto. return nullptr; } JS_FireOnNewGlobalObject(cx, global); } return global; }
static bool ProcessFile(AutoJSAPI& jsapi, const char* filename, FILE* file, bool forceTTY) { JSContext* cx = jsapi.cx(); JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx)); MOZ_ASSERT(global); if (forceTTY) { file = stdin; } else if (!isatty(fileno(file))) { /* * It's not interactive - just execute it. * * Support the UNIX #! shell hack; gobble the first line if it starts * with '#'. TODO - this isn't quite compatible with sharp variables, * as a legal js program (using sharp variables) might start with '#'. * But that would require multi-character lookahead. */ int ch = fgetc(file); if (ch == '#') { while ((ch = fgetc(file)) != EOF) { if (ch == '\n' || ch == '\r') break; } } ungetc(ch, file); JS::RootedScript script(cx); JS::RootedValue unused(cx); JS::CompileOptions options(cx); options.setUTF8(true) .setFileAndLine(filename, 1) .setIsRunOnce(true) .setNoScriptRval(true); if (!JS::Compile(cx, options, file, &script)) return false; return compileOnly || JS_ExecuteScript(cx, script, &unused); } /* It's an interactive filehandle; drop into read-eval-print loop. */ int lineno = 1; bool hitEOF = false; do { char buffer[4096]; char* bufp = buffer; *bufp = '\0'; /* * Accumulate lines until we get a 'compilable unit' - one that either * generates an error (before running out of source) or that compiles * cleanly. This should be whenever we get a complete statement that * coincides with the end of a line. */ int startline = lineno; do { if (!GetLine(cx, bufp, file, startline == lineno ? "js> " : "")) { hitEOF = true; break; } bufp += strlen(bufp); lineno++; } while (!JS_BufferIsCompilableUnit(cx, global, buffer, strlen(buffer))); if (!ProcessLine(jsapi, buffer, startline)) jsapi.ClearException(); // Errors from interactive processing are squelched. } while (!hitEOF && !gQuitting); fprintf(gOutFile, "\n"); return true; }