Bug 1686668 [wpt PR 27185] - Update wpt metadata, a=testonly
[gecko.git] / xpcom / components / StaticComponents.cpp.in
blobc4b340b2ff3dae0cfb96adf2fc29d8d01548ae37
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 "StaticComponents.h"
9 #include "mozilla/ArrayUtils.h"
10 #include "mozilla/PerfectHash.h"
11 #include "mozilla/ResultExtensions.h"
12 #include "mozilla/StaticPtr.h"
13 #include "mozilla/UniquePtr.h"
14 #include "mozilla/dom/ScriptSettings.h"
15 #include "mozJSComponentLoader.h"
16 #include "nsCOMPtr.h"
17 #include "nsComponentManager.h"
18 #include "nsContentUtils.h"
19 #include "nsIFactory.h"
20 #include "nsISupports.h"
21 #include "nsIXPConnect.h"
22 #include "nsString.h"
23 #include "nsStringEnumerator.h"
24 #include "nsTArray.h"
25 #include "xptinfo.h"
27 // Cleanup pollution from zipstruct.h
28 #undef UNSUPPORTED
30 // Public includes
31 //# @includes@
33 // Relative includes
34 //# @relative_includes@
36 //# @decls@
38 namespace mozilla {
40 using dom::AutoJSAPI;
42 namespace xpcom {
44 static constexpr uint32_t kNoContractID = 0xffffffff;
46 namespace {
47 // Template helpers for constructor function sanity checks.
48 template <typename T>
49 struct RemoveAlreadyAddRefed {
50 using Type = T;
53 template <typename T>
54 struct RemoveAlreadyAddRefed<already_AddRefed<T>> {
55 using Type = T;
57 } // anonymous namespace
60 uint8_t gInvalidContracts[kContractCount / 8 + 1];
62 static StaticRefPtr<nsISupports> gServiceInstances[kStaticModuleCount];
64 uint8_t gInitCalled[kModuleInitCount / 8 + 1];
66 static const char gStrings[] =
67 //# @strings@
68 "";
70 const StaticCategory gStaticCategories[kStaticCategoryCount] = {
71 //# @categories@
73 const StaticCategoryEntry gStaticCategoryEntries[] = {
74 //# @category_entries@
77 const nsXPTInterface gInterfaces[] = {
78 //# @interfaces@
81 const StringOffset gComponentJSMs[] = {
82 //# @component_jsms@
85 /**
86 * Returns a nsCString corresponding to the given entry in the `gStrings` string
87 * table. The resulting nsCString points directly to static storage, and does
88 * not incur any memory allocation overhead.
90 static inline nsCString GetString(const StringOffset& aOffset) {
91 const char* str = &gStrings[aOffset.mOffset];
92 nsCString result;
93 result.AssignLiteral(str, strlen(str));
94 return result;
97 nsCString ContractEntry::ContractID() const {
98 return GetString(mContractID);
101 bool ContractEntry::Matches(const nsACString& aContractID) const {
102 return aContractID == ContractID() && Module().Active();
106 static nsresult ConstructJSMComponent(const nsACString& aURI,
107 const char* aConstructor,
108 nsISupports** aResult) {
109 if (!nsComponentManagerImpl::JSLoaderReady()) {
110 return NS_ERROR_NOT_AVAILABLE;
113 AutoJSAPI jsapi;
114 MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()));
115 JSContext* cx = jsapi.cx();
117 JS::RootedObject global(cx);
118 JS::RootedObject exports(cx);
119 MOZ_TRY(mozJSComponentLoader::Get()->Import(cx, aURI, &global, &exports));
121 JS::RootedValue ctor(cx);
122 if (!JS_GetProperty(cx, exports, aConstructor, &ctor) ||
123 !ctor.isObject()) {
124 return NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED;
127 JS::RootedObject inst(cx);
128 if (!JS::Construct(cx, ctor, JS::HandleValueArray::empty(), &inst)) {
129 return NS_ERROR_FAILURE;
132 return nsContentUtils::XPConnect()->WrapJS(cx, inst, NS_GET_IID(nsISupports),
133 (void**)aResult);
137 //# @module_cid_table@
139 //# @module_contract_id_table@
141 //# @js_services_table@
143 static inline bool CalledInit(size_t aIdx) {
144 return GetBit(gInitCalled, aIdx);
147 static nsresult CallInitFunc(size_t aIdx) {
148 if (CalledInit(aIdx)) {
149 return NS_OK;
152 nsresult rv = NS_OK;
153 switch (aIdx) {
154 //# @init_funcs@
157 SetBit(gInitCalled, aIdx);
159 MOZ_ASSERT(NS_SUCCEEDED(rv));
160 return rv;
163 static void CallUnloadFuncs() {
164 //# @unload_funcs@
167 static nsresult CreateInstanceImpl(ModuleID aID, nsISupports* aOuter,
168 const nsIID& aIID, void** aResult) {
169 if (aOuter) {
170 return NS_ERROR_NO_AGGREGATION;
173 // The full set of constructors for all static modules.
174 // This switch statement will be compiled to a relative address jump table
175 // with no runtime relocations and a single indirect jump.
176 switch (aID) {
177 //# @constructors@
180 MOZ_ASSERT_UNREACHABLE("Constructor didn't return");
181 return NS_ERROR_FAILURE;
185 namespace {
187 class StaticModuleFactory final : public nsIFactory {
188 NS_DECL_ISUPPORTS
189 NS_DECL_NSIFACTORY
191 explicit StaticModuleFactory(ModuleID aID) : mID(aID) {}
193 private:
194 ~StaticModuleFactory() = default;
196 const ModuleID mID;
199 NS_IMPL_ISUPPORTS(StaticModuleFactory, nsIFactory)
201 NS_IMETHODIMP StaticModuleFactory::CreateInstance(nsISupports* aOuter,
202 const nsIID& aIID,
203 void** aResult) {
204 return CreateInstanceImpl(mID, aOuter, aIID, aResult);
207 NS_IMETHODIMP StaticModuleFactory::LockFactory(bool aLock) {
208 MOZ_CRASH("LockFactory is no longer a thing");
209 return NS_ERROR_NOT_IMPLEMENTED;
212 } // anonymous namespace
215 already_AddRefed<nsIFactory> StaticModule::GetFactory() const {
216 return do_AddRef(new StaticModuleFactory(ID()));
219 bool StaticModule::Active() const {
220 return FastProcessSelectorMatches(mProcessSelector);
223 bool StaticModule::Overridable() const {
224 return mContractID.mOffset != kNoContractID;
227 nsCString StaticModule::ContractID() const {
228 MOZ_ASSERT(Overridable());
229 return GetString(mContractID);
232 nsresult StaticModule::CreateInstance(nsISupports* aOuter, const nsIID& aIID,
233 void** aResult) const {
234 return CreateInstanceImpl(ID(), aOuter, aIID, aResult);
237 GetServiceHelper StaticModule::GetService() const {
238 return { ID(), nullptr };
241 GetServiceHelper StaticModule::GetService(nsresult* aRv) const {
242 return { ID(), aRv };
246 nsISupports* StaticModule::ServiceInstance() const {
247 return gServiceInstances[Idx()];
250 void StaticModule::SetServiceInstance(
251 already_AddRefed<nsISupports> aInst) const {
252 gServiceInstances[Idx()] = aInst;
256 nsCString StaticCategoryEntry::Entry() const {
257 return GetString(mEntry);
259 nsCString StaticCategoryEntry::Value() const {
260 return GetString(mValue);
262 bool StaticCategoryEntry::Active() const {
263 return FastProcessSelectorMatches(mProcessSelector);
266 nsCString StaticCategory::Name() const {
267 return GetString(mName);
270 nsCString JSServiceEntry::Name() const {
271 return GetString(mName);
274 JSServiceEntry::InterfaceList JSServiceEntry::Interfaces() const {
275 InterfaceList iids;
276 iids.SetCapacity(mInterfaceCount);
278 for (size_t i = 0; i < mInterfaceCount; i++) {
279 nsXPTInterface ifaceID = gInterfaces[mInterfaceOffset.mOffset + i];
280 iids.AppendElement(&nsXPTInterfaceInfo::Get(ifaceID)->IID());
282 return iids;
286 /* static */
287 const JSServiceEntry* JSServiceEntry::Lookup(const nsACString& aName) {
288 return LookupJSService(aName);
291 /* static */ const StaticModule* StaticComponents::LookupByCID(
292 const nsID& aCID) {
293 return ModuleByCID(aCID);
296 /* static */ const StaticModule* StaticComponents::LookupByContractID(
297 const nsACString& aContractID) {
298 if (const ContractEntry* entry = LookupContractID(aContractID)) {
299 if (!entry->Invalid()) {
300 return &entry->Module();
303 return nullptr;
306 /* static */ bool StaticComponents::InvalidateContractID(
307 const nsACString& aContractID, bool aInvalid) {
308 if (const ContractEntry* entry = LookupContractID(aContractID)) {
309 entry->SetInvalid(aInvalid);
310 return true;
312 return false;
315 /* static */ already_AddRefed<nsIUTF8StringEnumerator>
316 StaticComponents::GetComponentJSMs() {
317 auto jsms = MakeUnique<nsTArray<nsCString>>(MOZ_ARRAY_LENGTH(gComponentJSMs));
319 for (const auto& entry : gComponentJSMs) {
320 jsms->AppendElement(GetString(entry));
323 nsCOMPtr<nsIUTF8StringEnumerator> result;
324 MOZ_ALWAYS_SUCCEEDS(NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(result),
325 jsms.release()));
326 return result.forget();
329 /* static */ Span<const JSServiceEntry> StaticComponents::GetJSServices() {
330 return { gJSServices, ArrayLength(gJSServices) };
333 /* static */ void StaticComponents::Shutdown() {
334 CallUnloadFuncs();
337 /* static */ const nsID& Components::GetCID(ModuleID aID) {
338 return gStaticModules[size_t(aID)].CID();
341 nsresult GetServiceHelper::operator()(const nsIID& aIID, void** aResult) const {
342 nsresult rv =
343 nsComponentManagerImpl::gComponentManager->GetService(mId, aIID, aResult);
344 return SetResult(rv);
347 nsresult CreateInstanceHelper::operator()(const nsIID& aIID,
348 void** aResult) const {
349 const auto& entry = gStaticModules[size_t(mId)];
350 if (!entry.Active()) {
351 return SetResult(NS_ERROR_FACTORY_NOT_REGISTERED);
354 nsresult rv = entry.CreateInstance(nullptr, aIID, aResult);
355 return SetResult(rv);
358 } // namespace xpcom
359 } // namespace mozilla