Bug 1892041 - Part 1: Update test262 features. r=spidermonkey-reviewers,dminor
[gecko.git] / dom / workers / EventWithOptionsRunnable.cpp
blob2ddc56d946c930e613bf7bc73d2feb520089a6d5
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=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 https://mozilla.org/MPL/2.0/. */
7 #include "EventWithOptionsRunnable.h"
8 #include "WorkerScope.h"
9 #include "mozilla/dom/WorkerRunnable.h"
10 #include "mozilla/dom/StructuredCloneHolder.h"
11 #include "js/StructuredClone.h"
12 #include "js/RootingAPI.h"
13 #include "js/Value.h"
14 #include "nsJSPrincipals.h"
15 #include "nsContentUtils.h"
16 #include "nsDebug.h"
17 #include "MainThreadUtils.h"
18 #include "mozilla/Assertions.h"
19 #include "nsGlobalWindowInner.h"
20 #include "mozilla/DOMEventTargetHelper.h"
21 #include "mozilla/ErrorResult.h"
22 #include "nsIGlobalObject.h"
23 #include "nsCOMPtr.h"
24 #include "js/GlobalObject.h"
25 #include "xpcpublic.h"
26 #include "mozilla/dom/MessagePortBinding.h"
27 #include "mozilla/dom/MessagePort.h"
28 #include "mozilla/OwningNonNull.h"
29 #include "mozilla/RefPtr.h"
30 #include "mozilla/dom/Event.h"
31 #include "mozilla/dom/WorkerCommon.h"
33 namespace mozilla::dom {
34 EventWithOptionsRunnable::EventWithOptionsRunnable(Worker& aWorker,
35 const char* aName)
36 : WorkerDebuggeeRunnable(aWorker.mWorkerPrivate, aName,
37 WorkerRunnable::WorkerThread),
38 StructuredCloneHolder(CloningSupported, TransferringSupported,
39 StructuredCloneScope::SameProcess) {}
41 EventWithOptionsRunnable::~EventWithOptionsRunnable() = default;
43 void EventWithOptionsRunnable::InitOptions(
44 JSContext* aCx, JS::Handle<JS::Value> aOptions,
45 const Sequence<JSObject*>& aTransferable, ErrorResult& aRv) {
46 JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
48 aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
49 &transferable);
50 if (NS_WARN_IF(aRv.Failed())) {
51 return;
54 JS::CloneDataPolicy clonePolicy;
55 // DedicatedWorkers are always part of the same agent cluster.
56 clonePolicy.allowIntraClusterClonableSharedObjects();
58 MOZ_ASSERT(NS_IsMainThread());
59 nsGlobalWindowInner* win = nsContentUtils::IncumbentInnerWindow();
60 if (win && win->IsSharedMemoryAllowed()) {
61 clonePolicy.allowSharedMemoryObjects();
64 Write(aCx, aOptions, transferable, clonePolicy, aRv);
67 // Cargo-culted from MesssageEventRunnable.
68 bool EventWithOptionsRunnable::BuildAndFireEvent(
69 JSContext* aCx, WorkerPrivate* aWorkerPrivate,
70 DOMEventTargetHelper* aTarget) {
71 IgnoredErrorResult rv;
72 nsCOMPtr<nsIGlobalObject> parent = aTarget->GetParentObject();
74 // For some workers without window, parent is null and we try to find it
75 // from the JS Context.
76 if (!parent) {
77 JS::Rooted<JSObject*> globalObject(aCx, JS::CurrentGlobalOrNull(aCx));
78 if (NS_WARN_IF(!globalObject)) {
79 rv.ThrowDataCloneError("failed to get global object");
80 OptionsDeserializeFailed(rv);
81 return false;
84 parent = xpc::NativeGlobal(globalObject);
85 if (NS_WARN_IF(!parent)) {
86 rv.ThrowDataCloneError("failed to get parent");
87 OptionsDeserializeFailed(rv);
88 return false;
92 MOZ_ASSERT(parent);
94 JS::Rooted<JS::Value> options(aCx);
96 JS::CloneDataPolicy cloneDataPolicy;
97 if (parent->GetClientInfo().isSome() &&
98 parent->GetClientInfo()->AgentClusterId().isSome() &&
99 parent->GetClientInfo()->AgentClusterId()->Equals(
100 aWorkerPrivate->AgentClusterId())) {
101 cloneDataPolicy.allowIntraClusterClonableSharedObjects();
104 if (aWorkerPrivate->IsSharedMemoryAllowed()) {
105 cloneDataPolicy.allowSharedMemoryObjects();
108 Read(parent, aCx, &options, cloneDataPolicy, rv);
110 if (NS_WARN_IF(rv.Failed())) {
111 OptionsDeserializeFailed(rv);
112 return false;
115 Sequence<OwningNonNull<MessagePort>> ports;
116 if (NS_WARN_IF(!TakeTransferredPortsAsSequence(ports))) {
117 // TODO: Is this an appropriate type? What does this actually do?
118 rv.ThrowDataCloneError("TakeTransferredPortsAsSequence failed");
119 OptionsDeserializeFailed(rv);
120 return false;
123 RefPtr<dom::Event> event = BuildEvent(aCx, parent, aTarget, options);
125 if (NS_WARN_IF(!event)) {
126 return false;
129 aTarget->DispatchEvent(*event);
130 return true;
133 bool EventWithOptionsRunnable::WorkerRun(JSContext* aCx,
134 WorkerPrivate* aWorkerPrivate) {
135 if (mTarget == ParentThread) {
136 // Don't fire this event if the JS object has been disconnected from the
137 // private object.
138 if (!aWorkerPrivate->IsAcceptingEvents()) {
139 return true;
142 aWorkerPrivate->AssertInnerWindowIsCorrect();
144 return BuildAndFireEvent(aCx, aWorkerPrivate,
145 aWorkerPrivate->ParentEventTargetRef());
148 MOZ_ASSERT(aWorkerPrivate == GetWorkerPrivateFromContext(aCx));
149 MOZ_ASSERT(aWorkerPrivate->GlobalScope());
151 // If the worker start shutting down, don't dispatch the event.
152 if (NS_FAILED(
153 aWorkerPrivate->GlobalScope()->CheckCurrentGlobalCorrectness())) {
154 return true;
157 return BuildAndFireEvent(aCx, aWorkerPrivate, aWorkerPrivate->GlobalScope());
160 } // namespace mozilla::dom