Coverage Report

Created: 2018-09-25 14:53

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