Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/GamepadBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM Gamepad.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "GamepadBinding.h"
4
#include "WrapperFactory.h"
5
#include "XrayWrapper.h"
6
#include "jsapi.h"
7
#include "mozilla/FloatingPoint.h"
8
#include "mozilla/OwningNonNull.h"
9
#include "mozilla/Preferences.h"
10
#include "mozilla/dom/BindingUtils.h"
11
#include "mozilla/dom/DOMJSClass.h"
12
#include "mozilla/dom/Gamepad.h"
13
#include "mozilla/dom/GamepadButton.h"
14
#include "mozilla/dom/GamepadHapticActuator.h"
15
#include "mozilla/dom/GamepadPose.h"
16
#include "mozilla/dom/NonRefcountedDOMObject.h"
17
#include "mozilla/dom/Nullable.h"
18
#include "mozilla/dom/PrimitiveConversions.h"
19
#include "mozilla/dom/XrayExpandoClass.h"
20
21
namespace mozilla {
22
namespace dom {
23
24
namespace binding_detail {}; // Just to make sure it's known as a namespace
25
using namespace mozilla::dom::binding_detail;
26
27
28
namespace GamepadHandValues {
29
extern const EnumEntry strings[4] = {
30
  {"", 0},
31
  {"left", 4},
32
  {"right", 5},
33
  { nullptr, 0 }
34
};
35
} // namespace GamepadHandValues
36
37
bool
38
ToJSValue(JSContext* aCx, GamepadHand aArgument, JS::MutableHandle<JS::Value> aValue)
39
0
{
40
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(GamepadHandValues::strings));
41
0
  JSString* resultStr =
42
0
    JS_NewStringCopyN(aCx, GamepadHandValues::strings[uint32_t(aArgument)].value,
43
0
                      GamepadHandValues::strings[uint32_t(aArgument)].length);
44
0
  if (!resultStr) {
45
0
    return false;
46
0
  }
47
0
  aValue.setString(resultStr);
48
0
  return true;
49
0
}
50
51
52
namespace GamepadMappingTypeValues {
53
extern const EnumEntry strings[3] = {
54
  {"", 0},
55
  {"standard", 8},
56
  { nullptr, 0 }
57
};
58
} // namespace GamepadMappingTypeValues
59
60
bool
61
ToJSValue(JSContext* aCx, GamepadMappingType aArgument, JS::MutableHandle<JS::Value> aValue)
62
0
{
63
0
  MOZ_ASSERT(uint32_t(aArgument) < ArrayLength(GamepadMappingTypeValues::strings));
64
0
  JSString* resultStr =
65
0
    JS_NewStringCopyN(aCx, GamepadMappingTypeValues::strings[uint32_t(aArgument)].value,
66
0
                      GamepadMappingTypeValues::strings[uint32_t(aArgument)].length);
67
0
  if (!resultStr) {
68
0
    return false;
69
0
  }
70
0
  aValue.setString(resultStr);
71
0
  return true;
72
0
}
73
74
75
namespace Gamepad_Binding {
76
77
MOZ_CAN_RUN_SCRIPT static bool
78
get_id(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
79
0
{
80
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.id", DOM, cx);
81
0
82
0
  DOMString result;
83
0
  self->GetId(result);
84
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
85
0
  if (!xpc::NonVoidStringToJsval(cx, result, args.rval())) {
86
0
    return false;
87
0
  }
88
0
  return true;
89
0
}
90
91
static const JSJitInfo id_getterinfo = {
92
  { (JSJitGetterOp)get_id },
93
  { prototypes::id::Gamepad },
94
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
95
  JSJitInfo::Getter,
96
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
97
  JSVAL_TYPE_STRING,  /* returnType.  Not relevant for setters. */
98
  false,  /* isInfallible. False in setters. */
99
  false,  /* isMovable.  Not relevant for setters. */
100
  false, /* isEliminatable.  Not relevant for setters. */
101
  false, /* isAlwaysInSlot.  Only relevant for getters. */
102
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
103
  false,  /* isTypedMethod.  Only relevant for methods. */
104
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
105
};
106
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
107
static_assert(0 < 4, "There is no slot for us");
108
109
MOZ_CAN_RUN_SCRIPT static bool
110
get_index(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
111
0
{
112
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.index", DOM, cx);
113
0
114
0
  uint32_t result(self->Index());
115
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
116
0
  args.rval().setNumber(result);
117
0
  return true;
118
0
}
119
120
static const JSJitInfo index_getterinfo = {
121
  { (JSJitGetterOp)get_index },
122
  { prototypes::id::Gamepad },
123
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
124
  JSJitInfo::Getter,
125
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
126
  JSVAL_TYPE_DOUBLE,  /* returnType.  Not relevant for setters. */
127
  true,  /* isInfallible. False in setters. */
128
  false,  /* isMovable.  Not relevant for setters. */
129
  false, /* isEliminatable.  Not relevant for setters. */
130
  false, /* isAlwaysInSlot.  Only relevant for getters. */
131
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
132
  false,  /* isTypedMethod.  Only relevant for methods. */
133
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
134
};
135
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
136
static_assert(0 < 4, "There is no slot for us");
137
138
MOZ_CAN_RUN_SCRIPT static bool
139
get_mapping(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
140
0
{
141
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.mapping", DOM, cx);
142
0
143
0
  GamepadMappingType result(self->Mapping());
144
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
145
0
  if (!ToJSValue(cx, result, args.rval())) {
146
0
    return false;
147
0
  }
148
0
  return true;
149
0
}
150
151
static const JSJitInfo mapping_getterinfo = {
152
  { (JSJitGetterOp)get_mapping },
153
  { prototypes::id::Gamepad },
154
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
155
  JSJitInfo::Getter,
156
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
157
  JSVAL_TYPE_STRING,  /* returnType.  Not relevant for setters. */
158
  false,  /* isInfallible. False in setters. */
159
  false,  /* isMovable.  Not relevant for setters. */
160
  false, /* isEliminatable.  Not relevant for setters. */
161
  false, /* isAlwaysInSlot.  Only relevant for getters. */
162
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
163
  false,  /* isTypedMethod.  Only relevant for methods. */
164
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
165
};
166
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
167
static_assert(0 < 4, "There is no slot for us");
168
169
MOZ_CAN_RUN_SCRIPT static bool
170
get_hand(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
171
0
{
172
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.hand", DOM, cx);
173
0
174
0
  GamepadHand result(self->Hand());
175
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
176
0
  if (!ToJSValue(cx, result, args.rval())) {
177
0
    return false;
178
0
  }
179
0
  return true;
180
0
}
181
182
static const JSJitInfo hand_getterinfo = {
183
  { (JSJitGetterOp)get_hand },
184
  { prototypes::id::Gamepad },
185
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
186
  JSJitInfo::Getter,
187
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
188
  JSVAL_TYPE_STRING,  /* returnType.  Not relevant for setters. */
189
  false,  /* isInfallible. False in setters. */
190
  false,  /* isMovable.  Not relevant for setters. */
191
  false, /* isEliminatable.  Not relevant for setters. */
192
  false, /* isAlwaysInSlot.  Only relevant for getters. */
193
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
194
  false,  /* isTypedMethod.  Only relevant for methods. */
195
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
196
};
197
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
198
static_assert(0 < 4, "There is no slot for us");
199
200
MOZ_CAN_RUN_SCRIPT static bool
201
get_displayId(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
202
0
{
203
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.displayId", DOM, cx);
204
0
205
0
  uint32_t result(self->DisplayId());
206
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
207
0
  args.rval().setNumber(result);
208
0
  return true;
209
0
}
210
211
static const JSJitInfo displayId_getterinfo = {
212
  { (JSJitGetterOp)get_displayId },
213
  { prototypes::id::Gamepad },
214
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
215
  JSJitInfo::Getter,
216
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
217
  JSVAL_TYPE_DOUBLE,  /* returnType.  Not relevant for setters. */
218
  true,  /* isInfallible. False in setters. */
219
  false,  /* isMovable.  Not relevant for setters. */
220
  false, /* isEliminatable.  Not relevant for setters. */
221
  false, /* isAlwaysInSlot.  Only relevant for getters. */
222
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
223
  false,  /* isTypedMethod.  Only relevant for methods. */
224
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
225
};
226
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
227
static_assert(0 < 4, "There is no slot for us");
228
229
MOZ_CAN_RUN_SCRIPT static bool
230
get_connected(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
231
0
{
232
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.connected", DOM, cx);
233
0
234
0
  bool result(self->Connected());
235
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
236
0
  args.rval().setBoolean(result);
237
0
  return true;
238
0
}
239
240
static const JSJitInfo connected_getterinfo = {
241
  { (JSJitGetterOp)get_connected },
242
  { prototypes::id::Gamepad },
243
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
244
  JSJitInfo::Getter,
245
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
246
  JSVAL_TYPE_BOOLEAN,  /* returnType.  Not relevant for setters. */
247
  true,  /* isInfallible. False in setters. */
248
  false,  /* isMovable.  Not relevant for setters. */
249
  false, /* isEliminatable.  Not relevant for setters. */
250
  false, /* isAlwaysInSlot.  Only relevant for getters. */
251
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
252
  false,  /* isTypedMethod.  Only relevant for methods. */
253
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
254
};
255
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
256
static_assert(0 < 4, "There is no slot for us");
257
258
MOZ_CAN_RUN_SCRIPT static bool
259
get_buttons(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
260
0
{
261
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.buttons", DOM, cx);
262
0
263
0
  // Have to either root across the getter call or reget after.
264
0
  bool isXray;
265
0
  JS::Rooted<JSObject*> slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray));
266
0
  if (!slotStorage) {
267
0
    return false;
268
0
  }
269
0
  const size_t slotIndex = isXray ? (xpc::JSSLOT_EXPANDO_COUNT + 0) : (DOM_INSTANCE_RESERVED_SLOTS + 0);
270
0
  MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(js::GetObjectClass(slotStorage)) > slotIndex);
271
0
  {
272
0
    // Scope for cachedVal
273
0
    JS::Value cachedVal = js::GetReservedSlot(slotStorage, slotIndex);
274
0
    if (!cachedVal.isUndefined()) {
275
0
      args.rval().set(cachedVal);
276
0
      // The cached value is in the compartment of slotStorage,
277
0
      // so wrap into the caller compartment as needed.
278
0
      if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
279
0
        return true;
280
0
      }
281
0
      return false;
282
0
    }
283
0
  }
284
0
285
0
  nsTArray<StrongPtrForMember<mozilla::dom::GamepadButton>::Type> result;
286
0
  self->GetButtons(result);
287
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
288
0
  {
289
0
    JS::Rooted<JSObject*> conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage);
290
0
    JSAutoRealm ar(cx, conversionScope);
291
0
    do { // block we break out of when done wrapping
292
0
293
0
      uint32_t length = result.Length();
294
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
295
0
      if (!returnArray) {
296
0
        return false;
297
0
      }
298
0
      // Scope for 'tmp'
299
0
      {
300
0
        JS::Rooted<JS::Value> tmp(cx);
301
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
302
0
          // Control block to let us common up the JS_DefineElement calls when there
303
0
          // are different ways to succeed at wrapping the object.
304
0
          do {
305
0
            if (!GetOrCreateDOMReflector(cx, result[sequenceIdx0], &tmp)) {
306
0
              MOZ_ASSERT(JS_IsExceptionPending(cx));
307
0
              return false;
308
0
            }
309
0
            break;
310
0
          } while (false);
311
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
312
0
                                JSPROP_ENUMERATE)) {
313
0
            return false;
314
0
          }
315
0
        }
316
0
      }
317
0
      args.rval().setObject(*returnArray);
318
0
      break;
319
0
    } while (false);
320
0
    JS::Rooted<JSObject*> rvalObj(cx, &args.rval().toObject());
321
0
    if (!JS_FreezeObject(cx, rvalObj)) {
322
0
      return false;
323
0
    }
324
0
  }
325
0
  { // And now store things in the realm of our slotStorage.
326
0
    JSAutoRealm ar(cx, slotStorage);
327
0
    // Make a copy so that we don't do unnecessary wrapping on args.rval().
328
0
    JS::Rooted<JS::Value> storedVal(cx, args.rval());
329
0
    if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) {
330
0
      return false;
331
0
    }
332
0
    js::SetReservedSlot(slotStorage, slotIndex, storedVal);
333
0
    if (!isXray) {
334
0
      // In the Xray case we don't need to do this, because getting the
335
0
      // expando object already preserved our wrapper.
336
0
      PreserveWrapper(self);
337
0
    }
338
0
  }
339
0
  // And now make sure args.rval() is in the caller realm.
340
0
  if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
341
0
    return true;
342
0
  }
