Skip to content

Commit ea191a7

Browse files
committed
Bug 1771092 - Part 1: Add esModuleURI key to ProcessActorSidedOptions/WindowActorSidedOptions and support loading system ESM. r=kmag
Differential Revision: https://phabricator.services.mozilla.com/D147422
1 parent 730eee4 commit ea191a7

10 files changed

+198
-74
lines changed

dom/chrome-webidl/JSProcessActor.webidl

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,24 @@ dictionary ProcessActorOptions {
6262
dictionary ProcessActorSidedOptions {
6363
/**
6464
* The JSM path which should be loaded for the actor on this side.
65-
* If not passed, the specified side cannot receive messages, but may send
66-
* them using `sendAsyncMessage` or `sendQuery`.
65+
*
66+
* Mutually exclusive with `esModuleURI`.
67+
*
68+
* If neither this nor `esModuleURI` is passed, the specified side cannot receive
69+
* messages, but may send them using `sendAsyncMessage` or `sendQuery`.
70+
*/
71+
ByteString moduleURI;
72+
73+
/**
74+
* The ESM path which should be loaded for the actor on this side.
75+
*
76+
* Mutually exclusive with `moduleURI`.
77+
*
78+
* If neither this nor `moduleURI` is passed, the specified side cannot
79+
* receive messages, but may send them using `sendAsyncMessage` or
80+
* `sendQuery`.
6781
*/
68-
required ByteString moduleURI;
82+
ByteString esModuleURI;
6983
};
7084

7185
dictionary ProcessActorChildOptions : ProcessActorSidedOptions {

dom/chrome-webidl/JSWindowActor.webidl

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,24 @@ dictionary WindowActorOptions {
127127
dictionary WindowActorSidedOptions {
128128
/**
129129
* The JSM path which should be loaded for the actor on this side.
130-
* If not passed, the specified side cannot receive messages, but may send
131-
* them using `sendAsyncMessage` or `sendQuery`.
130+
*
131+
* Mutually exclusive with `esModuleURI`.
132+
*
133+
* If neither this nor `esModuleURI` is passed, the specified side cannot receive
134+
* messages, but may send them using `sendAsyncMessage` or `sendQuery`.
135+
*/
136+
ByteString moduleURI;
137+
138+
/**
139+
* The ESM path which should be loaded for the actor on this side.
140+
*
141+
* Mutually exclusive with `moduleURI`.
142+
*
143+
* If neither this nor `moduleURI` is passed, the specified side cannot
144+
* receive messages, but may send them using `sendAsyncMessage` or
145+
* `sendQuery`.
132146
*/
133-
required ByteString moduleURI;
147+
ByteString esModuleURI;
134148
};
135149

136150
dictionary WindowActorEventListenerOptions : AddEventListenerOptions {

dom/ipc/PContent.ipdl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ struct JSWindowActorInfo
294294
nsCString name;
295295
bool allFrames;
296296

297+
// True if `url` is for ESM.
298+
// False if `url` is for JSM or nothing.
299+
bool isESModule;
300+
297301
// The module of the url.
298302
nsCString? url;
299303

@@ -310,6 +314,11 @@ struct JSProcessActorInfo
310314
{
311315
// The name of the actor.
312316
nsCString name;
317+
318+
// True if `url` is for ESM.
319+
// False if `url` is for JSM or nothing.
320+
bool isESModule;
321+
313322
// The module of the url.
314323
nsCString? url;
315324

dom/ipc/jsactor/JSActorManager.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,25 @@ already_AddRefed<JSActor> JSActorManager::GetActor(JSContext* aCx,
6565
MOZ_ASSERT(loader);
6666

6767
// If a module URI was provided, use it to construct an instance of the actor.
68-
JS::RootedObject actorObj(aCx);
69-
if (side.mModuleURI) {
70-
JS::RootedObject global(aCx);
71-
JS::RootedObject exports(aCx);
72-
aRv = loader->Import(aCx, side.mModuleURI.ref(), &global, &exports);
73-
if (aRv.Failed()) {
74-
return nullptr;
68+
JS::Rooted<JSObject*> actorObj(aCx);
69+
if (side.mModuleURI || side.mESModuleURI) {
70+
JS::Rooted<JSObject*> exports(aCx);
71+
if (side.mModuleURI) {
72+
JS::Rooted<JSObject*> global(aCx);
73+
aRv = loader->Import(aCx, side.mModuleURI.ref(), &global, &exports);
74+
if (aRv.Failed()) {
75+
return nullptr;
76+
}
77+
} else {
78+
aRv = loader->ImportESModule(aCx, side.mESModuleURI.ref(), &exports);
79+
if (aRv.Failed()) {
80+
return nullptr;
81+
}
7582
}
7683
MOZ_ASSERT(exports, "null exports!");
7784

7885
// Load the specific property from our module.
79-
JS::RootedValue ctor(aCx);
86+
JS::Rooted<JS::Value> ctor(aCx);
8087
nsAutoCString ctorName(aName);
8188
ctorName.Append(isParent ? "Parent"_ns : "Child"_ns);
8289
if (!JS_GetProperty(aCx, exports, ctorName.get(), &ctor)) {
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
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/. */
6+
7+
#ifndef mozilla_dom_JSActorProtocolUtils_h
8+
#define mozilla_dom_JSActorProtocolUtils_h
9+
10+
#include "mozilla/Assertions.h" // MOZ_ASSERT
11+
#include "mozilla/ErrorResult.h" // ErrorResult
12+
13+
namespace mozilla {
14+
15+
namespace dom {
16+
17+
class JSActorProtocolUtils {
18+
public:
19+
template <typename ProtoT, typename ActorInfoT>
20+
static void FromIPCShared(ProtoT& aProto, const ActorInfoT& aInfo) {
21+
aProto->mRemoteTypes = aInfo.remoteTypes().Clone();
22+
23+
if (aInfo.isESModule()) {
24+
aProto->mChild.mESModuleURI = aInfo.url();
25+
} else {
26+
aProto->mChild.mModuleURI = aInfo.url();
27+
}
28+
29+
aProto->mChild.mObservers = aInfo.observers().Clone();
30+
}
31+
32+
template <typename ProtoT, typename ActorInfoT>
33+
static void ToIPCShared(ActorInfoT& aInfo, const ProtoT& aProto) {
34+
aInfo.name() = aProto->mName;
35+
36+
aInfo.remoteTypes() = aProto->mRemoteTypes.Clone();
37+
38+
if (aProto->mChild.mModuleURI) {
39+
aInfo.url() = aProto->mChild.mModuleURI;
40+
aInfo.isESModule() = false;
41+
} else {
42+
aInfo.url() = aProto->mChild.mESModuleURI;
43+
aInfo.isESModule() = true;
44+
}
45+
46+
aInfo.observers() = aProto->mChild.mObservers.Clone();
47+
}
48+
49+
template <typename ProtoT, typename ActorOptionsT>
50+
static bool FromWebIDLOptionsShared(ProtoT& aProto,
51+
const ActorOptionsT& aOptions,
52+
ErrorResult& aRv) {
53+
if (aOptions.mRemoteTypes.WasPassed()) {
54+
MOZ_ASSERT(aOptions.mRemoteTypes.Value().Length());
55+
aProto->mRemoteTypes = aOptions.mRemoteTypes.Value();
56+
}
57+
58+
if (aOptions.mParent.WasPassed()) {
59+
const auto& parentOptions = aOptions.mParent.Value();
60+
61+
if (parentOptions.mModuleURI.WasPassed()) {
62+
if (parentOptions.mEsModuleURI.WasPassed()) {
63+
aRv.ThrowNotSupportedError(
64+
"moduleURI and esModuleURI are mutually exclusive.");
65+
return false;
66+
}
67+
68+
aProto->mParent.mModuleURI.emplace(parentOptions.mModuleURI.Value());
69+
} else if (parentOptions.mEsModuleURI.WasPassed()) {
70+
aProto->mParent.mESModuleURI.emplace(
71+
parentOptions.mEsModuleURI.Value());
72+
} else {
73+
aRv.ThrowNotSupportedError(
74+
"Either moduleURI or esModuleURI is required.");
75+
return false;
76+
}
77+
}
78+
if (aOptions.mChild.WasPassed()) {
79+
const auto& childOptions = aOptions.mChild.Value();
80+
81+
if (childOptions.mModuleURI.WasPassed()) {
82+
if (childOptions.mEsModuleURI.WasPassed()) {
83+
aRv.ThrowNotSupportedError(
84+
"moduleURI and esModuleURI are exclusive.");
85+
return false;
86+
}
87+
88+
aProto->mChild.mModuleURI.emplace(childOptions.mModuleURI.Value());
89+
} else if (childOptions.mEsModuleURI.WasPassed()) {
90+
aProto->mChild.mESModuleURI.emplace(childOptions.mEsModuleURI.Value());
91+
} else {
92+
aRv.ThrowNotSupportedError(
93+
"Either moduleURI or esModuleURI is required.");
94+
return false;
95+
}
96+
}
97+
98+
if (!aOptions.mChild.WasPassed() && !aOptions.mParent.WasPassed()) {
99+
aRv.ThrowNotSupportedError(
100+
"No point registering an actor with neither child nor parent "
101+
"specifications.");
102+
return false;
103+
}
104+
105+
if (aOptions.mChild.WasPassed() &&
106+
aOptions.mChild.Value().mObservers.WasPassed()) {
107+
aProto->mChild.mObservers = aOptions.mChild.Value().mObservers.Value();
108+
}
109+
110+
return true;
111+
}
112+
};
113+
114+
} // namespace dom
115+
} // namespace mozilla
116+
117+
#endif // mozilla_dom_JSActorProtocolUtils_h

dom/ipc/jsactor/JSActorService.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class JSActorProtocol : public nsISupports {
9999
public:
100100
struct Sided {
101101
Maybe<nsCString> mModuleURI;
102+
Maybe<nsCString> mESModuleURI;
102103
};
103104

104105
virtual const Sided& Parent() const = 0;

dom/ipc/jsactor/JSProcessActorProtocol.cpp

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
#include "mozilla/dom/ContentParent.h"
1313
#include "mozilla/dom/JSActorBinding.h"
1414
#include "mozilla/dom/PContent.h"
15+
1516
#include "nsContentUtils.h"
17+
#include "JSActorProtocolUtils.h"
1618

1719
namespace mozilla::dom {
1820

@@ -31,13 +33,11 @@ JSProcessActorProtocol::FromIPC(const JSProcessActorInfo& aInfo) {
3133

3234
RefPtr<JSProcessActorProtocol> proto =
3335
new JSProcessActorProtocol(aInfo.name());
36+
JSActorProtocolUtils::FromIPCShared(proto, aInfo);
3437

3538
// Content processes aren't the parent process, so this flag is irrelevant and
3639
// not propagated.
3740
proto->mIncludeParent = false;
38-
proto->mRemoteTypes = aInfo.remoteTypes().Clone();
39-
proto->mChild.mModuleURI = aInfo.url();
40-
proto->mChild.mObservers = aInfo.observers().Clone();
4141

4242
return proto.forget();
4343
}
@@ -46,10 +46,8 @@ JSProcessActorInfo JSProcessActorProtocol::ToIPC() {
4646
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
4747

4848
JSProcessActorInfo info;
49-
info.name() = mName;
50-
info.remoteTypes() = mRemoteTypes.Clone();
51-
info.url() = mChild.mModuleURI;
52-
info.observers() = mChild.mObservers.Clone();
49+
JSActorProtocolUtils::ToIPCShared(info, this);
50+
5351
return info;
5452
}
5553

@@ -60,31 +58,11 @@ JSProcessActorProtocol::FromWebIDLOptions(const nsACString& aName,
6058
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
6159

6260
RefPtr<JSProcessActorProtocol> proto = new JSProcessActorProtocol(aName);
63-
proto->mIncludeParent = aOptions.mIncludeParent;
64-
65-
if (aOptions.mRemoteTypes.WasPassed()) {
66-
MOZ_ASSERT(aOptions.mRemoteTypes.Value().Length());
67-
proto->mRemoteTypes = aOptions.mRemoteTypes.Value();
68-
}
69-
70-
if (aOptions.mParent.WasPassed()) {
71-
proto->mParent.mModuleURI.emplace(aOptions.mParent.Value().mModuleURI);
72-
}
73-
if (aOptions.mChild.WasPassed()) {
74-
proto->mChild.mModuleURI.emplace(aOptions.mChild.Value().mModuleURI);
75-
}
76-
77-
if (!aOptions.mChild.WasPassed() && !aOptions.mParent.WasPassed()) {
78-
aRv.ThrowNotSupportedError(
79-
"No point registering an actor with neither child nor parent "
80-
"specifications.");
61+
if (!JSActorProtocolUtils::FromWebIDLOptionsShared(proto, aOptions, aRv)) {
8162
return nullptr;
8263
}
8364

84-
if (aOptions.mChild.WasPassed() &&
85-
aOptions.mChild.Value().mObservers.WasPassed()) {
86-
proto->mChild.mObservers = aOptions.mChild.Value().mObservers.Value();
87-
}
65+
proto->mIncludeParent = aOptions.mIncludeParent;
8866

8967
return proto.forget();
9068
}

dom/ipc/jsactor/JSProcessActorProtocol.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace dom {
2222
struct ProcessActorOptions;
2323
class JSProcessActorInfo;
2424
class EventTarget;
25+
class JSActorProtocolUtils;
2526

2627
/**
2728
* Object corresponding to a single process actor protocol
@@ -66,6 +67,8 @@ class JSProcessActorProtocol final : public JSActorProtocol,
6667
nsTArray<nsCString> mRemoteTypes;
6768
bool mIncludeParent = false;
6869

70+
friend class JSActorProtocolUtils;
71+
6972
ParentSide mParent;
7073
ChildSide mChild;
7174
};

0 commit comments

Comments
 (0)