Bug 1769002 - Support ESM in components.conf. r=kmag

Also ESM-ify SimpleServices.jsm as an example, given an empty array is not
allowed inside StaticComponents.cpp.

Differential Revision: https://phabricator.services.mozilla.com/D147414
This commit is contained in:
Tooru Fujisawa 2022-06-16 16:20:37 +00:00
Родитель 3d15caadb4
Коммит 591472f193
9 изменённых файлов: 97 добавлений и 16 удалений

Просмотреть файл

@ -832,6 +832,7 @@ add_task(async function checkAllTheFiles() {
".mjs",
".js",
".jsm",
".mjs",
".json",
".html",
".xhtml",
@ -880,6 +881,9 @@ add_task(async function checkAllTheFiles() {
for (let jsm of Components.manager.getComponentJSMs()) {
gReferencesFromCode.set(jsm, null);
}
for (let esModule of Components.manager.getComponentESModules()) {
gReferencesFromCode.set(esModule, null);
}
// manifest.json is a common name, it is used for WebExtension manifests
// but also for other things. To tell them apart, we have to actually

Просмотреть файл

@ -14,6 +14,7 @@
/* globals WebExtensionPolicy */
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
@ -25,7 +26,6 @@ ChromeUtils.defineModuleGetter(
"NetUtil",
"resource://gre/modules/NetUtil.jsm"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyServiceGetter(
lazy,
@ -46,7 +46,7 @@ const ArrayBufferInputStream = Components.Constructor(
* See SubstituteChannel in netwerk/protocol/res/ExtensionProtocolHandler.cpp
* for usage.
*/
function AddonLocalizationConverter() {}
export function AddonLocalizationConverter() {}
AddonLocalizationConverter.prototype = {
QueryInterface: ChromeUtils.generateQI(["nsIStreamConverter"]),
@ -137,7 +137,7 @@ AddonLocalizationConverter.prototype = {
},
};
function HttpIndexViewer() {}
export function HttpIndexViewer() {}
HttpIndexViewer.prototype = {
QueryInterface: ChromeUtils.generateQI(["nsIDocumentLoaderFactory"]),
@ -180,5 +180,3 @@ HttpIndexViewer.prototype = {
return res;
},
};
var EXPORTED_SYMBOLS = ["AddonLocalizationConverter", "HttpIndexViewer"];

Просмотреть файл

@ -8,13 +8,13 @@ Classes = [
{
'cid': '{ded150e3-c92e-4077-a396-0dba9953e39f}',
'contract_ids': ['@mozilla.org/streamconv;1?from=application/vnd.mozilla.webext.unlocalized&to=text/css'],
'jsm': 'resource://gre/modules/SimpleServices.jsm',
'esModule': 'resource://gre/modules/SimpleServices.sys.mjs',
'constructor': 'AddonLocalizationConverter',
},
{
'cid': '{742ad274-34c5-43d1-a8b7-293eaf8962d6}',
'contract_ids': ['@mozilla.org/content-viewers/http-index-format'],
'jsm': 'resource://gre/modules/SimpleServices.jsm',
'esModule': 'resource://gre/modules/SimpleServices.sys.mjs',
'constructor': 'HttpIndexViewer',
'categories': {'Gecko-Content-Viewers': 'application/http-index-format'},
},

Просмотреть файл

@ -8,7 +8,7 @@ with Files("**"):
BUG_COMPONENT = ("Toolkit", "General")
EXTRA_JS_MODULES += [
"SimpleServices.jsm",
"SimpleServices.sys.mjs",
]
EXTRA_JS_MODULES["components-utils"] = [

Просмотреть файл

@ -87,6 +87,10 @@ const StringOffset gComponentJSMs[] = {
//# @component_jsms@
};
const StringOffset gComponentESModules[] = {
//# @component_esmodules@
};
/**
* Returns a nsCString corresponding to the given entry in the `gStrings` string
* table. The resulting nsCString points directly to static storage, and does
@ -107,10 +111,12 @@ bool ContractEntry::Matches(const nsACString& aContractID) const {
return aContractID == ContractID() && Module().Active();
}
enum class ComponentType { JSM, ESM };
static nsresult ConstructJSMComponent(const nsACString& aURI,
const char* aConstructor,
nsISupports** aResult) {
template <ComponentType type>
static nsresult ConstructJSMOrESMComponent(const nsACString& aURI,
const char* aConstructor,
nsISupports** aResult) {
if (!nsComponentManagerImpl::JSLoaderReady()) {
return NS_ERROR_NOT_AVAILABLE;
}
@ -119,17 +125,21 @@ static nsresult ConstructJSMComponent(const nsACString& aURI,
MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()));
JSContext* cx = jsapi.cx();
JS::RootedObject global(cx);
JS::RootedObject exports(cx);
MOZ_TRY(mozJSComponentLoader::Get()->Import(cx, aURI, &global, &exports));
JS::Rooted<JSObject*> exports(cx);
if constexpr (type == ComponentType::JSM) {
JS::Rooted<JSObject*> global(cx);
MOZ_TRY(mozJSComponentLoader::Get()->Import(cx, aURI, &global, &exports));
} else {
MOZ_TRY(mozJSComponentLoader::Get()->ImportESModule(cx, aURI, &exports));
}
JS::RootedValue ctor(cx);
JS::Rooted<JS::Value> ctor(cx);
if (!JS_GetProperty(cx, exports, aConstructor, &ctor) ||
!ctor.isObject()) {
return NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED;
}
JS::RootedObject inst(cx);
JS::Rooted<JSObject*> inst(cx);
if (!JS::Construct(cx, ctor, JS::HandleValueArray::empty(), &inst)) {
return NS_ERROR_FAILURE;
}
@ -138,6 +148,19 @@ static nsresult ConstructJSMComponent(const nsACString& aURI,
(void**)aResult);
}
static nsresult ConstructJSMComponent(const nsACString& aURI,
const char* aConstructor,
nsISupports** aResult) {
return ConstructJSMOrESMComponent<ComponentType::JSM>(
aURI, aConstructor, aResult);
}
static nsresult ConstructESModuleComponent(const nsACString& aURI,
const char* aConstructor,
nsISupports** aResult) {
return ConstructJSMOrESMComponent<ComponentType::ESM>(
aURI, aConstructor, aResult);
}
//# @module_cid_table@
@ -330,6 +353,20 @@ StaticComponents::GetComponentJSMs() {
return result.forget();
}
/* static */ already_AddRefed<nsIUTF8StringEnumerator>
StaticComponents::GetComponentESModules() {
auto esModules = MakeUnique<nsTArray<nsCString>>(MOZ_ARRAY_LENGTH(gComponentESModules));
for (const auto& entry : gComponentESModules) {
esModules->AppendElement(GetString(entry));
}
nsCOMPtr<nsIUTF8StringEnumerator> result;
MOZ_ALWAYS_SUCCEEDS(NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(result),
esModules.release()));
return result.forget();
}
/* static */ Span<const JSServiceEntry> StaticComponents::GetJSServices() {
return { gJSServices, ArrayLength(gJSServices) };
}

Просмотреть файл

@ -243,6 +243,7 @@ class StaticComponents final {
bool aInvalid = true);
static already_AddRefed<nsIUTF8StringEnumerator> GetComponentJSMs();
static already_AddRefed<nsIUTF8StringEnumerator> GetComponentESModules();
static Span<const JSServiceEntry> GetJSServices();

Просмотреть файл

@ -282,6 +282,7 @@ class ModuleEntry(object):
self.init_method = data.get("init_method", [])
self.jsm = data.get("jsm", None)
self.esModule = data.get("esModule", None)
self.external = data.get(
"external", not (self.headers or self.legacy_constructor)
@ -307,6 +308,16 @@ class ModuleEntry(object):
if not self.constructor:
error("JavaScript components must specify a constructor")
for prop in ("init_method", "legacy_constructor", "headers"):
if getattr(self, prop):
error(
"JavaScript components may not specify a '%s' "
"property" % prop
)
elif self.esModule:
if not self.constructor:
error("JavaScript components must specify a constructor")
for prop in ("init_method", "legacy_constructor", "headers"):
if getattr(self, prop):
error(
@ -413,6 +424,14 @@ class ModuleEntry(object):
" getter_AddRefs(inst)));"
"\n" % (json.dumps(self.jsm), json.dumps(self.constructor))
)
elif self.esModule:
res += (
" nsCOMPtr<nsISupports> inst;\n"
" MOZ_TRY(ConstructESModuleComponent(nsLiteralCString(%s),\n"
" %s,\n"
" getter_AddRefs(inst)));"
"\n" % (json.dumps(self.esModule), json.dumps(self.constructor))
)
elif self.external:
res += (
" nsCOMPtr<nsISupports> inst = "
@ -743,6 +762,7 @@ def gen_substs(manifests):
js_services = {}
jsms = set()
esModules = set()
types = set()
@ -767,6 +787,9 @@ def gen_substs(manifests):
if mod.jsm:
jsms.add(mod.jsm)
if mod.esModule:
esModules.add(mod.esModule)
if mod.js_name:
if mod.js_name in js_services:
raise Exception("Duplicate JS service name: %s" % mod.js_name)
@ -805,6 +828,9 @@ def gen_substs(manifests):
substs["component_jsms"] = (
"\n".join(" %s," % strings.entry_to_cxx(jsm) for jsm in sorted(jsms)) + "\n"
)
substs["component_esmodules"] = (
"\n".join(" %s," % strings.entry_to_cxx(esModule) for esModule in sorted(esModules)) + "\n"
)
substs["interfaces"] = gen_interfaces(interfaces)

Просмотреть файл

@ -1877,6 +1877,15 @@ nsComponentManagerImpl::GetComponentJSMs(nsIUTF8StringEnumerator** aJSMs) {
return NS_OK;
}
NS_IMETHODIMP
nsComponentManagerImpl::GetComponentESModules(
nsIUTF8StringEnumerator** aESModules) {
nsCOMPtr<nsIUTF8StringEnumerator> result =
StaticComponents::GetComponentESModules();
result.forget(aESModules);
return NS_OK;
}
NS_IMETHODIMP
nsComponentManagerImpl::GetManifestLocations(nsIArray** aLocations) {
NS_ENSURE_ARG_POINTER(aLocations);

Просмотреть файл

@ -101,6 +101,12 @@ interface nsIComponentManager : nsISupports
* should only be used in automation.
*/
nsIUTF8StringEnumerator getComponentJSMs();
/**
* Returns a list of ESM URLs which are used to create components. This
* should only be used in automation.
*/
nsIUTF8StringEnumerator getComponentESModules();
};