343
0
  return false;
344
0
}
345
346
static const JSJitInfo buttons_getterinfo = {
347
  { (JSJitGetterOp)get_buttons },
348
  { prototypes::id::Gamepad },
349
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
350
  JSJitInfo::Getter,
351
  JSJitInfo::AliasDOMSets, /* aliasSet.  Not relevant for setters. */
352
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
353
  false,  /* isInfallible. False in setters. */
354
  true,  /* isMovable.  Not relevant for setters. */
355
  true, /* isEliminatable.  Not relevant for setters. */
356
  false, /* isAlwaysInSlot.  Only relevant for getters. */
357
  true, /* isLazilyCachedInSlot.  Only relevant for getters. */
358
  false,  /* isTypedMethod.  Only relevant for methods. */
359
  (DOM_INSTANCE_RESERVED_SLOTS + 0)   /* Reserved slot index, if we're stored in a slot, else 0. */
360
};
361
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 0) <= JSJitInfo::maxSlotIndex, "We won't fit");
362
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 0) < 4, "There is no slot for us");
363
364
MOZ_CAN_RUN_SCRIPT static bool
365
get_axes(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
366
0
{
367
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.axes", DOM, cx);
368
0
369
0
  // Have to either root across the getter call or reget after.
370
0
  bool isXray;
371
0
  JS::Rooted<JSObject*> slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray));
