Bug 1524688: Part 1a - Support static registration JS components. r=mccr8

--HG--
extra : source : 68eb174a337b20e64583ae8afd45d479a3f54b61
This commit is contained in:
Kris Maglione 2019-01-29 17:46:27 -08:00
parent b718cffa0e
commit a34d453ee8
5 changed files with 68 additions and 2 deletions

View File

@ -102,6 +102,12 @@ Class definitions may have the following properties:
This property is incompatible with ``legacy_constructor``.
``jsm`` (optional)
If provided, must be the URL of a JavaScript module which contains a
JavaScript implementation of the component. The ``constructor`` property
must contain the name of an exported function which can be constructed to
create a new instance of the component.
``legacy_constructor`` (optional)
This property is deprecated, and should not be used in new code.

View File

@ -9,8 +9,11 @@
#include "mozilla/PerfectHash.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozJSComponentLoader.h"
#include "nsCOMPtr.h"
#include "nsComponentManager.h"
#include "nsContentUtils.h"
#include "nsIFactory.h"
#include "nsISupports.h"
#include "nsString.h"
@ -27,6 +30,9 @@
//# @decls@
namespace mozilla {
using dom::AutoJSAPI;
namespace xpcom {
static constexpr uint32_t kNoContractID = 0xffffffff;
@ -83,6 +89,37 @@ bool ContractEntry::Matches(const nsACString& aContractID) const {
}
static nsresult ConstructJSMComponent(const nsACString& aURI,
const char* aConstructor,
nsISupports** aResult) {
if (!nsComponentManagerImpl::JSLoaderReady()) {
return NS_ERROR_NOT_AVAILABLE;
}
AutoJSAPI jsapi;
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::RootedValue ctor(cx);
if (!JS_GetProperty(cx, exports, aConstructor, &ctor) ||
!ctor.isObject()) {
return NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED;
}
JS::RootedObject inst(cx);
if (!JS::Construct(cx, ctor, JS::HandleValueArray::empty(), &inst)) {
return NS_ERROR_FAILURE;
}
return nsContentUtils::XPConnect()->WrapJS(cx, inst, NS_GET_IID(nsISupports),
(void**)aResult);
}
//# @module_cid_table@
//# @module_contract_id_table@

View File

@ -218,6 +218,8 @@ class ModuleEntry(object):
self.legacy_constructor = data.get('legacy_constructor', None)
self.init_method = data.get('init_method', [])
self.jsm = data.get('jsm', None)
self.external = data.get('external', not (self.headers or
self.legacy_constructor))
self.singleton = data.get('singleton', False)
@ -236,7 +238,15 @@ class ModuleEntry(object):
str(self.cid), ', '.join(map(repr, self.contract_ids)),
str_))
if self.external:
if self.jsm:
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.external:
if self.constructor or self.legacy_constructor:
error("Externally-constructed components may not specify "
"'constructor' or 'legacy_constructor' properties")
@ -299,7 +309,14 @@ class ModuleEntry(object):
% self.legacy_constructor)
return res
if self.external:
if self.jsm:
res += (
' nsCOMPtr<nsISupports> inst;\n'
' MOZ_TRY(ConstructJSMComponent(NS_LITERAL_CSTRING(%s),\n'
' %s,\n'
' getter_AddRefs(inst)));'
'\n' % (json.dumps(self.jsm), json.dumps(self.constructor)))
elif self.external:
res += (' nsCOMPtr<nsISupports> inst = '
'mozCreateComponent<%s>();\n' % self.type)
else:

View File

@ -531,6 +531,8 @@ nsresult nsComponentManagerImpl::Init() {
// used, and before any calls are made into the JS engine.
nsLayoutModuleInitialize();
mJSLoaderReady = true;
// The overall order in which chrome.manifests are expected to be treated
// is the following:
// - greDir

View File

@ -166,6 +166,8 @@ class nsComponentManagerImpl final : public nsIComponentManager,
nsresult GetService(mozilla::xpcom::ModuleID, const nsIID& aIID,
void** aResult);
static bool JSLoaderReady() { return gComponentManager->mJSLoaderReady; }
static void InitializeStaticModules();
static void InitializeModuleLocations();
@ -281,6 +283,8 @@ class nsComponentManagerImpl final : public nsIComponentManager,
nsTArray<PendingServiceInfo> mPendingServices;
bool mJSLoaderReady = false;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
private: