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 https://mozilla.org/MPL/2.0/. */
6
7 /**
8 * Structures and methods with information about XPCOM interfaces for use by
9 * XPConnect. The static backing data structures used by this file are generated
10 * from xpidl interfaces by the jsonxpt.py and xptcodegen.py scripts.
11 */
12
13 #ifndef xptinfo_h
14 #define xptinfo_h
15
16 #include <stdint.h>
17 #include "nsID.h"
18 #include "mozilla/Assertions.h"
19 #include "jsapi.h"
20 #include "js/Symbol.h"
21 #include "js/Value.h"
22 #include "nsString.h"
23 #include "nsTArray.h"
24
25 // Forward Declarations
26 namespace mozilla {
27 namespace dom {
28 struct NativePropertyHooks;
29 } // namespace dom
30 } // namespace mozilla
31
32 struct nsXPTInterfaceInfo;
33 struct nsXPTType;
34 struct nsXPTParamInfo;
35 struct nsXPTMethodInfo;
36 struct nsXPTConstantInfo;
37 struct nsXPTDOMObjectInfo;
38
39 // Internal helper methods.
40 namespace xpt {
41 namespace detail {
42
43 inline const nsXPTInterfaceInfo* GetInterface(uint16_t aIndex);
44 inline const nsXPTType& GetType(uint16_t aIndex);
45 inline const nsXPTParamInfo& GetParam(uint16_t aIndex);
46 inline const nsXPTMethodInfo& GetMethod(uint16_t aIndex);
47 inline const nsXPTConstantInfo& GetConstant(uint16_t aIndex);
48 inline const nsXPTDOMObjectInfo& GetDOMObjectInfo(uint16_t aIndex);
49 inline const char* GetString(uint32_t aIndex);
50
51 const nsXPTInterfaceInfo* InterfaceByIID(const nsIID& aIID);
52 const nsXPTInterfaceInfo* InterfaceByName(const char* aName);
53
54 extern const uint16_t sInterfacesSize;
55
56 } // namespace detail
57 } // namespace xpt
58
59 /*
60 * An Interface describes a single XPCOM interface, including all of its
61 * methods. We don't record non-scriptable interfaces.
62 */
63 struct nsXPTInterfaceInfo {
64 // High efficiency getters for Interfaces based on perfect hashes.
ByIIDnsXPTInterfaceInfo65 static const nsXPTInterfaceInfo* ByIID(const nsIID& aIID) {
66 return xpt::detail::InterfaceByIID(aIID);
67 }
ByNamensXPTInterfaceInfo68 static const nsXPTInterfaceInfo* ByName(const char* aName) {
69 return xpt::detail::InterfaceByName(aName);
70 }
71
72 // These are only needed for Components_interfaces's enumerator.
ByIndexnsXPTInterfaceInfo73 static const nsXPTInterfaceInfo* ByIndex(uint16_t aIndex) {
74 // NOTE: We add 1 here, as the internal index 0 is reserved for null.
75 return xpt::detail::GetInterface(aIndex + 1);
76 }
InterfaceCountnsXPTInterfaceInfo77 static uint16_t InterfaceCount() { return xpt::detail::sInterfacesSize; }
78
79 // Interface flag getters
IsFunctionnsXPTInterfaceInfo80 bool IsFunction() const { return mFunction; }
IsBuiltinClassnsXPTInterfaceInfo81 bool IsBuiltinClass() const { return mBuiltinClass; }
IsMainProcessScriptableOnlynsXPTInterfaceInfo82 bool IsMainProcessScriptableOnly() const {
83 return mMainProcessScriptableOnly;
84 }
85
NamensXPTInterfaceInfo86 const char* Name() const { return xpt::detail::GetString(mName); }
IIDnsXPTInterfaceInfo87 const nsIID& IID() const { return mIID; }
88
89 // Get the parent interface, or null if this interface doesn't have a parent.
GetParentnsXPTInterfaceInfo90 const nsXPTInterfaceInfo* GetParent() const {
91 return xpt::detail::GetInterface(mParent);
92 }
93
94 // Do we have an ancestor interface with the given IID?
95 bool HasAncestor(const nsIID& aIID) const;
96
97 // Get methods & constants
ConstantCountnsXPTInterfaceInfo98 uint16_t ConstantCount() const { return mNumConsts; }
99 const nsXPTConstantInfo& Constant(uint16_t aIndex) const;
MethodCountnsXPTInterfaceInfo100 uint16_t MethodCount() const { return mNumMethods; }
101 const nsXPTMethodInfo& Method(uint16_t aIndex) const;
102
103 nsresult GetMethodInfo(uint16_t aIndex, const nsXPTMethodInfo** aInfo) const;
104 nsresult GetConstant(uint16_t aIndex, JS::MutableHandleValue constant,
105 char** aName) const;
106
107 ////////////////////////////////////////////////////////////////
108 // Ensure these fields are in the same order as xptcodegen.py //
109 ////////////////////////////////////////////////////////////////
110
111 nsID mIID;
112 uint32_t mName; // Index into xpt::detail::sStrings
113
114 uint16_t mParent : 14;
115 uint16_t mBuiltinClass : 1;
116 // XXX(nika): Do we need this if we don't have addons anymore?
117 uint16_t mMainProcessScriptableOnly : 1;
118
119 uint16_t mMethods; // Index into xpt::detail::sMethods
120
121 uint16_t mConsts : 14; // Index into xpt::detail::sConsts
122 uint16_t mFunction : 1;
123 // uint16_t unused : 1;
124
125 uint8_t mNumMethods; // NOTE(24/04/18): largest=nsIDocShell (193)
126 uint8_t mNumConsts; // NOTE(24/04/18): largest=nsIAccessibleRole (175)
127 };
128
129 // The fields in nsXPTInterfaceInfo were carefully ordered to minimize size.
130 static_assert(sizeof(nsXPTInterfaceInfo) == 28, "wrong size?");
131
132 /*
133 * The following enum represents contains the different tag types which
134 * can be found in nsXPTTypeInfo::mTag.
135 *
136 * WARNING: mTag is 5 bits wide, supporting at most 32 tags.
137 */
138 enum nsXPTTypeTag : uint8_t {
139 // Arithmetic (POD) Types
140 // - Do not require cleanup,
141 // - All bit patterns are valid,
142 // - Outparams may be uninitialized by caller,
143 // - Directly supported in xptcall.
144 //
145 // NOTE: The name 'Arithmetic' comes from Harbison/Steele. Despite being a tad
146 // unclear, it is used frequently in xptcall, so is unlikely to be changed.
147 TD_INT8 = 0,
148 TD_INT16 = 1,
149 TD_INT32 = 2,
150 TD_INT64 = 3,
151 TD_UINT8 = 4,
152 TD_UINT16 = 5,
153 TD_UINT32 = 6,
154 TD_UINT64 = 7,
155 TD_FLOAT = 8,
156 TD_DOUBLE = 9,
157 TD_BOOL = 10,
158 TD_CHAR = 11,
159 TD_WCHAR = 12,
160 _TD_LAST_ARITHMETIC = TD_WCHAR,
161
162 // Pointer Types
163 // - Require cleanup unless NULL,
164 // - All-zeros (NULL) bit pattern is valid,
165 // - Outparams may be uninitialized by caller,
166 // - Supported in xptcall as raw pointer.
167 TD_VOID = 13,
168 TD_NSIDPTR = 14,
169 TD_PSTRING = 15,
170 TD_PWSTRING = 16,
171 TD_INTERFACE_TYPE = 17,
172 TD_INTERFACE_IS_TYPE = 18,
173 TD_LEGACY_ARRAY = 19,
174 TD_PSTRING_SIZE_IS = 20,
175 TD_PWSTRING_SIZE_IS = 21,
176 TD_DOMOBJECT = 22,
177 TD_PROMISE = 23,
178 _TD_LAST_POINTER = TD_PROMISE,
179
180 // Complex Types
181 // - Require cleanup,
182 // - Always passed indirectly,
183 // - Outparams must be initialized by caller,
184 // - Supported in xptcall due to indirection.
185 TD_UTF8STRING = 24,
186 TD_CSTRING = 25,
187 TD_ASTRING = 26,
188 TD_NSID = 27,
189 TD_JSVAL = 28,
190 TD_ARRAY = 29,
191 _TD_LAST_COMPLEX = TD_ARRAY
192 };
193
194 static_assert(_TD_LAST_COMPLEX < 32, "nsXPTTypeTag must fit in 5 bits");
195
196 /*
197 * A nsXPTType is a union used to identify the type of a method argument or
198 * return value. The internal data is stored as an 5-bit tag, and two 8-bit
199 * integers, to keep alignment requirements low.
200 *
201 * nsXPTType contains 3 extra bits, reserved for use by nsXPTParamInfo.
202 */
203 struct nsXPTType {
TagnsXPTType204 nsXPTTypeTag Tag() const { return static_cast<nsXPTTypeTag>(mTag); }
205
206 // The index in the function argument list which should be used when
207 // determining the iid_is or size_is properties of this dependent type.
ArgNumnsXPTType208 uint8_t ArgNum() const {
209 MOZ_ASSERT(Tag() == TD_INTERFACE_IS_TYPE || Tag() == TD_PSTRING_SIZE_IS ||
210 Tag() == TD_PWSTRING_SIZE_IS || Tag() == TD_LEGACY_ARRAY);
211 return mData1;
212 }
213
214 private:
215 // Helper for reading 16-bit data values split between mData1 and mData2.
Data16nsXPTType216 uint16_t Data16() const {
217 return static_cast<uint16_t>(mData1 << 8) | mData2;
218 }
219
220 public:
221 // Get the type of the element in the current array or sequence. Arrays only
222 // fit 8 bits of type data, while sequences support up to 16 bits of type data
223 // due to not needing to store an ArgNum.
ArrayElementTypensXPTType224 const nsXPTType& ArrayElementType() const {
225 if (Tag() == TD_LEGACY_ARRAY) {
226 return xpt::detail::GetType(mData2);
227 }
228 MOZ_ASSERT(Tag() == TD_ARRAY);
229 return xpt::detail::GetType(Data16());
230 }
231
232 // We store the 16-bit iface value as two 8-bit values in order to
233 // avoid 16-bit alignment requirements for XPTTypeDescriptor, which
234 // reduces its size and also the size of XPTParamDescriptor.
GetInterfacensXPTType235 const nsXPTInterfaceInfo* GetInterface() const {
236 MOZ_ASSERT(Tag() == TD_INTERFACE_TYPE);
237 return xpt::detail::GetInterface(Data16());
238 }
239
GetDOMObjectInfonsXPTType240 const nsXPTDOMObjectInfo& GetDOMObjectInfo() const {
241 MOZ_ASSERT(Tag() == TD_DOMOBJECT);
242 return xpt::detail::GetDOMObjectInfo(Data16());
243 }
244
245 // See the comments in nsXPTTypeTag for an explanation as to what each of
246 // these categories mean.
IsArithmeticnsXPTType247 bool IsArithmetic() const { return Tag() <= _TD_LAST_ARITHMETIC; }
IsPointernsXPTType248 bool IsPointer() const {
249 return !IsArithmetic() && Tag() <= _TD_LAST_POINTER;
250 }
IsComplexnsXPTType251 bool IsComplex() const { return Tag() > _TD_LAST_POINTER; }
252
IsInterfacePointernsXPTType253 bool IsInterfacePointer() const {
254 return Tag() == TD_INTERFACE_TYPE || Tag() == TD_INTERFACE_IS_TYPE;
255 }
256
IsDependentnsXPTType257 bool IsDependent() const {
258 return (Tag() == TD_ARRAY && InnermostType().IsDependent()) ||
259 Tag() == TD_INTERFACE_IS_TYPE || Tag() == TD_LEGACY_ARRAY ||
260 Tag() == TD_PSTRING_SIZE_IS || Tag() == TD_PWSTRING_SIZE_IS;
261 }
262
263 // Unwrap a nested type to its innermost value (e.g. through arrays).
InnermostTypensXPTType264 const nsXPTType& InnermostType() const {
265 if (Tag() == TD_LEGACY_ARRAY || Tag() == TD_ARRAY) {
266 return ArrayElementType().InnermostType();
267 }
268 return *this;
269 }
270
271 // In-memory size of native type in bytes.
272 inline size_t Stride() const;
273
274 // Offset the given base pointer to reference the element at the given index.
ElementPtrnsXPTType275 void* ElementPtr(const void* aBase, uint32_t aIndex) const {
276 return (char*)aBase + (aIndex * Stride());
277 }
278
279 // Zero out a native value of the given type. The type must not be 'complex'.
ZeroValuensXPTType280 void ZeroValue(void* aValue) const {
281 MOZ_RELEASE_ASSERT(!IsComplex(), "Cannot zero a complex value");
282 memset(aValue, 0, Stride());
283 }
284
285 // Indexes into the extra types array of a small set of known types.
286 enum class Idx : uint8_t {
287 INT8 = 0,
288 UINT8,
289 INT16,
290 UINT16,
291 INT32,
292 UINT32,
293 INT64,
294 UINT64,
295 FLOAT,
296 DOUBLE,
297 BOOL,
298 CHAR,
299 WCHAR,
300 NSIDPTR,
301 PSTRING,
302 PWSTRING,
303 INTERFACE_IS_TYPE
304 };
305
306 // Helper methods for fabricating nsXPTType values used by xpconnect.
MkArrayTypensXPTType307 static nsXPTType MkArrayType(Idx aInner) {
308 MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE);
309 return {TD_LEGACY_ARRAY, false, false, false, 0, (uint8_t)aInner};
310 }
GetnsXPTType311 static const nsXPTType& Get(Idx aInner) {
312 MOZ_ASSERT(aInner <= Idx::INTERFACE_IS_TYPE);
313 return xpt::detail::GetType((uint8_t)aInner);
314 }
315
316 ///////////////////////////////////////
317 // nsXPTType backwards compatibility //
318 ///////////////////////////////////////
319
320 nsXPTType& operator=(nsXPTTypeTag aPrefix) {
321 mTag = aPrefix;
322 return *this;
323 }
nsXPTTypeTagnsXPTType324 operator nsXPTTypeTag() const { return Tag(); }
325
326 #define TD_ALIAS_(name_, value_) static constexpr nsXPTTypeTag name_ = value_
327 TD_ALIAS_(T_I8, TD_INT8);
328 TD_ALIAS_(T_I16, TD_INT16);
329 TD_ALIAS_(T_I32, TD_INT32);
330 TD_ALIAS_(T_I64, TD_INT64);
331 TD_ALIAS_(T_U8, TD_UINT8);
332 TD_ALIAS_(T_U16, TD_UINT16);
333 TD_ALIAS_(T_U32, TD_UINT32);
334 TD_ALIAS_(T_U64, TD_UINT64);
335 TD_ALIAS_(T_FLOAT, TD_FLOAT);
336 TD_ALIAS_(T_DOUBLE, TD_DOUBLE);
337 TD_ALIAS_(T_BOOL, TD_BOOL);
338 TD_ALIAS_(T_CHAR, TD_CHAR);
339 TD_ALIAS_(T_WCHAR, TD_WCHAR);
340 TD_ALIAS_(T_VOID, TD_VOID);
341 TD_ALIAS_(T_NSIDPTR, TD_NSIDPTR);
342 TD_ALIAS_(T_CHAR_STR, TD_PSTRING);
343 TD_ALIAS_(T_WCHAR_STR, TD_PWSTRING);
344 TD_ALIAS_(T_INTERFACE, TD_INTERFACE_TYPE);
345 TD_ALIAS_(T_INTERFACE_IS, TD_INTERFACE_IS_TYPE);
346 TD_ALIAS_(T_LEGACY_ARRAY, TD_LEGACY_ARRAY);
347 TD_ALIAS_(T_PSTRING_SIZE_IS, TD_PSTRING_SIZE_IS);
348 TD_ALIAS_(T_PWSTRING_SIZE_IS, TD_PWSTRING_SIZE_IS);
349 TD_ALIAS_(T_UTF8STRING, TD_UTF8STRING);
350 TD_ALIAS_(T_CSTRING, TD_CSTRING);
351 TD_ALIAS_(T_ASTRING, TD_ASTRING);
352 TD_ALIAS_(T_NSID, TD_NSID);
353 TD_ALIAS_(T_JSVAL, TD_JSVAL);
354 TD_ALIAS_(T_DOMOBJECT, TD_DOMOBJECT);
355 TD_ALIAS_(T_PROMISE, TD_PROMISE);
356 TD_ALIAS_(T_ARRAY, TD_ARRAY);
357 #undef TD_ALIAS_
358
359 ////////////////////////////////////////////////////////////////
360 // Ensure these fields are in the same order as xptcodegen.py //
361 ////////////////////////////////////////////////////////////////
362
363 uint8_t mTag : 5;
364
365 // Parameter bitflags are packed into the XPTTypeDescriptor to save space.
366 // When the TypeDescriptor is not in a parameter, these flags are ignored.
367 uint8_t mInParam : 1;
368 uint8_t mOutParam : 1;
369 uint8_t mOptionalParam : 1;
370
371 // The data for the different variants is stored in these two data fields.
372 // These should only be accessed via the getter methods above, which will
373 // assert if the tag is invalid.
374 uint8_t mData1;
375 uint8_t mData2;
376 };
377
378 // The fields in nsXPTType were carefully ordered to minimize size.
379 static_assert(sizeof(nsXPTType) == 3, "wrong size");
380
381 /*
382 * A nsXPTParamInfo is used to describe either a single argument to a method or
383 * a method's result. It stores its flags in the type descriptor to save space.
384 */
385 struct nsXPTParamInfo {
IsInnsXPTParamInfo386 bool IsIn() const { return mType.mInParam; }
IsOutnsXPTParamInfo387 bool IsOut() const { return mType.mOutParam; }
IsOptionalnsXPTParamInfo388 bool IsOptional() const { return mType.mOptionalParam; }
IsSharednsXPTParamInfo389 bool IsShared() const { return false; } // XXX remove (backcompat)
390
391 // Get the type of this parameter.
TypensXPTParamInfo392 const nsXPTType& Type() const { return mType; }
GetTypensXPTParamInfo393 const nsXPTType& GetType() const {
394 return Type();
395 } // XXX remove (backcompat)
396
397 // Whether this parameter is passed indirectly on the stack. All out/inout
398 // params are passed indirectly, and complex types are always passed
399 // indirectly.
IsIndirectnsXPTParamInfo400 bool IsIndirect() const { return IsOut() || Type().IsComplex(); }
401
402 ////////////////////////////////////////////////////////////////
403 // Ensure these fields are in the same order as xptcodegen.py //
404 ////////////////////////////////////////////////////////////////
405
406 nsXPTType mType;
407 };
408
409 // The fields in nsXPTParamInfo were carefully ordered to minimize size.
410 static_assert(sizeof(nsXPTParamInfo) == 3, "wrong size");
411
412 /*
413 * A nsXPTMethodInfo is used to describe a single interface method.
414 */
415 struct nsXPTMethodInfo {
IsGetternsXPTMethodInfo416 bool IsGetter() const { return mGetter; }
IsSetternsXPTMethodInfo417 bool IsSetter() const { return mSetter; }
IsReflectablensXPTMethodInfo418 bool IsReflectable() const { return mReflectable; }
IsSymbolnsXPTMethodInfo419 bool IsSymbol() const { return mIsSymbol; }
WantsOptArgcnsXPTMethodInfo420 bool WantsOptArgc() const { return mOptArgc; }
WantsContextnsXPTMethodInfo421 bool WantsContext() const { return mContext; }
ParamCountnsXPTMethodInfo422 uint8_t ParamCount() const { return mNumParams; }
423
NamensXPTMethodInfo424 const char* Name() const {
425 MOZ_ASSERT(!IsSymbol());
426 return xpt::detail::GetString(mName);
427 }
ParamnsXPTMethodInfo428 const nsXPTParamInfo& Param(uint8_t aIndex) const {
429 MOZ_ASSERT(aIndex < mNumParams);
430 return xpt::detail::GetParam(mParams + aIndex);
431 }
432
HasRetvalnsXPTMethodInfo433 bool HasRetval() const { return mHasRetval; }
GetRetvalnsXPTMethodInfo434 const nsXPTParamInfo* GetRetval() const {
435 return mHasRetval ? &Param(mNumParams - 1) : nullptr;
436 }
437
438 // If this is an [implicit_jscontext] method, returns the index of the
439 // implicit JSContext* argument in the C++ method's argument list.
440 // Otherwise returns UINT8_MAX.
IndexOfJSContextnsXPTMethodInfo441 uint8_t IndexOfJSContext() const {
442 if (!WantsContext()) {
443 return UINT8_MAX;
444 }
445 if (IsGetter() || IsSetter()) {
446 // Getters/setters always have the context as first argument.
447 return 0;
448 }
449 // The context comes before the return value, if there is one.
450 MOZ_ASSERT_IF(HasRetval(), ParamCount() > 0);
451 return ParamCount() - uint8_t(HasRetval());
452 }
453
GetSymbolCodensXPTMethodInfo454 JS::SymbolCode GetSymbolCode() const {
455 MOZ_ASSERT(IsSymbol());
456 return JS::SymbolCode(mName);
457 }
458
GetSymbolnsXPTMethodInfo459 JS::Symbol* GetSymbol(JSContext* aCx) const {
460 return JS::GetWellKnownSymbol(aCx, GetSymbolCode());
461 }
462
463 const char* SymbolDescription() const;
464
NameOrDescriptionnsXPTMethodInfo465 const char* NameOrDescription() const {
466 if (IsSymbol()) {
467 return SymbolDescription();
468 }
469 return Name();
470 }
471
472 bool GetId(JSContext* aCx, jsid& aId) const;
473
474 /////////////////////////////////////////////
475 // nsXPTMethodInfo backwards compatibility //
476 /////////////////////////////////////////////
477
GetNamensXPTMethodInfo478 const char* GetName() const { return Name(); }
479
GetParamCountnsXPTMethodInfo480 uint8_t GetParamCount() const { return ParamCount(); }
GetParamnsXPTMethodInfo481 const nsXPTParamInfo& GetParam(uint8_t aIndex) const { return Param(aIndex); }
482
483 ////////////////////////////////////////////////////////////////
484 // Ensure these fields are in the same order as xptcodegen.py //
485 ////////////////////////////////////////////////////////////////
486
487 uint32_t mName; // Index into xpt::detail::sStrings.
488 uint16_t mParams; // Index into xpt::detail::sParams.
489 uint8_t mNumParams;
490
491 uint8_t mGetter : 1;
492 uint8_t mSetter : 1;
493 uint8_t mReflectable : 1;
494 uint8_t mOptArgc : 1;
495 uint8_t mContext : 1;
496 uint8_t mHasRetval : 1;
497 uint8_t mIsSymbol : 1;
498 };
499
500 // The fields in nsXPTMethodInfo were carefully ordered to minimize size.
501 static_assert(sizeof(nsXPTMethodInfo) == 8, "wrong size");
502
503 /**
504 * A nsXPTConstantInfo is used to describe a single interface constant.
505 */
506 struct nsXPTConstantInfo {
NamensXPTConstantInfo507 const char* Name() const { return xpt::detail::GetString(mName); }
508
JSValuensXPTConstantInfo509 JS::Value JSValue() const {
510 if (mSigned || mValue <= uint32_t(INT32_MAX)) {
511 return JS::Int32Value(int32_t(mValue));
512 }
513 return JS::DoubleValue(mValue);
514 }
515
516 ////////////////////////////////////////////////////////////////
517 // Ensure these fields are in the same order as xptcodegen.py //
518 ////////////////////////////////////////////////////////////////
519
520 uint32_t mName : 31; // Index into xpt::detail::mStrings.
521
522 // Whether the value should be interpreted as a int32_t or uint32_t.
523 uint32_t mSigned : 1;
524 uint32_t mValue; // The value stored as a u32
525 };
526
527 // The fields in nsXPTConstantInfo were carefully ordered to minimize size.
528 static_assert(sizeof(nsXPTConstantInfo) == 8, "wrong size");
529
530 /**
531 * Object representing the information required to wrap and unwrap DOMObjects.
532 *
533 * This object will not live in rodata as it contains relocations.
534 */
535 struct nsXPTDOMObjectInfo {
UnwrapnsXPTDOMObjectInfo536 nsresult Unwrap(JS::HandleValue aHandle, void** aObj, JSContext* aCx) const {
537 return mUnwrap(aHandle, aObj, aCx);
538 }
539
WrapnsXPTDOMObjectInfo540 bool Wrap(JSContext* aCx, void* aObj, JS::MutableHandleValue aHandle) const {
541 return mWrap(aCx, aObj, aHandle);
542 }
543
CleanupnsXPTDOMObjectInfo544 void Cleanup(void* aObj) const { return mCleanup(aObj); }
545
546 ////////////////////////////////////////////////////////////////
547 // Ensure these fields are in the same order as xptcodegen.py //
548 ////////////////////////////////////////////////////////////////
549
550 nsresult (*mUnwrap)(JS::HandleValue aHandle, void** aObj, JSContext* aCx);
551 bool (*mWrap)(JSContext* aCx, void* aObj, JS::MutableHandleValue aHandle);
552 void (*mCleanup)(void* aObj);
553 };
554
555 namespace xpt {
556 namespace detail {
557
558 // The UntypedTArray type allows low-level access from XPConnect to nsTArray
559 // internals without static knowledge of the array element type in question.
560 class UntypedTArray : public nsTArray_base<nsTArrayFallibleAllocator,
561 nsTArray_RelocateUsingMemutils> {
562 public:
Elements()563 void* Elements() const { return static_cast<void*>(Hdr() + 1); }
564
565 // Changes the length and capacity to be at least large enough for aTo
566 // elements.
SetLength(const nsXPTType & aEltTy,uint32_t aTo)567 bool SetLength(const nsXPTType& aEltTy, uint32_t aTo) {
568 if (!EnsureCapacity<nsTArrayFallibleAllocator>(aTo, aEltTy.Stride())) {
569 return false;
570 }
571
572 if (mHdr != EmptyHdr()) {
573 mHdr->mLength = aTo;
574 }
575
576 return true;
577 }
578
579 // Free backing memory for the nsTArray object.
Clear()580 void Clear() {
581 if (mHdr != EmptyHdr() && !UsesAutoArrayBuffer()) {
582 nsTArrayFallibleAllocator::Free(mHdr);
583 }
584 mHdr = EmptyHdr();
585 }
586 };
587
588 //////////////////////////////////////////////
589 // Raw typelib data stored in const statics //
590 //////////////////////////////////////////////
591
592 // XPIDL information
593 extern const nsXPTInterfaceInfo sInterfaces[];
594 extern const nsXPTType sTypes[];
595 extern const nsXPTParamInfo sParams[];
596 extern const nsXPTMethodInfo sMethods[];
597 extern const nsXPTConstantInfo sConsts[];
598 extern const nsXPTDOMObjectInfo sDOMObjects[];
599
600 extern const char sStrings[];
601
602 //////////////////////////////////////
603 // Helper Methods for fetching data //
604 //////////////////////////////////////
605
GetInterface(uint16_t aIndex)606 inline const nsXPTInterfaceInfo* GetInterface(uint16_t aIndex) {
607 if (aIndex > 0 && aIndex <= sInterfacesSize) {
608 return &sInterfaces[aIndex - 1]; // 1-based as 0 is a marker.
609 }
610 return nullptr;
611 }
612
GetType(uint16_t aIndex)613 inline const nsXPTType& GetType(uint16_t aIndex) { return sTypes[aIndex]; }
614
GetParam(uint16_t aIndex)615 inline const nsXPTParamInfo& GetParam(uint16_t aIndex) {
616 return sParams[aIndex];
617 }
618
GetMethod(uint16_t aIndex)619 inline const nsXPTMethodInfo& GetMethod(uint16_t aIndex) {
620 return sMethods[aIndex];
621 }
622
GetConstant(uint16_t aIndex)623 inline const nsXPTConstantInfo& GetConstant(uint16_t aIndex) {
624 return sConsts[aIndex];
625 }
626
GetDOMObjectInfo(uint16_t aIndex)627 inline const nsXPTDOMObjectInfo& GetDOMObjectInfo(uint16_t aIndex) {
628 return sDOMObjects[aIndex];
629 }
630
GetString(uint32_t aIndex)631 inline const char* GetString(uint32_t aIndex) { return &sStrings[aIndex]; }
632
633 } // namespace detail
634 } // namespace xpt
635
636 #define XPT_FOR_EACH_ARITHMETIC_TYPE(MACRO) \
637 MACRO(TD_INT8, int8_t) \
638 MACRO(TD_INT16, int16_t) \
639 MACRO(TD_INT32, int32_t) \
640 MACRO(TD_INT64, int64_t) \
641 MACRO(TD_UINT8, uint8_t) \
642 MACRO(TD_UINT16, uint16_t) \
643 MACRO(TD_UINT32, uint32_t) \
644 MACRO(TD_UINT64, uint64_t) \
645 MACRO(TD_FLOAT, float) \
646 MACRO(TD_DOUBLE, double) \
647 MACRO(TD_BOOL, bool) \
648 MACRO(TD_CHAR, char) \
649 MACRO(TD_WCHAR, char16_t)
650
651 #define XPT_FOR_EACH_POINTER_TYPE(MACRO) \
652 MACRO(TD_VOID, void*) \
653 MACRO(TD_NSIDPTR, nsID*) \
654 MACRO(TD_PSTRING, char*) \
655 MACRO(TD_PWSTRING, wchar_t*) \
656 MACRO(TD_INTERFACE_TYPE, nsISupports*) \
657 MACRO(TD_INTERFACE_IS_TYPE, nsISupports*) \
658 MACRO(TD_LEGACY_ARRAY, void*) \
659 MACRO(TD_PSTRING_SIZE_IS, char*) \
660 MACRO(TD_PWSTRING_SIZE_IS, wchar_t*) \
661 MACRO(TD_DOMOBJECT, void*) \
662 MACRO(TD_PROMISE, mozilla::dom::Promise*)
663
664 #define XPT_FOR_EACH_COMPLEX_TYPE(MACRO) \
665 MACRO(TD_UTF8STRING, nsCString) \
666 MACRO(TD_CSTRING, nsCString) \
667 MACRO(TD_ASTRING, nsString) \
668 MACRO(TD_NSID, nsID) \
669 MACRO(TD_JSVAL, JS::Value) \
670 MACRO(TD_ARRAY, xpt::detail::UntypedTArray)
671
672 #define XPT_FOR_EACH_TYPE(MACRO) \
673 XPT_FOR_EACH_ARITHMETIC_TYPE(MACRO) \
674 XPT_FOR_EACH_POINTER_TYPE(MACRO) \
675 XPT_FOR_EACH_COMPLEX_TYPE(MACRO)
676
Stride()677 inline size_t nsXPTType::Stride() const {
678 // Compute the stride to use when walking an array of the given type.
679 switch (Tag()) {
680 #define XPT_TYPE_STRIDE(tag, type) \
681 case tag: \
682 return sizeof(type);
683 XPT_FOR_EACH_TYPE(XPT_TYPE_STRIDE)
684 #undef XPT_TYPE_STRIDE
685 }
686
687 MOZ_CRASH("Unknown type");
688 }
689
690 #endif /* xptinfo_h */
691