372
0
  if (!slotStorage) {
373
0
    return false;
374
0
  }
375
0
  const size_t slotIndex = isXray ? (xpc::JSSLOT_EXPANDO_COUNT + 1) : (DOM_INSTANCE_RESERVED_SLOTS + 1);
376
0
  MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(js::GetObjectClass(slotStorage)) > slotIndex);
377
0
  {
378
0
    // Scope for cachedVal
379
0
    JS::Value cachedVal = js::GetReservedSlot(slotStorage, slotIndex);
380
0
    if (!cachedVal.isUndefined()) {
381
0
      args.rval().set(cachedVal);
382
0
      // The cached value is in the compartment of slotStorage,
383
0
      // so wrap into the caller compartment as needed.
384
0
      if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
385
0
        return true;
386
0
      }
387
0
      return false;
388
0
    }
389
0
  }
390
0
391
0
  nsTArray<double> result;
392
0
  self->GetAxes(result);
393
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
394
0
  {
395
0
    JS::Rooted<JSObject*> conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage);
396
0
    JSAutoRealm ar(cx, conversionScope);
397
0
    do { // block we break out of when done wrapping
398
0
399
0
      uint32_t length = result.Length();
400
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
401
0
      if (!returnArray) {
402
0
        return false;
403
0
      }
404
0
      // Scope for 'tmp'
405
0
      {
406
0
        JS::Rooted<JS::Value> tmp(cx);
407
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
408
0
          // Control block to let us common up the JS_DefineElement calls when there
409
0
          // are different ways to succeed at wrapping the object.
410
0
          do {
411
0
            tmp.set(JS_NumberValue(double(result[sequenceIdx0])));
412
0
            break;
413
0
          } while (false);
414
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
415
0
                                JSPROP_ENUMERATE)) {
416
0
            return false;
417
0
          }
418
0
        }
419
0
      }
420
0
      args.rval().setObject(*returnArray);
421
0
      break;
422
0
    } while (false);
423
0
    JS::Rooted<JSObject*> rvalObj(cx, &args.rval().toObject());
424
0
    if (!JS_FreezeObject(cx, rvalObj)) {
425
0
      return false;
426
0
    }
427
0
  }
428
0
  { // And now store things in the realm of our slotStorage.
429
0
    JSAutoRealm ar(cx, slotStorage);
430
0
    // Make a copy so that we don't do unnecessary wrapping on args.rval().
431
0
    JS::Rooted<JS::Value> storedVal(cx, args.rval());
432
0
    if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) {
433
0
      return false;
434
0
    }
435
0
    js::SetReservedSlot(slotStorage, slotIndex, storedVal);
436
0
    if (!isXray) {
437
0
      // In the Xray case we don't need to do this, because getting the
438
0
      // expando object already preserved our wrapper.
439
0
      PreserveWrapper(self);
440
0
    }
441
0
  }
442
0
  // And now make sure args.rval() is in the caller realm.
443
0
  if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
444
0
    return true;
445
0
  }
446
0
  return false;
