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