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);
  }
}
Beispiel #4
0
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;
}
Beispiel #5
0
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();
  }
}
Beispiel #7
0
// 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;
}