447
0
}
448
449
static const JSJitInfo axes_getterinfo = {
450
  { (JSJitGetterOp)get_axes },
451
  { prototypes::id::Gamepad },
452
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
453
  JSJitInfo::Getter,
454
  JSJitInfo::AliasDOMSets, /* aliasSet.  Not relevant for setters. */
455
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
456
  false,  /* isInfallible. False in setters. */
457
  true,  /* isMovable.  Not relevant for setters. */
458
  true, /* isEliminatable.  Not relevant for setters. */
459
  false, /* isAlwaysInSlot.  Only relevant for getters. */
460
  true, /* isLazilyCachedInSlot.  Only relevant for getters. */
461
  false,  /* isTypedMethod.  Only relevant for methods. */
462
  (DOM_INSTANCE_RESERVED_SLOTS + 1)   /* Reserved slot index, if we're stored in a slot, else 0. */
463
};
464
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 1) <= JSJitInfo::maxSlotIndex, "We won't fit");
465
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 1) < 4, "There is no slot for us");
466
467
MOZ_CAN_RUN_SCRIPT static bool
468
get_timestamp(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
469
0
{
470
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.timestamp", DOM, cx);
471
0
472
0
  double result(self->Timestamp());
473
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
474
0
  args.rval().set(JS_NumberValue(double(result)));
475
0
  return true;
476
0
}
477
478
static const JSJitInfo timestamp_getterinfo = {
479
  { (JSJitGetterOp)get_timestamp },
480
  { prototypes::id::Gamepad },
481
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
482
  JSJitInfo::Getter,
483
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
484
  JSVAL_TYPE_DOUBLE,  /* returnType.  Not relevant for setters. */
485
  true,  /* isInfallible. False in setters. */
486
  false,  /* isMovable.  Not relevant for setters. */
487
  false, /* isEliminatable.  Not relevant for setters. */
488
  false, /* isAlwaysInSlot.  Only relevant for getters. */
489
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
490
  false,  /* isTypedMethod.  Only relevant for methods. */
491
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
492
};
493
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
494
static_assert(0 < 4, "There is no slot for us");
495
496
MOZ_CAN_RUN_SCRIPT static bool
497
get_pose(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
498
0
{
499
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.pose", DOM, cx);
500
0
501
0
  auto result(StrongOrRawPtr<mozilla::dom::GamepadPose>(self->GetPose()));
502
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
503
0
  if (!result) {
504
0
    args.rval().setNull();
505
0
    return true;
506
0
  }
507
0
  if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
508
0
    MOZ_ASSERT(JS_IsExceptionPending(cx));
509
0
    return false;
510
0
  }
511
0
  return true;
512
0
}
513
514
static const JSJitInfo pose_getterinfo = {
515
  { (JSJitGetterOp)get_pose },
516
  { prototypes::id::Gamepad },
517
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
518
  JSJitInfo::Getter,
519
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
520
  JSVAL_TYPE_UNKNOWN,  /* returnType.  Not relevant for setters. */
521
  false,  /* isInfallible. False in setters. */
522
  false,  /* isMovable.  Not relevant for setters. */
523
  false, /* isEliminatable.  Not relevant for setters. */
524
  false, /* isAlwaysInSlot.  Only relevant for getters. */
525
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
526
  false,  /* isTypedMethod.  Only relevant for methods. */
527
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
528
};
529
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
530
static_assert(0 < 4, "There is no slot for us");
531
532
MOZ_CAN_RUN_SCRIPT static bool
533
get_hapticActuators(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::Gamepad* self, JSJitGetterCallArgs args)
534
0
{
535
0
  AUTO_PROFILER_LABEL_FAST("get Gamepad.hapticActuators", DOM, cx);
536
0
537
0
  // Have to either root across the getter call or reget after.
538
0
  bool isXray;
539
0
  JS::Rooted<JSObject*> slotStorage(cx, GetCachedSlotStorageObject(cx, obj, &isXray));
540
0
  if (!slotStorage) {
541
0
    return false;
542
0
  }
543
0
  const size_t slotIndex = isXray ? (xpc::JSSLOT_EXPANDO_COUNT + 2) : (DOM_INSTANCE_RESERVED_SLOTS + 2);
544
0
  MOZ_ASSERT(JSCLASS_RESERVED_SLOTS(js::GetObjectClass(slotStorage)) > slotIndex);
545
0
  {
546
0
    // Scope for cachedVal
547
0
    JS::Value cachedVal = js::GetReservedSlot(slotStorage, slotIndex);
548
0
    if (!cachedVal.isUndefined()) {
549
0
      args.rval().set(cachedVal);
550
0
      // The cached value is in the compartment of slotStorage,
551
0
      // so wrap into the caller compartment as needed.
552
0
      if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
553
0
        return true;
554
0
      }
555
0
      return false;
556
0
    }
557
0
  }
558
0
559
0
  nsTArray<StrongPtrForMember<mozilla::dom::GamepadHapticActuator>::Type> result;
560
0
  self->GetHapticActuators(result);
561
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
562
0
  {
563
0
    JS::Rooted<JSObject*> conversionScope(cx, isXray ? JS::CurrentGlobalOrNull(cx) : slotStorage);
564
0
    JSAutoRealm ar(cx, conversionScope);
565
0
    do { // block we break out of when done wrapping
566
0
567
0
      uint32_t length = result.Length();
568
0
      JS::Rooted<JSObject*> returnArray(cx, JS_NewArrayObject(cx, length));
569
0
      if (!returnArray) {
570
0
        return false;
571
0
      }
572
0
      // Scope for 'tmp'
573
0
      {
574
0
        JS::Rooted<JS::Value> tmp(cx);
575
0
        for (uint32_t sequenceIdx0 = 0; sequenceIdx0 < length; ++sequenceIdx0) {
576
0
          // Control block to let us common up the JS_DefineElement calls when there
577
0
          // are different ways to succeed at wrapping the object.
578
0
          do {
579
0
            if (!GetOrCreateDOMReflector(cx, result[sequenceIdx0], &tmp)) {
580
0
              MOZ_ASSERT(JS_IsExceptionPending(cx));
581
0
              return false;
582
0
            }
583
0
            break;
584
0
          } while (false);
585
0
          if (!JS_DefineElement(cx, returnArray, sequenceIdx0, tmp,
586
0
                                JSPROP_ENUMERATE)) {
587
0
            return false;
588
0
          }
589
0
        }
590
0
      }
591
0
      args.rval().setObject(*returnArray);
592
0
      break;
593
0
    } while (false);
594
0
    JS::Rooted<JSObject*> rvalObj(cx, &args.rval().toObject());
595
0
    if (!JS_FreezeObject(cx, rvalObj)) {
596
0
      return false;
597
0
    }
598
0
  }
599
0
  { // And now store things in the realm of our slotStorage.
600
0
    JSAutoRealm ar(cx, slotStorage);
601
0
    // Make a copy so that we don't do unnecessary wrapping on args.rval().
602
0
    JS::Rooted<JS::Value> storedVal(cx, args.rval());
603
0
    if (!MaybeWrapNonDOMObjectValue(cx, &storedVal)) {
604
0
      return false;
605
0
    }
606
0
    js::SetReservedSlot(slotStorage, slotIndex, storedVal);
607
0
    if (!isXray) {
608
0
      // In the Xray case we don't need to do this, because getting the
609
0
      // expando object already preserved our wrapper.
610
0
      PreserveWrapper(self);
611
0
    }
612
0
  }
613
0
  // And now make sure args.rval() is in the caller realm.
614
0
  if (MaybeWrapNonDOMObjectValue(cx, args.rval())) {
615
0
    return true;
616
0
  }
617
0
  return false;
618
0
}
619
620
static const JSJitInfo hapticActuators_getterinfo = {
621
  { (JSJitGetterOp)get_hapticActuators },
622
  { prototypes::id::Gamepad },
623
  { PrototypeTraits<prototypes::id::Gamepad>::Depth },
624
  JSJitInfo::Getter,
625
  JSJitInfo::AliasNone, /* aliasSet.  Not relevant for setters. */
626
  JSVAL_TYPE_OBJECT,  /* returnType.  Not relevant for setters. */
627
  false,  /* isInfallible. False in setters. */
628
  true,  /* isMovable.  Not relevant for setters. */
629
  true, /* isEliminatable.  Not relevant for setters. */
630
  false, /* isAlwaysInSlot.  Only relevant for getters. */
631
  true, /* isLazilyCachedInSlot.  Only relevant for getters. */
632
  false,  /* isTypedMethod.  Only relevant for methods. */
633
  (DOM_INSTANCE_RESERVED_SLOTS + 2)   /* Reserved slot index, if we're stored in a slot, else 0. */
634
};
635
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 2) <= JSJitInfo::maxSlotIndex, "We won't fit");
636
static_assert((DOM_INSTANCE_RESERVED_SLOTS + 2) < 4, "There is no slot for us");
637
638
static bool
639
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
640
0
{
641
0
  mozilla::dom::Gamepad* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Gamepad>(obj);
642
0
  // We don't want to preserve if we don't have a wrapper, and we
643
0
  // obviously can't preserve if we're not initialized.
644
0
  if (self && self->GetWrapperPreserveColor()) {
645
0
    PreserveWrapper(self);
646
0
  }
647
0
  return true;
648
0
}
649
650
static void
651
_finalize(js::FreeOp* fop, JSObject* obj)
652
0
{
653
0
  mozilla::dom::Gamepad* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Gamepad>(obj);
654
0
  if (self) {
655
0
    ClearWrapper(self, self, obj);
656
0
    AddForDeferredFinalization<mozilla::dom::Gamepad>(self);
657
0
  }
658
0
}
659
660
static size_t
661
_objectMoved(JSObject* obj, JSObject* old)
662
0
{
663
0
  mozilla::dom::Gamepad* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::Gamepad>(obj);
664
0
  if (self) {
665
0
    UpdateWrapper(self, self, obj, old);
666
0
  }
667
0
668
0
  return 0;
669
0
}
670
671
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
672
#if defined(__clang__)
673
#pragma clang diagnostic push
674
#pragma clang diagnostic ignored "-Wmissing-braces"
675
#endif
676
static const JSPropertySpec sAttributes_specs[] = {
677
  { "id", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &id_getterinfo, nullptr, nullptr },
678
  { "index", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &index_getterinfo, nullptr, nullptr },
679
  { "mapping", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &mapping_getterinfo, nullptr, nullptr },
680
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr },
681
  { "hand", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &hand_getterinfo, nullptr, nullptr },
