1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "MessagePort.h"
9 #include "MessageEvent.h"
10 #include "MessagePortChild.h"
11 #include "mozilla/dom/BlobBinding.h"
12 #include "mozilla/dom/Event.h"
13 #include "mozilla/dom/File.h"
14 #include "mozilla/dom/MessageChannel.h"
15 #include "mozilla/dom/MessageEventBinding.h"
16 #include "mozilla/dom/MessagePortBinding.h"
17 #include "mozilla/dom/MessagePortChild.h"
18 #include "mozilla/dom/PMessagePort.h"
19 #include "mozilla/dom/RootedDictionary.h"
20 #include "mozilla/dom/ScriptSettings.h"
21 #include "mozilla/dom/StructuredCloneTags.h"
22 #include "mozilla/dom/WorkerCommon.h"
23 #include "mozilla/dom/WorkerRef.h"
24 #include "mozilla/dom/WorkerScope.h"
25 #include "mozilla/ipc/BackgroundChild.h"
26 #include "mozilla/dom/RefMessageBodyService.h"
27 #include "mozilla/dom/SharedMessageBody.h"
28 #include "mozilla/ipc/PBackgroundChild.h"
29 #include "mozilla/ScopeExit.h"
30 #include "mozilla/Unused.h"
31 #include "nsContentUtils.h"
32 #include "nsPresContext.h"
38 namespace mozilla::dom
{
40 void UniqueMessagePortId::ForceClose() {
41 if (!mIdentifier
.neutered()) {
42 MessagePort::ForceClose(mIdentifier
);
43 mIdentifier
.neutered() = true;
47 class PostMessageRunnable final
: public CancelableRunnable
{
48 friend class MessagePort
;
51 PostMessageRunnable(MessagePort
* aPort
, SharedMessageBody
* aData
)
52 : CancelableRunnable("dom::PostMessageRunnable"),
61 NS_ASSERT_OWNINGTHREAD(Runnable
);
63 // The port can be cycle collected while this runnable is pending in
69 MOZ_ASSERT(mPort
->mPostMessageRunnable
== this);
73 // We must check if we were waiting for this message in order to shutdown
75 mPort
->UpdateMustKeepAlive();
77 mPort
->mPostMessageRunnable
= nullptr;
83 nsresult
Cancel() override
{
84 NS_ASSERT_OWNINGTHREAD(Runnable
);
92 void DispatchMessage() const {
93 NS_ASSERT_OWNINGTHREAD(Runnable
);
95 if (NS_FAILED(mPort
->CheckCurrentGlobalCorrectness())) {
99 nsCOMPtr
<nsIGlobalObject
> globalObject
= mPort
->GetParentObject();
102 if (!globalObject
|| !jsapi
.Init(globalObject
)) {
103 NS_WARNING("Failed to initialize AutoJSAPI object.");
107 JSContext
* cx
= jsapi
.cx();
109 IgnoredErrorResult rv
;
110 JS::Rooted
<JS::Value
> value(cx
);
112 mData
->Read(cx
, &value
, mPort
->mRefMessageBodyService
,
113 SharedMessageBody::ReadMethod::StealRefMessageBody
, rv
);
115 if (NS_WARN_IF(rv
.Failed())) {
116 JS_ClearPendingException(cx
);
117 mPort
->DispatchError();
122 nsCOMPtr
<mozilla::dom::EventTarget
> eventTarget
=
123 do_QueryInterface(mPort
->GetOwner());
124 RefPtr
<MessageEvent
> event
=
125 new MessageEvent(eventTarget
, nullptr, nullptr);
127 Sequence
<OwningNonNull
<MessagePort
>> ports
;
128 if (!mData
->TakeTransferredPortsAsSequence(ports
)) {
129 mPort
->DispatchError();
133 event
->InitMessageEvent(nullptr, u
"message"_ns
, CanBubble::eNo
,
134 Cancelable::eNo
, value
, u
""_ns
, u
""_ns
, nullptr,
136 event
->SetTrusted(true);
138 mPort
->DispatchEvent(*event
);
142 ~PostMessageRunnable() = default;
144 RefPtr
<MessagePort
> mPort
;
145 RefPtr
<SharedMessageBody
> mData
;
148 NS_IMPL_CYCLE_COLLECTION_CLASS(MessagePort
)
150 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MessagePort
,
151 DOMEventTargetHelper
)
152 if (tmp
->mPostMessageRunnable
) {
153 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPostMessageRunnable
->mPort
);
156 NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessagesForTheOtherPort
);
159 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
161 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MessagePort
,
162 DOMEventTargetHelper
)
163 if (tmp
->mPostMessageRunnable
) {
164 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPostMessageRunnable
->mPort
);
167 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUnshippedEntangledPort
);
168 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
170 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MessagePort
)
171 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper
)
173 NS_IMPL_ADDREF_INHERITED(MessagePort
, DOMEventTargetHelper
)
174 NS_IMPL_RELEASE_INHERITED(MessagePort
, DOMEventTargetHelper
)
176 MessagePort::MessagePort(nsIGlobalObject
* aGlobal
, State aState
)
177 : DOMEventTargetHelper(aGlobal
),
178 mRefMessageBodyService(RefMessageBodyService::GetOrCreate()),
180 mMessageQueueEnabled(false),
182 mHasBeenTransferredOrClosed(false) {
185 mIdentifier
= MakeUnique
<MessagePortIdentifier
>();
186 mIdentifier
->neutered() = true;
187 mIdentifier
->sequenceId() = 0;
190 MessagePort::~MessagePort() {
194 mActor
->SetPort(nullptr);
197 MOZ_ASSERT(!mWorkerRef
);
201 already_AddRefed
<MessagePort
> MessagePort::Create(nsIGlobalObject
* aGlobal
,
203 const nsID
& aDestinationUUID
,
207 RefPtr
<MessagePort
> mp
= new MessagePort(aGlobal
, eStateUnshippedEntangled
);
208 mp
->Initialize(aUUID
, aDestinationUUID
, 1 /* 0 is an invalid sequence ID */,
209 false /* Neutered */, aRv
);
214 already_AddRefed
<MessagePort
> MessagePort::Create(
215 nsIGlobalObject
* aGlobal
, UniqueMessagePortId
& aIdentifier
,
219 RefPtr
<MessagePort
> mp
= new MessagePort(aGlobal
, eStateEntangling
);
220 mp
->Initialize(aIdentifier
.uuid(), aIdentifier
.destinationUuid(),
221 aIdentifier
.sequenceId(), aIdentifier
.neutered(), aRv
);
222 aIdentifier
.neutered() = true;
226 void MessagePort::UnshippedEntangle(MessagePort
* aEntangledPort
) {
227 MOZ_DIAGNOSTIC_ASSERT(aEntangledPort
);
228 MOZ_DIAGNOSTIC_ASSERT(!mUnshippedEntangledPort
);
230 mUnshippedEntangledPort
= aEntangledPort
;
233 void MessagePort::Initialize(const nsID
& aUUID
, const nsID
& aDestinationUUID
,
234 uint32_t aSequenceID
, bool aNeutered
,
236 MOZ_ASSERT(mIdentifier
);
237 mIdentifier
->uuid() = aUUID
;
238 mIdentifier
->destinationUuid() = aDestinationUUID
;
239 mIdentifier
->sequenceId() = aSequenceID
;
242 // If this port is neutered we don't want to keep it alive artificially nor
243 // we want to add listeners or WorkerRefs.
244 mState
= eStateDisentangled
;
248 if (mState
== eStateEntangling
) {
249 if (!ConnectToPBackground()) {
250 aRv
.Throw(NS_ERROR_FAILURE
);
254 MOZ_ASSERT(mState
== eStateUnshippedEntangled
);
257 // The port has to keep itself alive until it's entangled.
258 UpdateMustKeepAlive();
260 if (WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate()) {
261 RefPtr
<MessagePort
> self
= this;
263 // When the callback is executed, we cannot process messages anymore because
264 // we cannot dispatch new runnables. Let's force a Close().
265 RefPtr
<StrongWorkerRef
> strongWorkerRef
= StrongWorkerRef::Create(
266 workerPrivate
, "MessagePort", [self
]() { self
->CloseForced(); });
267 if (NS_WARN_IF(!strongWorkerRef
)) {
268 // The worker is shutting down.
270 aRv
.Throw(NS_ERROR_FAILURE
);
274 MOZ_ASSERT(!mWorkerRef
);
275 mWorkerRef
= std::move(strongWorkerRef
);
279 JSObject
* MessagePort::WrapObject(JSContext
* aCx
,
280 JS::Handle
<JSObject
*> aGivenProto
) {
281 return MessagePort_Binding::Wrap(aCx
, this, aGivenProto
);
284 void MessagePort::PostMessage(JSContext
* aCx
, JS::Handle
<JS::Value
> aMessage
,
285 const Sequence
<JSObject
*>& aTransferable
,
287 // We *must* clone the data here, or the JS::Value could be modified
290 // Here we want to check if the transerable object list contains
292 for (uint32_t i
= 0; i
< aTransferable
.Length(); ++i
) {
293 JS::Rooted
<JSObject
*> object(aCx
, aTransferable
[i
]);
298 MessagePort
* port
= nullptr;
299 nsresult rv
= UNWRAP_OBJECT(MessagePort
, &object
, port
);
300 if (NS_SUCCEEDED(rv
) && port
== this) {
301 aRv
.Throw(NS_ERROR_DOM_DATA_CLONE_ERR
);
306 JS::Rooted
<JS::Value
> transferable(aCx
, JS::UndefinedValue());
308 aRv
= nsContentUtils::CreateJSValueFromSequenceOfObject(aCx
, aTransferable
,
310 if (NS_WARN_IF(aRv
.Failed())) {
314 Maybe
<nsID
> agentClusterId
;
315 nsCOMPtr
<nsIGlobalObject
> global
= GetOwnerGlobal();
317 agentClusterId
= global
->GetAgentClusterId();
320 RefPtr
<SharedMessageBody
> data
= new SharedMessageBody(
321 StructuredCloneHolder::TransferringSupported
, agentClusterId
);
323 data
->Write(aCx
, aMessage
, transferable
, mIdentifier
->uuid(),
324 mRefMessageBodyService
, aRv
);
326 if (NS_WARN_IF(aRv
.Failed())) {
330 // This message has to be ignored.
331 if (mState
> eStateEntangled
) {
335 // If we are unshipped we are connected to the other port on the same thread.
336 if (mState
== eStateUnshippedEntangled
) {
337 MOZ_DIAGNOSTIC_ASSERT(mUnshippedEntangledPort
);
338 mUnshippedEntangledPort
->mMessages
.AppendElement(data
);
339 mUnshippedEntangledPort
->Dispatch();
343 // Not entangled yet, but already closed/disentangled.
344 if (mState
== eStateEntanglingForDisentangle
||
345 mState
== eStateEntanglingForClose
) {
349 RemoveDocFromBFCache();
351 // Not entangled yet.
352 if (mState
== eStateEntangling
) {
353 mMessagesForTheOtherPort
.AppendElement(data
);
358 MOZ_ASSERT(mMessagesForTheOtherPort
.IsEmpty());
360 AutoTArray
<RefPtr
<SharedMessageBody
>, 1> array
;
361 array
.AppendElement(data
);
363 AutoTArray
<MessageData
, 1> messages
;
364 // note: `messages` will borrow the underlying buffer, but this is okay
365 // because reverse destruction order means `messages` will be destroyed prior
366 // to `array`/`data`.
367 SharedMessageBody::FromSharedToMessagesChild(mActor
->Manager(), array
,
369 mActor
->SendPostMessages(messages
);
372 void MessagePort::PostMessage(JSContext
* aCx
, JS::Handle
<JS::Value
> aMessage
,
373 const StructuredSerializeOptions
& aOptions
,
375 PostMessage(aCx
, aMessage
, aOptions
.mTransfer
, aRv
);
378 void MessagePort::Start() {
379 if (mMessageQueueEnabled
) {
383 mMessageQueueEnabled
= true;
387 void MessagePort::Dispatch() {
388 if (!mMessageQueueEnabled
|| mMessages
.IsEmpty() || mPostMessageRunnable
) {
393 case eStateUnshippedEntangled
:
394 // Everything is fine here. We have messages because the other
395 // port populates our queue directly.
398 case eStateEntangling
:
399 // Everything is fine here as well. We have messages because the other
400 // port populated our queue directly when we were in the
401 // eStateUnshippedEntangled state.
404 case eStateEntanglingForDisentangle
:
405 // Here we don't want to ship messages because these messages must be
406 // delivered by the cloned version of this one. They will be sent in the
407 // SendDisentangle().
410 case eStateEntanglingForClose
:
411 // We still want to deliver messages if we are closing. These messages
412 // are here from the previous eStateUnshippedEntangled state.
415 case eStateEntangled
:
416 // This port is up and running.
419 case eStateDisentangling
:
420 // If we are in the process to disentangle the port, we cannot dispatch
421 // messages. They will be sent to the cloned version of this port via
422 // SendDisentangle();
425 case eStateDisentangled
:
426 MOZ_CRASH("This cannot happen.");
427 // It cannot happen because Disentangle should take off all the pending
431 case eStateDisentangledForClose
:
432 // If we are here is because the port has been closed. We can still
433 // process the pending messages.
437 RefPtr
<SharedMessageBody
> data
= mMessages
.ElementAt(0);
438 mMessages
.RemoveElementAt(0);
440 mPostMessageRunnable
= new PostMessageRunnable(this, data
);
441 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToCurrentThread(mPostMessageRunnable
));
444 void MessagePort::Close() {
445 mHasBeenTransferredOrClosed
= true;
446 CloseInternal(true /* aSoftly */);
449 void MessagePort::CloseForced() { CloseInternal(false /* aSoftly */); }
451 void MessagePort::CloseInternal(bool aSoftly
) {
452 // If we have some messages to send but we don't want a 'soft' close, we have
453 // to flush them now.
458 // Let's inform the RefMessageBodyService that any our shared messages are
460 mRefMessageBodyService
->ForgetPort(mIdentifier
->uuid());
462 if (mState
== eStateUnshippedEntangled
) {
463 MOZ_DIAGNOSTIC_ASSERT(mUnshippedEntangledPort
);
465 // This avoids loops.
466 RefPtr
<MessagePort
> port
= std::move(mUnshippedEntangledPort
);
468 mState
= eStateDisentangledForClose
;
469 port
->CloseInternal(aSoftly
);
471 UpdateMustKeepAlive();
475 // Not entangled yet, we have to wait.
476 if (mState
== eStateEntangling
) {
477 mState
= eStateEntanglingForClose
;
481 // Not entangled but already cloned or closed
482 if (mState
== eStateEntanglingForDisentangle
||
483 mState
== eStateEntanglingForClose
) {
487 // Maybe we were already closing the port but softly. In this case we call
488 // UpdateMustKeepAlive() to consider the empty pending message queue.
489 if (mState
== eStateDisentangledForClose
&& !aSoftly
) {
490 UpdateMustKeepAlive();
494 if (mState
> eStateEntangled
) {
498 // We don't care about stopping the sending of messages because from now all
499 // the incoming messages will be ignored.
500 mState
= eStateDisentangledForClose
;
505 mActor
->SetPort(nullptr);
508 UpdateMustKeepAlive();
511 EventHandlerNonNull
* MessagePort::GetOnmessage() {
512 return GetEventHandler(nsGkAtoms::onmessage
);
515 void MessagePort::SetOnmessage(EventHandlerNonNull
* aCallback
) {
516 SetEventHandler(nsGkAtoms::onmessage
, aCallback
);
518 // When using onmessage, the call to start() is implied.
522 // This method is called when the PMessagePortChild actor is entangled to
523 // another actor. It receives a list of messages to be dispatch. It can be that
524 // we were waiting for this entangling step in order to disentangle the port or
526 void MessagePort::Entangled(nsTArray
<MessageData
>& aMessages
) {
527 MOZ_ASSERT(mState
== eStateEntangling
||
528 mState
== eStateEntanglingForDisentangle
||
529 mState
== eStateEntanglingForClose
);
531 State oldState
= mState
;
532 mState
= eStateEntangled
;
534 // If we have pending messages, these have to be sent.
535 if (!mMessagesForTheOtherPort
.IsEmpty()) {
537 nsTArray
<MessageData
> messages
;
538 SharedMessageBody::FromSharedToMessagesChild(
539 mActor
->Manager(), mMessagesForTheOtherPort
, messages
);
540 mActor
->SendPostMessages(messages
);
542 // Because `messages` borrow the underlying JSStructuredCloneData buffers,
543 // only clear after `messages` have gone out of scope.
544 mMessagesForTheOtherPort
.Clear();
547 // We must convert the messages into SharedMessageBodys to avoid leaks.
548 FallibleTArray
<RefPtr
<SharedMessageBody
>> data
;
550 !SharedMessageBody::FromMessagesToSharedChild(aMessages
, data
))) {
555 // If the next step is to close the port, we do it ignoring the received
557 if (oldState
== eStateEntanglingForClose
) {
562 mMessages
.AppendElements(data
);
564 // We were waiting for the entangling callback in order to disentangle this
565 // port immediately after.
566 if (oldState
== eStateEntanglingForDisentangle
) {
567 StartDisentangling();
574 void MessagePort::StartDisentangling() {
576 MOZ_ASSERT(mState
== eStateEntangled
);
578 mState
= eStateDisentangling
;
580 // Sending this message we communicate to the parent actor that we don't want
581 // to receive any new messages. It is possible that a message has been
582 // already sent but not received yet. So we have to collect all of them and
583 // we send them in the SendDispatch() request.
584 mActor
->SendStopSendingData();
587 void MessagePort::MessagesReceived(nsTArray
<MessageData
>& aMessages
) {
588 MOZ_ASSERT(mState
== eStateEntangled
|| mState
== eStateDisentangling
||
589 // This last step can happen only if Close() has been called
590 // manually. At this point SendClose() is sent but we can still
591 // receive something until the Closing request is processed.
592 mState
== eStateDisentangledForClose
);
593 MOZ_ASSERT(mMessagesForTheOtherPort
.IsEmpty());
595 RemoveDocFromBFCache();
597 FallibleTArray
<RefPtr
<SharedMessageBody
>> data
;
599 !SharedMessageBody::FromMessagesToSharedChild(aMessages
, data
))) {
604 mMessages
.AppendElements(data
);
606 if (mState
== eStateEntangled
) {
611 void MessagePort::StopSendingDataConfirmed() {
612 MOZ_ASSERT(mState
== eStateDisentangling
);
618 void MessagePort::Disentangle() {
619 MOZ_ASSERT(mState
== eStateDisentangling
);
622 mState
= eStateDisentangled
;
625 nsTArray
<MessageData
> messages
;
626 SharedMessageBody::FromSharedToMessagesChild(mActor
->Manager(), mMessages
,
628 mActor
->SendDisentangle(messages
);
631 // Let's inform the RefMessageBodyService that any our shared messages are
633 mRefMessageBodyService
->ForgetPort(mIdentifier
->uuid());
635 // Only clear mMessages after the MessageData instances have gone out of scope
636 // because they borrow mMessages' underlying JSStructuredCloneDatas.
639 mActor
->SetPort(nullptr);
642 UpdateMustKeepAlive();
645 void MessagePort::CloneAndDisentangle(UniqueMessagePortId
& aIdentifier
) {
646 MOZ_ASSERT(mIdentifier
);
647 MOZ_ASSERT(!mHasBeenTransferredOrClosed
);
649 mHasBeenTransferredOrClosed
= true;
651 // We can clone a port that has already been transfered. In this case, on the
652 // otherside will have a neutered port. Here we set neutered to true so that
653 // we are safe in case a early return.
654 aIdentifier
.neutered() = true;
656 if (mState
> eStateEntangled
) {
660 // We already have a 'next step'. We have to consider this port as already
661 // cloned/closed/disentangled.
662 if (mState
== eStateEntanglingForDisentangle
||
663 mState
== eStateEntanglingForClose
) {
667 aIdentifier
.uuid() = mIdentifier
->uuid();
668 aIdentifier
.destinationUuid() = mIdentifier
->destinationUuid();
669 aIdentifier
.sequenceId() = mIdentifier
->sequenceId() + 1;
670 aIdentifier
.neutered() = false;
672 // We have to entangle first.
673 if (mState
== eStateUnshippedEntangled
) {
674 MOZ_ASSERT(mUnshippedEntangledPort
);
675 MOZ_ASSERT(mMessagesForTheOtherPort
.IsEmpty());
677 RefPtr
<MessagePort
> port
= std::move(mUnshippedEntangledPort
);
679 // Disconnect the entangled port and connect it to PBackground.
680 if (!port
->ConnectToPBackground()) {
681 // We are probably shutting down. We cannot proceed.
682 mState
= eStateDisentangled
;
683 UpdateMustKeepAlive();
687 // In this case, we don't need to be connected to the PBackground service.
688 if (mMessages
.IsEmpty()) {
689 aIdentifier
.sequenceId() = mIdentifier
->sequenceId();
691 mState
= eStateDisentangled
;
692 UpdateMustKeepAlive();
696 // Register this component to PBackground.
697 if (!ConnectToPBackground()) {
698 // We are probably shutting down. We cannot proceed.
702 mState
= eStateEntanglingForDisentangle
;
706 // Not entangled yet, we have to wait.
707 if (mState
== eStateEntangling
) {
708 mState
= eStateEntanglingForDisentangle
;
712 MOZ_ASSERT(mState
== eStateEntangled
);
713 StartDisentangling();
716 void MessagePort::Closed() {
717 if (mState
>= eStateDisentangled
) {
721 mState
= eStateDisentangledForClose
;
724 mActor
->SetPort(nullptr);
728 UpdateMustKeepAlive();
731 bool MessagePort::ConnectToPBackground() {
732 RefPtr
<MessagePort
> self
= this;
733 auto raii
= MakeScopeExit([self
] {
734 self
->mState
= eStateDisentangled
;
735 self
->UpdateMustKeepAlive();
738 mozilla::ipc::PBackgroundChild
* actorChild
=
739 mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
740 if (NS_WARN_IF(!actorChild
)) {
744 PMessagePortChild
* actor
= actorChild
->SendPMessagePortConstructor(
745 mIdentifier
->uuid(), mIdentifier
->destinationUuid(),
746 mIdentifier
->sequenceId());
747 if (NS_WARN_IF(!actor
)) {
751 mActor
= static_cast<MessagePortChild
*>(actor
);
754 mActor
->SetPort(this);
755 mState
= eStateEntangling
;
761 void MessagePort::UpdateMustKeepAlive() {
762 if (mState
>= eStateDisentangled
&& mMessages
.IsEmpty() && mIsKeptAlive
) {
763 mIsKeptAlive
= false;
765 // The DTOR of this WorkerRef will release the worker for us.
766 mWorkerRef
= nullptr;
772 if (mState
< eStateDisentangled
&& !mIsKeptAlive
) {
778 void MessagePort::DisconnectFromOwner() {
780 DOMEventTargetHelper::DisconnectFromOwner();
783 void MessagePort::RemoveDocFromBFCache() {
784 if (!NS_IsMainThread()) {
788 if (nsPIDOMWindowInner
* window
= GetOwner()) {
789 window
->RemoveFromBFCacheSync();
794 void MessagePort::ForceClose(const MessagePortIdentifier
& aIdentifier
) {
795 mozilla::ipc::PBackgroundChild
* actorChild
=
796 mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
797 if (NS_WARN_IF(!actorChild
)) {
798 MOZ_CRASH("Failed to create a PBackgroundChild actor!");
801 Unused
<< actorChild
->SendMessagePortForceClose(aIdentifier
.uuid(),
802 aIdentifier
.destinationUuid(),
803 aIdentifier
.sequenceId());
806 void MessagePort::DispatchError() {
807 nsCOMPtr
<nsIGlobalObject
> globalObject
= GetParentObject();
810 if (!globalObject
|| !jsapi
.Init(globalObject
)) {
811 NS_WARNING("Failed to initialize AutoJSAPI object.");
815 RootedDictionary
<MessageEventInit
> init(jsapi
.cx());
816 init
.mBubbles
= false;
817 init
.mCancelable
= false;
819 RefPtr
<Event
> event
=
820 MessageEvent::Constructor(this, u
"messageerror"_ns
, init
);
821 event
->SetTrusted(true);
823 DispatchEvent(*event
);
826 } // namespace mozilla::dom