void WindowGlobalChild::HandleAsyncMessage(const nsString& aActorName, const nsString& aMessageName, StructuredCloneData& aData) { if (NS_WARN_IF(mIPCClosed)) { return; } // Force creation of the actor if it hasn't been created yet. IgnoredErrorResult rv; RefPtr<JSWindowActorChild> actor = GetActor(aActorName, rv); if (NS_WARN_IF(rv.Failed())) { return; } // Get the JSObject for the named actor. JS::RootedObject obj(RootingCx(), actor->GetWrapper()); if (NS_WARN_IF(!obj)) { // If we don't have a preserved wrapper, there won't be any receiver // method to call. return; } RefPtr<JSWindowActorService> actorSvc = JSWindowActorService::GetSingleton(); if (NS_WARN_IF(!actorSvc)) { return; } actorSvc->ReceiveMessage(actor, obj, aMessageName, aData); }
already_AddRefed<JSWindowActorChild> WindowGlobalChild::GetActor( const nsAString& aName, ErrorResult& aRv) { // Check if this actor has already been created, and return it if it has. if (mWindowActors.Contains(aName)) { return do_AddRef(mWindowActors.GetWeak(aName)); } // Otherwise, we want to create a new instance of this actor. Call into the // JSWindowActorService to trigger construction. RefPtr<JSWindowActorService> actorSvc = JSWindowActorService::GetSingleton(); if (!actorSvc) { return nullptr; } JS::RootedObject obj(RootingCx()); actorSvc->ConstructActor(aName, /* aChildSide */ false, mBrowsingContext, &obj, aRv); if (aRv.Failed()) { return nullptr; } // Unwrap our actor to a JSWindowActorChild object. RefPtr<JSWindowActorChild> actor; if (NS_FAILED(UNWRAP_OBJECT(JSWindowActorChild, &obj, actor))) { return nullptr; } MOZ_RELEASE_ASSERT(!actor->Manager(), "mManager was already initialized once!"); actor->Init(aName, this); mWindowActors.Put(aName, actor); return actor.forget(); }
void nsBrowserElement::RemoveNextPaintListener(BrowserElementNextPaintEventCallback& aListener, ErrorResult& aRv) { NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); JS::Rooted<JS::Value> val(RootingCx(), JS::ObjectOrNullValue(aListener.CallbackOrNull())); nsresult rv = mBrowserElementAPI->RemoveNextPaintListener(val); if (NS_WARN_IF(NS_FAILED(rv))) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); } }
Promise::PromiseState Promise::State() const { JS::Rooted<JSObject*> p(RootingCx(), PromiseObj()); const JS::PromiseState state = JS::GetPromiseState(p); if (state == JS::PromiseState::Fulfilled) { return PromiseState::Resolved; } if (state == JS::PromiseState::Rejected) { return PromiseState::Rejected; } return PromiseState::Pending; }
void SpeechRecognition::NotifyFinalResult(SpeechEvent* aEvent) { ResetAndEnd(); RootedDictionary<SpeechRecognitionEventInit> init(RootingCx()); init.mBubbles = true; init.mCancelable = false; // init.mResultIndex = 0; init.mResults = aEvent->mRecognitionResultList; init.mInterpretation = JS::NullValue(); // init.mEmma = nullptr; RefPtr<SpeechRecognitionEvent> event = SpeechRecognitionEvent::Constructor( this, NS_LITERAL_STRING("result"), init); event->SetTrusted(true); DispatchEvent(*event); }
void ResizeObserverController::Notify() { if (mResizeObservers.IsEmpty()) { return; } // We may call BroadcastAllActiveObservations(), which might cause mDocument // to be destroyed (and the ResizeObserverController with it). // e.g. if mDocument is in an iframe, and the observer JS removes it from the // parent document and we trigger an unlucky GC/CC (or maybe if the observer // JS navigates to a different URL). Or the author uses elem.offsetTop API, // which could flush style + layout and make the document destroyed if we're // inside an iframe that has suddenly become |display:none| via the author // doing something in their ResizeObserver callback. // // Therefore, we ref-count mDocument here to make sure it and its members // (e.g. mResizeObserverController, which is `this` pointer) are still alive // in the rest of this function because after it goes up, `this` is possible // deleted. RefPtr<Document> doc(mDocument); uint32_t shallowestTargetDepth = 0; GatherAllActiveObservations(shallowestTargetDepth); while (HasAnyActiveObservations()) { DebugOnly<uint32_t> oldShallowestTargetDepth = shallowestTargetDepth; shallowestTargetDepth = BroadcastAllActiveObservations(); NS_ASSERTION(oldShallowestTargetDepth < shallowestTargetDepth, "shallowestTargetDepth should be getting strictly deeper"); // Flush layout, so that any callback functions' style changes / resizes // get a chance to take effect. doc->FlushPendingNotifications(FlushType::Layout); // To avoid infinite resize loop, we only gather all active observations // that have the depth of observed target element more than current // shallowestTargetDepth. GatherAllActiveObservations(shallowestTargetDepth); } mResizeObserverNotificationHelper->Unregister(); if (HasAnySkippedObservations()) { // Per spec, we deliver an error if the document has any skipped // observations. Also, we re-register via ScheduleNotification(). RootedDictionary<ErrorEventInit> init(RootingCx()); init.mMessage.AssignLiteral( "ResizeObserver loop completed with undelivered notifications."); init.mBubbles = false; init.mCancelable = false; nsEventStatus status = nsEventStatus_eIgnore; nsCOMPtr<nsPIDOMWindowInner> window = doc->GetWindow()->GetCurrentInnerWindow(); if (window) { nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window); MOZ_ASSERT(sgo); if (NS_WARN_IF(sgo->HandleScriptError(init, &status))) { status = nsEventStatus_eIgnore; } } else { // We don't fire error events at any global for non-window JS on the main // thread. } // We need to deliver pending notifications in next cycle. ScheduleNotification(); } }
// 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; }