682
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr },
683
  { "displayId", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &displayId_getterinfo, nullptr, nullptr },
684
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr },
685
  { "connected", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &connected_getterinfo, nullptr, nullptr },
686
  { "buttons", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &buttons_getterinfo, nullptr, nullptr },
687
  { "axes", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &axes_getterinfo, nullptr, nullptr },
688
  { "timestamp", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &timestamp_getterinfo, nullptr, nullptr },
689
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr },
690
  { "pose", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &pose_getterinfo, nullptr, nullptr },
691
  { "hapticActuators", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &hapticActuators_getterinfo, nullptr, nullptr },
692
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
693
};
694
#if defined(__clang__)
695
#pragma clang diagnostic pop
696
#endif
697
698
// Can't be const because the pref-enabled boolean needs to be writable
699
static PrefableDisablers sAttributes_disablers4 = {
700
  true, false, 0, nullptr
701
};
702
703
// Can't be const because the pref-enabled boolean needs to be writable
704
static PrefableDisablers sAttributes_disablers6 = {
705
  true, false, 0, nullptr
706
};
707
708
// Can't be const because the pref-enabled boolean needs to be writable
709
static PrefableDisablers sAttributes_disablers13 = {
710
  true, false, 0, nullptr
711
};
712
713
static const Prefable<const JSPropertySpec> sAttributes[] = {
714
  { nullptr, &sAttributes_specs[0] },
715
  { &sAttributes_disablers4, &sAttributes_specs[4] },
716
  { &sAttributes_disablers6, &sAttributes_specs[6] },
717
  { nullptr, &sAttributes_specs[8] },
718
  { &sAttributes_disablers13, &sAttributes_specs[13] },
719
  { nullptr, nullptr }
720
};
721
722
static_assert(5 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
723
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
724
static_assert(4 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
725
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
726
727
728
static uint16_t sNativeProperties_sortedPropertyIndices[11];
729
static PropertyInfo sNativeProperties_propertyInfos[11];
730
731
static const NativePropertiesN<1> sNativeProperties = {
732
  false, 0,
733
  false, 0,
734
  false, 0,
735
  true,  0 /* sAttributes */,
736
  false, 0,
737
  false, 0,
738
  false, 0,
739
  -1,
740
  11,
741
  sNativeProperties_sortedPropertyIndices,
742
  {
743
    { sAttributes, &sNativeProperties_propertyInfos[0] }
744
  }
745
};
746
static_assert(11 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
747
    "We have a property info count that is oversized");
748
749
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
750
  {
751
    "Function",
752
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
753
    &sBoringInterfaceObjectClassClassOps,
754
    JS_NULL_CLASS_SPEC,
755
    JS_NULL_CLASS_EXT,
756
    &sInterfaceObjectClassObjectOps
757
  },
758
  eInterface,
759
  true,
760
  prototypes::id::Gamepad,
761
  PrototypeTraits<prototypes::id::Gamepad>::Depth,
762
  sNativePropertyHooks,
763
  "function Gamepad() {\n    [native code]\n}",
764
  JS::GetRealmFunctionPrototype
765
};
766
767
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
768
  {
769
    "GamepadPrototype",
770
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
771
    JS_NULL_CLASS_OPS,
772
    JS_NULL_CLASS_SPEC,
773
    JS_NULL_CLASS_EXT,
774
    JS_NULL_OBJECT_OPS
775
  },
776
  eInterfacePrototype,
777
  false,
778
  prototypes::id::Gamepad,
779
  PrototypeTraits<prototypes::id::Gamepad>::Depth,
780
  sNativePropertyHooks,
781
  "[object GamepadPrototype]",
782
  JS::GetRealmObjectPrototype
783
};
784
785
bool
786
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
787
0
{
788
0
  static bool sPrefValue;
789
0
  static bool sPrefCacheSetUp = false;
790
0
  if (!sPrefCacheSetUp) {
791
0
    sPrefCacheSetUp = true;
792
0
    Preferences::AddBoolVarCache(&sPrefValue, "dom.gamepad.enabled");
793
0
  }
794
0
795
0
  return sPrefValue;
796
0
}
797
798
static const js::ClassOps sClassOps = {
799
  _addProperty, /* addProperty */
800
  nullptr,               /* delProperty */
801
  nullptr,               /* enumerate */
802
  nullptr, /* newEnumerate */
803
  nullptr, /* resolve */
804
  nullptr, /* mayResolve */
805
  _finalize, /* finalize */
806
  nullptr, /* call */
807
  nullptr,               /* hasInstance */
808
  nullptr,               /* construct */
809
  nullptr, /* trace */
810
};
811
812
static const js::ClassExtension sClassExtension = {
813
  nullptr, /* weakmapKeyDelegateOp */
814
  _objectMoved /* objectMovedOp */
815
};
816
817
static const DOMJSClass sClass = {
818
  { "Gamepad",
819
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(4),
820
    &sClassOps,
821
    JS_NULL_CLASS_SPEC,
822
    &sClassExtension,
823
    JS_NULL_OBJECT_OPS
824
  },
825
  { prototypes::id::Gamepad, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
826
  IsBaseOf<nsISupports, mozilla::dom::Gamepad >::value,
827
  sNativePropertyHooks,
828
  FindAssociatedGlobalForNative<mozilla::dom::Gamepad>::Get,
829
  GetProtoObjectHandle,
830
  GetCCParticipant<mozilla::dom::Gamepad>::Get()
831
};
832
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
833
              "Must have the right minimal number of reserved slots.");
834
static_assert(4 >= 4,
835
              "Must have enough reserved slots.");
836
837
const JSClass*
838
GetJSClass()
839
0
{
840
0
  return sClass.ToJSClass();
841
0
}
842
843
bool
844
Wrap(JSContext* aCx, mozilla::dom::Gamepad* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
845
0
{
846
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::Gamepad>::value,
847
0
                "Shouldn't have wrappercached things that are not refcounted.");
848
0
  MOZ_ASSERT(static_cast<mozilla::dom::Gamepad*>(aObject) ==
849
0
             reinterpret_cast<mozilla::dom::Gamepad*>(aObject),
850
0
             "Multiple inheritance for mozilla::dom::Gamepad is broken.");
851
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
852
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
853
0
  MOZ_ASSERT(!aCache->GetWrapper(),
854
0
             "You should probably not be using Wrap() directly; use "
855
0
             "GetOrCreateDOMReflector instead");
856
0
857
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
858
0
             "nsISupports must be on our primary inheritance chain");
859
0
860
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
861
0
  if (!global) {
862
0
    return false;
863
0
  }
864
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
865
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
866
0
867
0
  // That might have ended up wrapping us already, due to the wonders
868
0
  // of XBL.  Check for that, and bail out as needed.
869
0
  aReflector.set(aCache->GetWrapper());
870
0
  if (aReflector) {
871
#ifdef DEBUG
872
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
873
#endif // DEBUG
874
    return true;
875
0
  }
876
0
877
0
  JSAutoRealm ar(aCx, global);
878
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
879
0
  if (!canonicalProto) {
880
0
    return false;
881
0
  }
882
0
  JS::Rooted<JSObject*> proto(aCx);
883
0
  if (aGivenProto) {
884
0
    proto = aGivenProto;
885
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
886
0
    // coming in, we changed compartments to that of "parent" so may need
887
0
    // to wrap the proto here.
888
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
889
0
      if (!JS_WrapObject(aCx, &proto)) {
890
0
        return false;
891
0
      }
892
0
    }
893
0
  } else {
894
0
    proto = canonicalProto;
895
0
  }
896
0
897
0
  BindingJSObjectCreator<mozilla::dom::Gamepad> creator(aCx);
898
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
899
0
  if (!aReflector) {
900
0
    return false;
901
0
  }
902
0
903
0
  aCache->SetWrapper(aReflector);
904
0
  creator.InitializationSucceeded();
905
0
906
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
907
0
             aCache->GetWrapperPreserveColor() == aReflector);
908
0
  // If proto != canonicalProto, we have to preserve our wrapper;
909
0
  // otherwise we won't be able to properly recreate it later, since
910
0
  // we won't know what proto to use.  Note that we don't check
911
0
  // aGivenProto here, since it's entirely possible (and even
912
0
  // somewhat common) to have a non-null aGivenProto which is the
913
0
  // same as canonicalProto.
914
0
  if (proto != canonicalProto) {
915
0
    PreserveWrapper(aObject);
916
0
  }
917
0
918
0
  return true;
919
0
}
920
921
// This may allocate too many slots, because we only really need
922
// slots for our non-interface-typed members that we cache.  But
923
// allocating slots only for those would make the slot index
924
// computations much more complicated, so let's do this the simple
925
// way for now.
926
DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 3);
927
928
const NativePropertyHooks sNativePropertyHooks[] = { {
929
  nullptr,
930
  nullptr,
931
  nullptr,
932
  { sNativeProperties.Upcast(), nullptr },
933
  prototypes::id::Gamepad,
934
  constructors::id::Gamepad,
935
  nullptr,
936
  &sXrayExpandoObjectClass
937
} };
938
939
void
940
ClearCachedButtonsValue(mozilla::dom::Gamepad* aObject)
941
0
{
942
0
  JSObject* obj;
943
0
  obj = aObject->GetWrapper();
944
0
  if (!obj) {
945
0
    return;
946
0
  }
947
0
  js::SetReservedSlot(obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), JS::UndefinedValue());
948
0
  xpc::ClearXrayExpandoSlots(obj, (xpc::JSSLOT_EXPANDO_COUNT + 0));
949
0
}
950
951
void
952
ClearCachedAxesValue(mozilla::dom::Gamepad* aObject)
953
0
{
954
0
  JSObject* obj;
955
0
  obj = aObject->GetWrapper();
956
0
  if (!obj) {
957
0
    return;
958
0
  }
959
0
  js::SetReservedSlot(obj, (DOM_INSTANCE_RESERVED_SLOTS + 1), JS::UndefinedValue());
960
0
  xpc::ClearXrayExpandoSlots(obj, (xpc::JSSLOT_EXPANDO_COUNT + 1));
961
0
}
962
963
void
964
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
965
0
{
966
0
  JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
967
0
  if (!parentProto) {
968
0
    return;
969
0
  }
970
0
971
0
  JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
972
0
  if (!constructorProto) {
973
0
    return;
974
0
  }
975
0
976
0
  static bool sIdsInited = false;
977
0
  if (!sIdsInited && NS_IsMainThread()) {
978
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
979
0
      return;
980
0
    }
981
0
    sIdsInited = true;
982
0
  }
983
0
984
0
  static bool sPrefCachesInited = false;
985
0
  if (!sPrefCachesInited && NS_IsMainThread()) {
986
0
    sPrefCachesInited = true;
987
0
    Preferences::AddBoolVarCache(&sAttributes[1].disablers->enabled, "dom.gamepad.extensions.enabled");
988
0
    Preferences::AddBoolVarCache(&sAttributes[2].disablers->enabled, "dom.vr.enabled");
989
0
    Preferences::AddBoolVarCache(&sAttributes[4].disablers->enabled, "dom.gamepad.extensions.enabled");
990
0
  }
991
0
992
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::Gamepad);
993
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::Gamepad);
994
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
995
0
                              &sPrototypeClass.mBase, protoCache,
996
0
                              nullptr,
997
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
998
0
                              interfaceCache,
999
0
                              sNativeProperties.Upcast(),
1000
0
                              nullptr,
1001
0
                              "Gamepad", aDefineOnGlobal,
1002
0
                              nullptr,
1003
0
                              false);
1004
0
}
1005
1006
JSObject*
1007
GetConstructorObject(JSContext* aCx)
1008
0
{
1009
0
  return GetConstructorObjectHandle(aCx);
1010
0
}
1011
1012
} // namespace Gamepad_Binding
1013
1014
1015
1016
namespace GamepadButton_Binding {
1017
1018
MOZ_CAN_RUN_SCRIPT static bool
1019
get_pressed(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::GamepadButton* self, JSJitGetterCallArgs args)
1020
0
{
1021
0
  AUTO_PROFILER_LABEL_FAST("get GamepadButton.pressed", DOM, cx);
1022
0
1023
0
  bool result(self->Pressed());
1024
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1025
0
  args.rval().setBoolean(result);
1026
0
  return true;
1027
0
}
1028
1029
static const JSJitInfo pressed_getterinfo = {
1030
  { (JSJitGetterOp)get_pressed },
1031
  { prototypes::id::GamepadButton },
1032
  { PrototypeTraits<prototypes::id::GamepadButton>::Depth },
1033
  JSJitInfo::Getter,
1034
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
1035
  JSVAL_TYPE_BOOLEAN,  /* returnType.  Not relevant for setters. */
1036
  true,  /* isInfallible. False in setters. */
1037
  false,  /* isMovable.  Not relevant for setters. */
1038
  false, /* isEliminatable.  Not relevant for setters. */
1039
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1040
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1041
  false,  /* isTypedMethod.  Only relevant for methods. */
1042
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1043
};
1044
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1045
static_assert(0 < 1, "There is no slot for us");
1046
1047
MOZ_CAN_RUN_SCRIPT static bool
1048
get_touched(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::GamepadButton* self, JSJitGetterCallArgs args)
1049
0
{
1050
0
  AUTO_PROFILER_LABEL_FAST("get GamepadButton.touched", DOM, cx);
1051
0
1052
0
  bool result(self->Touched());
1053
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1054
0
  args.rval().setBoolean(result);
1055
0
  return true;
1056
0
}
1057
1058
static const JSJitInfo touched_getterinfo = {
1059
  { (JSJitGetterOp)get_touched },
1060
  { prototypes::id::GamepadButton },
1061
  { PrototypeTraits<prototypes::id::GamepadButton>::Depth },
1062
  JSJitInfo::Getter,
1063
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
1064
  JSVAL_TYPE_BOOLEAN,  /* returnType.  Not relevant for setters. */
1065
  true,  /* isInfallible. False in setters. */
1066
  false,  /* isMovable.  Not relevant for setters. */
1067
  false, /* isEliminatable.  Not relevant for setters. */
1068
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1069
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1070
  false,  /* isTypedMethod.  Only relevant for methods. */
1071
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1072
};
1073
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1074
static_assert(0 < 1, "There is no slot for us");
1075
1076
MOZ_CAN_RUN_SCRIPT static bool
1077
get_value(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::GamepadButton* self, JSJitGetterCallArgs args)
1078
0
{
1079
0
  AUTO_PROFILER_LABEL_FAST("get GamepadButton.value", DOM, cx);
1080
0
1081
0
  double result(self->Value());
1082
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
1083
0
  args.rval().set(JS_NumberValue(double(result)));
1084
0
  return true;
1085
0
}
1086
1087
static const JSJitInfo value_getterinfo = {
1088
  { (JSJitGetterOp)get_value },
1089
  { prototypes::id::GamepadButton },
1090
  { PrototypeTraits<prototypes::id::GamepadButton>::Depth },
1091
  JSJitInfo::Getter,
1092
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
1093
  JSVAL_TYPE_DOUBLE,  /* returnType.  Not relevant for setters. */
1094
  true,  /* isInfallible. False in setters. */
1095
  false,  /* isMovable.  Not relevant for setters. */
1096
  false, /* isEliminatable.  Not relevant for setters. */
1097
  false, /* isAlwaysInSlot.  Only relevant for getters. */
1098
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
1099
  false,  /* isTypedMethod.  Only relevant for methods. */
1100
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
1101
};
1102
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1103
static_assert(0 < 1, "There is no slot for us");
1104
1105
static bool
1106
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
1107
0
{
1108
0
  mozilla::dom::GamepadButton* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::GamepadButton>(obj);
1109
0
  // We don't want to preserve if we don't have a wrapper, and we
1110
0
  // obviously can't preserve if we're not initialized.
1111
0
  if (self && self->GetWrapperPreserveColor()) {
1112
0
    PreserveWrapper(self);
1113
0
  }
1114
0
  return true;
1115
0
}
1116
1117
static void
1118
_finalize(js::FreeOp* fop, JSObject* obj)
1119
0
{
1120
0
  mozilla::dom::GamepadButton* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::GamepadButton>(obj);
1121
0
  if (self) {
1122
0
    ClearWrapper(self, self, obj);
1123
0
    AddForDeferredFinalization<mozilla::dom::GamepadButton>(self);
1124
0
  }
1125
0
}
1126
1127
static size_t
1128
_objectMoved(JSObject* obj, JSObject* old)
1129
0
{
1130
0
  mozilla::dom::GamepadButton* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::GamepadButton>(obj);
1131
0
  if (self) {
1132
0
    UpdateWrapper(self, self, obj, old);
1133
0
  }
1134
0
1135
0
  return 0;
1136
0
}
1137
1138
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
1139
#if defined(__clang__)
1140
#pragma clang diagnostic push
1141
#pragma clang diagnostic ignored "-Wmissing-braces"
1142
#endif
1143
static const JSPropertySpec sAttributes_specs[] = {
1144
  { "pressed", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &pressed_getterinfo, nullptr, nullptr },
1145
  { "touched", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &touched_getterinfo, nullptr, nullptr },
1146
  { "value", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &value_getterinfo, nullptr, nullptr },
1147
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
1148
};
1149
#if defined(__clang__)
1150
#pragma clang diagnostic pop
1151
#endif
1152
1153
1154
static const Prefable<const JSPropertySpec> sAttributes[] = {
1155
  { nullptr, &sAttributes_specs[0] },
1156
  { nullptr, nullptr }
1157
};
1158
1159
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
1160
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
1161
static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
1162
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
1163
1164
1165
static uint16_t sNativeProperties_sortedPropertyIndices[3];
1166
static PropertyInfo sNativeProperties_propertyInfos[3];
1167
1168
static const NativePropertiesN<1> sNativeProperties = {
1169
  false, 0,
1170
  false, 0,
1171
  false, 0,
1172
  true,  0 /* sAttributes */,
1173
  false, 0,
1174
  false, 0,
1175
  false, 0,
1176
  -1,
1177
  3,
1178
  sNativeProperties_sortedPropertyIndices,
1179
  {
1180
    { sAttributes, &sNativeProperties_propertyInfos[0] }
1181
  }
1182
};
1183
static_assert(3 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
1184
    "We have a property info count that is oversized");
1185
1186
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
1187
  {
1188
    "Function",
1189
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
1190
    &sBoringInterfaceObjectClassClassOps,
1191
    JS_NULL_CLASS_SPEC,
1192
    JS_NULL_CLASS_EXT,
1193
    &sInterfaceObjectClassObjectOps
1194
  },
1195
  eInterface,
1196
  true,
1197
  prototypes::id::GamepadButton,
1198
  PrototypeTraits<prototypes::id::GamepadButton>::Depth,
1199
  sNativePropertyHooks,
1200
  "function GamepadButton() {\n    [native code]\n}",
1201
  JS::GetRealmFunctionPrototype
1202
};
1203
1204
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
1205
  {
1206
    "GamepadButtonPrototype",
1207
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
1208
    JS_NULL_CLASS_OPS,
1209
    JS_NULL_CLASS_SPEC,
1210
    JS_NULL_CLASS_EXT,
1211
    JS_NULL_OBJECT_OPS
1212
  },
1213
  eInterfacePrototype,
1214
  false,
1215
  prototypes::id::GamepadButton,
1216
  PrototypeTraits<prototypes::id::GamepadButton>::Depth,
1217
  sNativePropertyHooks,
1218
  "[object GamepadButtonPrototype]",
1219
  JS::GetRealmObjectPrototype
1220
};
1221
1222
bool
1223
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
1224
0
{
1225
0
  static bool sPrefValue;
1226
0
  static bool sPrefCacheSetUp = false;
1227
0
  if (!sPrefCacheSetUp) {
1228
0
    sPrefCacheSetUp = true;
1229
0
    Preferences::AddBoolVarCache(&sPrefValue, "dom.gamepad.enabled");
1230
0
  }
1231
0
1232
0
  return sPrefValue;
1233
0
}
1234
1235
static const js::ClassOps sClassOps = {
1236
  _addProperty, /* addProperty */
1237
  nullptr,               /* delProperty */
1238
  nullptr,               /* enumerate */
1239
  nullptr, /* newEnumerate */
1240
  nullptr, /* resolve */
1241
  nullptr, /* mayResolve */
1242
  _finalize, /* finalize */
1243
  nullptr, /* call */
1244
  nullptr,               /* hasInstance */
1245
  nullptr,               /* construct */
1246
  nullptr, /* trace */
1247
};
1248
1249
static const js::ClassExtension sClassExtension = {
1250
  nullptr, /* weakmapKeyDelegateOp */
1251
  _objectMoved /* objectMovedOp */
1252
};
1253
1254
static const DOMJSClass sClass = {
1255
  { "GamepadButton",
1256
    JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
1257
    &sClassOps,
1258
    JS_NULL_CLASS_SPEC,
1259
    &sClassExtension,
1260
    JS_NULL_OBJECT_OPS
1261
  },
1262
  { prototypes::id::GamepadButton, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
1263
  IsBaseOf<nsISupports, mozilla::dom::GamepadButton >::value,
1264
  sNativePropertyHooks,
1265
  FindAssociatedGlobalForNative<mozilla::dom::GamepadButton>::Get,
1266
  GetProtoObjectHandle,
1267
  GetCCParticipant<mozilla::dom::GamepadButton>::Get()
1268
};
1269
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
1270
              "Must have the right minimal number of reserved slots.");
1271
static_assert(1 >= 1,
1272
              "Must have enough reserved slots.");
1273
1274
const JSClass*
1275
GetJSClass()
1276
0
{
1277
0
  return sClass.ToJSClass();
1278
0
}
1279
1280
bool
1281
Wrap(JSContext* aCx, mozilla::dom::GamepadButton* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1282
0
{
1283
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::GamepadButton>::value,
1284
0
                "Shouldn't have wrappercached things that are not refcounted.");
1285
0
  MOZ_ASSERT(static_cast<mozilla::dom::GamepadButton*>(aObject) ==
1286
0
             reinterpret_cast<mozilla::dom::GamepadButton*>(aObject),
1287
0
             "Multiple inheritance for mozilla::dom::GamepadButton is broken.");
1288
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1289
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1290
0
  MOZ_ASSERT(!aCache->GetWrapper(),
1291
0
             "You should probably not be using Wrap() directly; use "
1292
0
             "GetOrCreateDOMReflector instead");
1293
0
1294
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
1295
0
             "nsISupports must be on our primary inheritance chain");
1296
0
1297
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
1298
0
  if (!global) {
1299
0
    return false;
1300
0
  }
1301
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
1302
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
1303
0
1304
0
  // That might have ended up wrapping us already, due to the wonders
1305
0
  // of XBL.  Check for that, and bail out as needed.
1306
0
  aReflector.set(aCache->GetWrapper());
1307
0
  if (aReflector) {
1308
#ifdef DEBUG
1309
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
1310
#endif // DEBUG
1311
    return true;
1312
0
  }
1313
0
1314
0
  JSAutoRealm ar(aCx, global);
1315
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1316
0
  if (!canonicalProto) {
1317
0
    return false;
1318
0
  }
1319
0
  JS::Rooted<JSObject*> proto(aCx);
1320
0
  if (aGivenProto) {
1321
0
    proto = aGivenProto;
1322
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
1323
0
    // coming in, we changed compartments to that of "parent" so may need
1324
0
    // to wrap the proto here.
1325
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1326
0
      if (!JS_WrapObject(aCx, &proto)) {
1327
0
        return false;
1328
0
      }
1329
0
    }
1330
0
  } else {
1331
0
    proto = canonicalProto;
1332
0
  }
1333
0
1334
0
  BindingJSObjectCreator<mozilla::dom::GamepadButton> creator(aCx);
1335
0
  creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
1336
0
  if (!aReflector) {
1337
0
    return false;
1338
0
  }
1339
0
1340
0
  aCache->SetWrapper(aReflector);
1341
0
  creator.InitializationSucceeded();
1342
0
1343
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
1344
0
             aCache->GetWrapperPreserveColor() == aReflector);
1345
0
  // If proto != canonicalProto, we have to preserve our wrapper;
1346
0
  // otherwise we won't be able to properly recreate it later, since
1347
0
  // we won't know what proto to use.  Note that we don't check
1348
0
  // aGivenProto here, since it's entirely possible (and even
1349
0
  // somewhat common) to have a non-null aGivenProto which is the
1350
0
  // same as canonicalProto.
1351
0
  if (proto != canonicalProto) {
1352
0
    PreserveWrapper(aObject);
1353
0
  }
1354
0
1355
0
  return true;
1356
0
}
1357
1358
const NativePropertyHooks sNativePropertyHooks[] = { {
1359
  nullptr,
1360
  nullptr,
1361
  nullptr,
1362
  { sNativeProperties.Upcast(), nullptr },
1363
  prototypes::id::GamepadButton,
1364
  constructors::id::GamepadButton,
1365
  nullptr,
1366
  &DefaultXrayExpandoObjectClass
1367
} };
1368
1369
void
1370
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
1371
0
{
1372
0
  JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
1373
0
  if (!parentProto) {
1374
0
    return;
1375
0
  }
1376
0
1377
0
  JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
1378
0
  if (!constructorProto) {
1379
0
    return;
1380
0
  }
1381
0
1382
0
  static bool sIdsInited = false;
1383
0
  if (!sIdsInited && NS_IsMainThread()) {
1384
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
1385
0
      return;
1386
0
    }
1387
0
    sIdsInited = true;
1388
0
  }
1389
0
1390
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::GamepadButton);
1391
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::GamepadButton);
1392
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
1393
0
                              &sPrototypeClass.mBase, protoCache,
1394
0
                              nullptr,
1395
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
1396
0
                              interfaceCache,
1397
0
                              sNativeProperties.Upcast(),
1398
0
                              nullptr,
1399
0
                              "GamepadButton", aDefineOnGlobal,
1400
0
                              nullptr,
1401
0
                              false);
1402
0
}
1403
1404
JSObject*
1405
GetConstructorObject(JSContext* aCx)
1406
0
{
1407
0
  return GetConstructorObjectHandle(aCx);
1408
0
}
1409
1410
} // namespace GamepadButton_Binding
1411
1412
1413
1414
} // namespace dom
1415
} // namespace mozilla