Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dom/bindings/HTMLOptionsCollectionBinding.cpp
Line
Count
Source (jump to first uncovered line)
1
/* THIS FILE IS AUTOGENERATED FROM HTMLOptionsCollection.webidl BY Codegen.py - DO NOT EDIT */
2
3
#include "HTMLCollectionBinding.h"
4
#include "HTMLOptionsCollectionBinding.h"
5
#include "WrapperFactory.h"
6
#include "mozilla/OwningNonNull.h"
7
#include "mozilla/dom/BindingUtils.h"
8
#include "mozilla/dom/CustomElementRegistry.h"
9
#include "mozilla/dom/DOMJSClass.h"
10
#include "mozilla/dom/DOMJSProxyHandler.h"
11
#include "mozilla/dom/DocGroup.h"
12
#include "mozilla/dom/HTMLOptionElement.h"
13
#include "mozilla/dom/HTMLOptionsCollection.h"
14
#include "mozilla/dom/NonRefcountedDOMObject.h"
15
#include "mozilla/dom/Nullable.h"
16
#include "mozilla/dom/PrimitiveConversions.h"
17
#include "mozilla/dom/UnionConversions.h"
18
#include "mozilla/dom/UnionTypes.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 HTMLOptionsCollection_Binding {
29
30
static_assert(IsRefcounted<NativeType>::value == IsRefcounted<HTMLCollection_Binding::NativeType>::value,
31
              "Can't inherit from an interface with a different ownership model.");
32
33
MOZ_CAN_RUN_SCRIPT static bool
34
get_length(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::HTMLOptionsCollection* self, JSJitGetterCallArgs args)
35
0
{
36
0
  AUTO_PROFILER_LABEL_FAST("get HTMLOptionsCollection.length", DOM, cx);
37
0
38
0
  uint32_t result(self->Length());
39
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
40
0
  args.rval().setNumber(result);
41
0
  return true;
42
0
}
43
44
MOZ_CAN_RUN_SCRIPT static bool
45
set_length(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::HTMLOptionsCollection* self, JSJitSetterCallArgs args)
46
0
{
47
0
  AUTO_PROFILER_LABEL_FAST("set HTMLOptionsCollection.length", DOM, cx);
48
0
49
0
  uint32_t arg0;
50
0
  if (!ValueToPrimitive<uint32_t, eDefault>(cx, args[0], &arg0)) {
51
0
    return false;
52
0
  }
53
0
  Maybe<AutoCEReaction> ceReaction;
54
0
  if (CustomElementRegistry::IsCustomElementEnabled(cx, obj)) {
55
0
    DocGroup* docGroup = self->GetDocGroup();
56
0
    if (docGroup) {
57
0
      ceReaction.emplace(docGroup->CustomElementReactionsStack(), cx);
58
0
    }
59
0
  }
60
0
  FastErrorResult rv;
61
0
  self->SetLength(arg0, rv);
62
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
63
0
    return false;
64
0
  }
65
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
66
0
67
0
  return true;
68
0
}
69
70
static const JSJitInfo length_getterinfo = {
71
  { (JSJitGetterOp)get_length },
72
  { prototypes::id::HTMLOptionsCollection },
73
  { PrototypeTraits<prototypes::id::HTMLOptionsCollection>::Depth },
74
  JSJitInfo::Getter,
75
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
76
  JSVAL_TYPE_DOUBLE,  /* returnType.  Not relevant for setters. */
77
  true,  /* isInfallible. False in setters. */
78
  false,  /* isMovable.  Not relevant for setters. */
79
  false, /* isEliminatable.  Not relevant for setters. */
80
  false, /* isAlwaysInSlot.  Only relevant for getters. */
81
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
82
  false,  /* isTypedMethod.  Only relevant for methods. */
83
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
84
};
85
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
86
static_assert(0 < 1, "There is no slot for us");
87
static const JSJitInfo length_setterinfo = {
88
  { (JSJitGetterOp)set_length },
89
  { prototypes::id::HTMLOptionsCollection },
90
  { PrototypeTraits<prototypes::id::HTMLOptionsCollection>::Depth },
91
  JSJitInfo::Setter,
92
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
93
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
94
  false,  /* isInfallible. False in setters. */
95
  false,  /* isMovable.  Not relevant for setters. */
96
  false, /* isEliminatable.  Not relevant for setters. */
97
  false, /* isAlwaysInSlot.  Only relevant for getters. */
98
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
99
  false,  /* isTypedMethod.  Only relevant for methods. */
100
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
101
};
102
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
103
static_assert(0 < 1, "There is no slot for us");
104
105
MOZ_CAN_RUN_SCRIPT static bool
106
add(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::HTMLOptionsCollection* self, const JSJitMethodCallArgs& args)
107
0
{
108
0
  AUTO_PROFILER_LABEL_FAST("HTMLOptionsCollection.add", DOM, cx);
109
0
110
0
  if (MOZ_UNLIKELY(args.length() < 1)) {
111
0
    return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "HTMLOptionsCollection.add");
112
0
  }
113
0
  HTMLOptionElementOrHTMLOptGroupElement arg0;
114
0
  HTMLOptionElementOrHTMLOptGroupElementArgument arg0_holder(arg0);
115
0
  {
116
0
    bool done = false, failed = false, tryNext;
117
0
    if (args[0].isObject()) {
118
0
      done = (failed = !arg0_holder.TrySetToHTMLOptionElement(cx, args[0], tryNext, false)) || !tryNext ||
119
0
             (failed = !arg0_holder.TrySetToHTMLOptGroupElement(cx, args[0], tryNext, false)) || !tryNext;
120
0
121
0
    }
122
0
    if (failed) {
123
0
      return false;
124
0
    }
125
0
    if (!done) {
126
0
      ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 1 of HTMLOptionsCollection.add", "HTMLOptionElement, HTMLOptGroupElement");
127
0
      return false;
128
0
    }
129
0
  }
130
0
  Nullable<HTMLElementOrLong > arg1;
131
0
  Maybe<HTMLElementOrLongArgument> arg1_holder;
132
0
  if (!(args.hasDefined(1)) || args[1].isNullOrUndefined()) {
133
0
    arg1.SetNull();
134
0
  } else {
135
0
    arg1_holder.emplace(arg1.SetValue());
136
0
    {
137
0
      bool done = false, failed = false, tryNext;
138
0
      if (args[1].isObject()) {
139
0
        done = (failed = !arg1_holder.ref().TrySetToHTMLElement(cx, args[1], tryNext, false)) || !tryNext;
140
0
141
0
      }
142
0
      if (!done) {
143
0
        do {
144
0
          done = (failed = !arg1_holder.ref().TrySetToLong(cx, args[1], tryNext)) || !tryNext;
145
0
          break;
146
0
        } while (false);
147
0
      }
148
0
      if (failed) {
149
0
        return false;
150
0
      }
151
0
      if (!done) {
152
0
        ThrowErrorMessage(cx, MSG_NOT_IN_UNION, "Argument 2 of HTMLOptionsCollection.add", "HTMLElement");
153
0
        return false;
154
0
      }
155
0
    }
156
0
  }
157
0
  Maybe<AutoCEReaction> ceReaction;
158
0
  if (CustomElementRegistry::IsCustomElementEnabled(cx, obj)) {
159
0
    DocGroup* docGroup = self->GetDocGroup();
160
0
    if (docGroup) {
161
0
      ceReaction.emplace(docGroup->CustomElementReactionsStack(), cx);
162
0
    }
163
0
  }
164
0
  FastErrorResult rv;
165
0
  self->Add(Constify(arg0), Constify(arg1), rv);
166
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
167
0
    return false;
168
0
  }
169
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
170
0
  args.rval().setUndefined();
171
0
  return true;
172
0
}
173
174
static const JSJitInfo add_methodinfo = {
175
  { (JSJitGetterOp)add },
176
  { prototypes::id::HTMLOptionsCollection },
177
  { PrototypeTraits<prototypes::id::HTMLOptionsCollection>::Depth },
178
  JSJitInfo::Method,
179
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
180
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
181
  false,  /* isInfallible. False in setters. */
182
  false,  /* isMovable.  Not relevant for setters. */
183
  false, /* isEliminatable.  Not relevant for setters. */
184
  false, /* isAlwaysInSlot.  Only relevant for getters. */
185
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
186
  false,  /* isTypedMethod.  Only relevant for methods. */
187
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
188
};
189
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
190
static_assert(0 < 1, "There is no slot for us");
191
192
MOZ_CAN_RUN_SCRIPT static bool
193
remove(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::HTMLOptionsCollection* self, const JSJitMethodCallArgs& args)
194
0
{
195
0
  AUTO_PROFILER_LABEL_FAST("HTMLOptionsCollection.remove", DOM, cx);
196
0
197
0
  if (MOZ_UNLIKELY(args.length() < 1)) {
198
0
    return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "HTMLOptionsCollection.remove");
199
0
  }
200
0
  int32_t arg0;
201
0
  if (!ValueToPrimitive<int32_t, eDefault>(cx, args[0], &arg0)) {
202
0
    return false;
203
0
  }
204
0
  Maybe<AutoCEReaction> ceReaction;
205
0
  if (CustomElementRegistry::IsCustomElementEnabled(cx, obj)) {
206
0
    DocGroup* docGroup = self->GetDocGroup();
207
0
    if (docGroup) {
208
0
      ceReaction.emplace(docGroup->CustomElementReactionsStack(), cx);
209
0
    }
210
0
  }
211
0
  FastErrorResult rv;
212
0
  self->Remove(arg0, rv);
213
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
214
0
    return false;
215
0
  }
216
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
217
0
  args.rval().setUndefined();
218
0
  return true;
219
0
}
220
221
static const JSJitInfo remove_methodinfo = {
222
  { (JSJitGetterOp)remove },
223
  { prototypes::id::HTMLOptionsCollection },
224
  { PrototypeTraits<prototypes::id::HTMLOptionsCollection>::Depth },
225
  JSJitInfo::Method,
226
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
227
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
228
  false,  /* isInfallible. False in setters. */
229
  false,  /* isMovable.  Not relevant for setters. */
230
  false, /* isEliminatable.  Not relevant for setters. */
231
  false, /* isAlwaysInSlot.  Only relevant for getters. */
232
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
233
  false,  /* isTypedMethod.  Only relevant for methods. */
234
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
235
};
236
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
237
static_assert(0 < 1, "There is no slot for us");
238
239
MOZ_CAN_RUN_SCRIPT static bool
240
get_selectedIndex(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::HTMLOptionsCollection* self, JSJitGetterCallArgs args)
241
0
{
242
0
  AUTO_PROFILER_LABEL_FAST("get HTMLOptionsCollection.selectedIndex", DOM, cx);
243
0
244
0
  FastErrorResult rv;
245
0
  int32_t result(self->GetSelectedIndex(rv));
246
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
247
0
    return false;
248
0
  }
249
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
250
0
  args.rval().setInt32(int32_t(result));
251
0
  return true;
252
0
}
253
254
MOZ_CAN_RUN_SCRIPT static bool
255
set_selectedIndex(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::HTMLOptionsCollection* self, JSJitSetterCallArgs args)
256
0
{
257
0
  AUTO_PROFILER_LABEL_FAST("set HTMLOptionsCollection.selectedIndex", DOM, cx);
258
0
259
0
  int32_t arg0;
260
0
  if (!ValueToPrimitive<int32_t, eDefault>(cx, args[0], &arg0)) {
261
0
    return false;
262
0
  }
263
0
  FastErrorResult rv;
264
0
  self->SetSelectedIndex(arg0, rv);
265
0
  if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
266
0
    return false;
267
0
  }
268
0
  MOZ_ASSERT(!JS_IsExceptionPending(cx));
269
0
270
0
  return true;
271
0
}
272
273
static const JSJitInfo selectedIndex_getterinfo = {
274
  { (JSJitGetterOp)get_selectedIndex },
275
  { prototypes::id::HTMLOptionsCollection },
276
  { PrototypeTraits<prototypes::id::HTMLOptionsCollection>::Depth },
277
  JSJitInfo::Getter,
278
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
279
  JSVAL_TYPE_INT32,  /* returnType.  Not relevant for setters. */
280
  false,  /* isInfallible. False in setters. */
281
  false,  /* isMovable.  Not relevant for setters. */
282
  false, /* isEliminatable.  Not relevant for setters. */
283
  false, /* isAlwaysInSlot.  Only relevant for getters. */
284
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
285
  false,  /* isTypedMethod.  Only relevant for methods. */
286
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
287
};
288
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
289
static_assert(0 < 1, "There is no slot for us");
290
static const JSJitInfo selectedIndex_setterinfo = {
291
  { (JSJitGetterOp)set_selectedIndex },
292
  { prototypes::id::HTMLOptionsCollection },
293
  { PrototypeTraits<prototypes::id::HTMLOptionsCollection>::Depth },
294
  JSJitInfo::Setter,
295
  JSJitInfo::AliasEverything, /* aliasSet.  Not relevant for setters. */
296
  JSVAL_TYPE_UNDEFINED,  /* returnType.  Not relevant for setters. */
297
  false,  /* isInfallible. False in setters. */
298
  false,  /* isMovable.  Not relevant for setters. */
299
  false, /* isEliminatable.  Not relevant for setters. */
300
  false, /* isAlwaysInSlot.  Only relevant for getters. */
301
  false, /* isLazilyCachedInSlot.  Only relevant for getters. */
302
  false,  /* isTypedMethod.  Only relevant for methods. */
303
  0   /* Reserved slot index, if we're stored in a slot, else 0. */
304
};
305
static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
306
static_assert(0 < 1, "There is no slot for us");
307
308
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
309
#if defined(__clang__)
310
#pragma clang diagnostic push
311
#pragma clang diagnostic ignored "-Wmissing-braces"
312
#endif
313
static const JSFunctionSpec sMethods_specs[] = {
314
  JS_FNSPEC("add", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&add_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
315
  JS_FNSPEC("remove", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&remove_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
316
  JS_SYM_FNSPEC(iterator, nullptr, nullptr, 0, 0, "ArrayValues"),
317
  JS_FS_END
318
};
319
#if defined(__clang__)
320
#pragma clang diagnostic pop
321
#endif
322
323
324
static const Prefable<const JSFunctionSpec> sMethods[] = {
325
  { nullptr, &sMethods_specs[0] },
326
  { nullptr, nullptr }
327
};
328
329
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
330
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
331
static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
332
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
333
334
// We deliberately use brace-elision to make Visual Studio produce better initalization code.
335
#if defined(__clang__)
336
#pragma clang diagnostic push
337
#pragma clang diagnostic ignored "-Wmissing-braces"
338
#endif
339
static const JSPropertySpec sAttributes_specs[] = {
340
  { "length", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &length_getterinfo, GenericSetter<NormalThisPolicy>, &length_setterinfo },
341
  { "selectedIndex", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &selectedIndex_getterinfo, GenericSetter<NormalThisPolicy>, &selectedIndex_setterinfo },
342
  { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
343
};
344
#if defined(__clang__)
345
#pragma clang diagnostic pop
346
#endif
347
348
349
static const Prefable<const JSPropertySpec> sAttributes[] = {
350
  { nullptr, &sAttributes_specs[0] },
351
  { nullptr, nullptr }
352
};
353
354
static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
355
    "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
356
static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
357
    "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
358
359
360
static uint16_t sNativeProperties_sortedPropertyIndices[5];
361
static PropertyInfo sNativeProperties_propertyInfos[5];
362
363
static const NativePropertiesN<2> sNativeProperties = {
364
  false, 0,
365
  false, 0,
366
  true,  0 /* sMethods */,
367
  true,  1 /* sAttributes */,
368
  false, 0,
369
  false, 0,
370
  false, 0,
371
  -1,
372
  5,
373
  sNativeProperties_sortedPropertyIndices,
374
  {
375
    { sMethods, &sNativeProperties_propertyInfos[0] },
376
    { sAttributes, &sNativeProperties_propertyInfos[3] }
377
  }
378
};
379
static_assert(5 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
380
    "We have a property info count that is oversized");
381
382
static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
383
  {
384
    "Function",
385
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
386
    &sBoringInterfaceObjectClassClassOps,
387
    JS_NULL_CLASS_SPEC,
388
    JS_NULL_CLASS_EXT,
389
    &sInterfaceObjectClassObjectOps
390
  },
391
  eInterface,
392
  true,
393
  prototypes::id::HTMLOptionsCollection,
394
  PrototypeTraits<prototypes::id::HTMLOptionsCollection>::Depth,
395
  sNativePropertyHooks,
396
  "function HTMLOptionsCollection() {\n    [native code]\n}",
397
  HTMLCollection_Binding::GetConstructorObject
398
};
399
400
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
401
  {
402
    "HTMLOptionsCollectionPrototype",
403
    JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
404
    JS_NULL_CLASS_OPS,
405
    JS_NULL_CLASS_SPEC,
406
    JS_NULL_CLASS_EXT,
407
    JS_NULL_OBJECT_OPS
408
  },
409
  eInterfacePrototype,
410
  false,
411
  prototypes::id::HTMLOptionsCollection,
412
  PrototypeTraits<prototypes::id::HTMLOptionsCollection>::Depth,
413
  sNativePropertyHooks,
414
  "[object HTMLOptionsCollectionPrototype]",
415
  HTMLCollection_Binding::GetProtoObject
416
};
417
418
static_assert(IsBaseOf<nsISupports, mozilla::dom::HTMLOptionsCollection >::value,
419
                  "We don't support non-nsISupports native classes for "
420
                  "proxy-based bindings yet");
421
422
423
class DOMProxyHandler : public mozilla::dom::DOMProxyHandler
424
{
425
public:
426
  explicit constexpr DOMProxyHandler()
427
0
  {
428
0
  }
429
430
  virtual bool
431
  getOwnPropDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool ignoreNamedProps, JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
432
433
  virtual bool
434
  defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& opresult, bool* defined) const override;
435
436
  using mozilla::dom::DOMProxyHandler::defineProperty;
437
438
  virtual bool
439
  ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy, unsigned flags, JS::AutoIdVector& props) const override;
440
441
  virtual bool
442
  hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) const override;
443
444
  virtual bool
445
  get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JS::Value> receiver, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
446
447
  virtual const char*
448
  className(JSContext* cx, JS::Handle<JSObject*> proxy) const override;
449
450
  virtual bool
451
  finalizeInBackground(const JS::Value& priv) const override;
452
453
  virtual void
454
  finalize(JSFreeOp* fop, JSObject* proxy) const override;
455
456
  static const DOMProxyHandler*
457
  getInstance();
458
459
  virtual bool
460
  delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::ObjectOpResult& opresult) const override;
461
462
  virtual bool
463
  getElements(JSContext* cx, JS::Handle<JSObject*> proxy, uint32_t begin, uint32_t end, js::ElementAdder* adder) const override;
464
465
  virtual bool
466
  setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::Handle<JS::Value> v, bool* done) const override;
467
468
  virtual size_t
469
  objectMoved(JSObject* obj, JSObject* old) const override;
470
};
471
472
MOZ_ALWAYS_INLINE bool
473
IsProxy(JSObject* obj)
474
0
{
475
0
  return js::IsProxy(obj) && js::GetProxyHandler(obj) == DOMProxyHandler::getInstance();
476
0
}
477
478
MOZ_ALWAYS_INLINE mozilla::dom::HTMLOptionsCollection*
479
UnwrapProxy(JSObject* obj)
480
0
{
481
0
  MOZ_ASSERT(js::IsProxy(obj));
482
0
  if (js::GetProxyHandler(obj) != DOMProxyHandler::getInstance()) {
483
0
    MOZ_ASSERT(xpc::WrapperFactory::IsXrayWrapper(obj));
484
0
    obj = js::UncheckedUnwrap(obj);
485
0
  }
486
0
  MOZ_ASSERT(IsProxy(obj));
487
0
  return static_cast<mozilla::dom::HTMLOptionsCollection*>(js::GetProxyReservedSlot(obj, DOM_OBJECT_SLOT).toPrivate());
488
0
}
489
490
bool
491
DOMProxyHandler::getOwnPropDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool ignoreNamedProps, JS::MutableHandle<JS::PropertyDescriptor> desc) const
492
0
{
493
0
  bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
494
0
  uint32_t index = GetArrayIndexFromId(cx, id);
495
0
  if (IsArrayIndex(index)) {
496
0
    mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
497
0
    bool found = false;
498
0
    auto result(StrongOrRawPtr<mozilla::dom::Element>(self->IndexedGetter(index, found)));
499
0
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
500
0
501
0
    if (found) {
502
0
      if (!result) {
503
0
        desc.value().setNull();
504
0
        FillPropertyDescriptor(desc, proxy, false);
505
0
        return true;
506
0
      }
507
0
      if (!GetOrCreateDOMReflector(cx, result, desc.value())) {
508
0
        MOZ_ASSERT(JS_IsExceptionPending(cx));
509
0
        return false;
510
0
      }
511
0
      FillPropertyDescriptor(desc, proxy, false);
512
0
      return true;
513
0
    }
514
0
  }
515
0
516
0
  JS::Rooted<JSObject*> expando(cx);
517
0
  if (!isXray && (expando = GetExpandoObject(proxy))) {
518
0
    if (!JS_GetOwnPropertyDescriptorById(cx, expando, id, desc)) {
519
0
      return false;
520
0
    }
521
0
    if (desc.object()) {
522
0
      // Pretend the property lives on the wrapper.
523
0
      desc.object().set(proxy);
524
0
      return true;
525
0
    }
526
0
  }
527
0
528
0
  bool callNamedGetter = false;
529
0
  if (!IsArrayIndex(index) && !ignoreNamedProps) {
530
0
    bool hasOnProto;
531
0
    if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
532
0
      return false;
533
0
    }
534
0
    callNamedGetter = !hasOnProto;
535
0
  }
536
0
  if (callNamedGetter) {
537
0
    FakeString name;
538
0
    bool isSymbol;
539
0
    if (!ConvertIdToString(cx, id, name, isSymbol)) {
540
0
      return false;
541
0
    }
542
0
    if (!isSymbol) {
543
0
      mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
544
0
      bool found = false;
545
0
      auto result(StrongOrRawPtr<mozilla::dom::Element>(self->NamedGetter(NonNullHelper(Constify(name)), found)));
546
0
      MOZ_ASSERT(!JS_IsExceptionPending(cx));
547
0
548
0
      if (found) {
549
0
        if (!result) {
550
0
          desc.value().setNull();
551
0
          FillPropertyDescriptor(desc, proxy, true, false);
552
0
          return true;
553
0
        }
554
0
        if (!GetOrCreateDOMReflector(cx, result, desc.value())) {
555
0
          MOZ_ASSERT(JS_IsExceptionPending(cx));
556
0
          return false;
557
0
        }
558
0
        FillPropertyDescriptor(desc, proxy, true, false);
559
0
        return true;
560
0
      }
561
0
    }
562
0
  }
563
0
564
0
  desc.object().set(nullptr);
565
0
  return true;
566
0
}
567
568
bool
569
DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& opresult, bool* defined) const
570
0
{
571
0
  uint32_t index = GetArrayIndexFromId(cx, id);
572
0
  if (IsArrayIndex(index)) {
573
0
    *defined = true;
574
0
    // https://heycam.github.io/webidl/#legacy-platform-object-defineownproperty
575
0
    // Step 1.1.  The no-indexed-setter case is handled by step 1.2.
576
0
    if (!desc.isDataDescriptor()) {
577
0
      return opresult.failNotDataDescriptor();
578
0
    }
579
0
580
0
    mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
581
0
    JS::Rooted<JS::Value> rootedValue(cx, desc.value());
582
0
    mozilla::dom::HTMLOptionElement* option;
583
0
    if (desc.value().isObject()) {
584
0
      {
585
0
        nsresult rv = UnwrapObject<prototypes::id::HTMLOptionElement, mozilla::dom::HTMLOptionElement>(&rootedValue, option);
586
0
        if (NS_FAILED(rv)) {
587
0
          ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Value being assigned to HTMLOptionsCollection setter", "HTMLOptionElement");
588
0
          return false;
589
0
        }
590
0
      }
591
0
    } else if (desc.value().isNullOrUndefined()) {
592
0
      option = nullptr;
593
0
    } else {
594
0
      ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Value being assigned to HTMLOptionsCollection setter");
595
0
      return false;
596
0
    }
597
0
    Maybe<AutoCEReaction> ceReaction;
598
0
    if (CustomElementRegistry::IsCustomElementEnabled(cx, proxy)) {
599
0
      DocGroup* docGroup = self->GetDocGroup();
600
0
      if (docGroup) {
601
0
        ceReaction.emplace(docGroup->CustomElementReactionsStack(), cx);
602
0
      }
603
0
    }
604
0
    FastErrorResult rv;
605
0
    self->IndexedSetter(index, MOZ_KnownLive(Constify(option)), rv);
606
0
    if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
607
0
      return false;
608
0
    }
609
0
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
610
0
    return opresult.succeed();
611
0
  }
612
0
  bool found = false;
613
0
  FakeString name;
614
0
  bool isSymbol;
615
0
  if (!ConvertIdToString(cx, id, name, isSymbol)) {
616
0
    return false;
617
0
  }
618
0
  if (!isSymbol) {
619
0
    mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
620
0
    auto result(StrongOrRawPtr<mozilla::dom::Element>(self->NamedGetter(NonNullHelper(Constify(name)), found)));
621
0
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
622
0
    (void)result;
623
0
  }
624
0
625
0
  if (found) {
626
0
    *defined = true;
627
0
    return opresult.failNoNamedSetter();
628
0
  }
629
0
  return mozilla::dom::DOMProxyHandler::defineProperty(cx, proxy, id, desc, opresult, defined);
630
0
}
631
632
633
bool
634
DOMProxyHandler::ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy, unsigned flags, JS::AutoIdVector& props) const
635
0
{
636
0
  bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
637
0
638
0
  uint32_t length = UnwrapProxy(proxy)->Length();
639
0
  MOZ_ASSERT(int32_t(length) >= 0);
640
0
  for (int32_t i = 0; i < int32_t(length); ++i) {
641
0
    if (!props.append(INT_TO_JSID(i))) {
642
0
      return false;
643
0
    }
644
0
  }
645
0
646
0
  if (flags & JSITER_HIDDEN) {
647
0
    nsTArray<nsString> names;
648
0
    UnwrapProxy(proxy)->GetSupportedNames(names);
649
0
    if (!AppendNamedPropertyIds(cx, proxy, names, false, props)) {
650
0
      return false;
651
0
    }
652
0
  }
653
0
654
0
  JS::Rooted<JSObject*> expando(cx);
655
0
  if (!isXray && (expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
656
0
      !js::GetPropertyKeys(cx, expando, flags, &props)) {
657
0
    return false;
658
0
  }
659
0
660
0
  return true;
661
0
}
662
663
bool
664
DOMProxyHandler::hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) const
665
0
{
666
0
  MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
667
0
            "Should not have a XrayWrapper here");
668
0
669
0
  uint32_t index = GetArrayIndexFromId(cx, id);
670
0
  if (IsArrayIndex(index)) {
671
0
    bool found = false;
672
0
    mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
673
0
    auto result(StrongOrRawPtr<mozilla::dom::Element>(self->IndexedGetter(index, found)));
674
0
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
675
0
    (void)result;
676
0
677
0
    *bp = found;
678
0
    return true;
679
0
  }
680
0
681
0
682
0
  JS::Rooted<JSObject*> expando(cx, GetExpandoObject(proxy));
683
0
  if (expando) {
684
0
    bool b = true;
685
0
    bool ok = JS_HasPropertyById(cx, expando, id, &b);
686
0
    *bp = !!b;
687
0
    if (!ok || *bp) {
688
0
      return ok;
689
0
    }
690
0
  }
691
0
692
0
  bool hasOnProto;
693
0
  if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
694
0
    return false;
695
0
  }
696
0
  if (!hasOnProto) {
697
0
    bool found = false;
698
0
    FakeString name;
699
0
    bool isSymbol;
700
0
    if (!ConvertIdToString(cx, id, name, isSymbol)) {
701
0
      return false;
702
0
    }
703
0
    if (!isSymbol) {
704
0
      mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
705
0
      auto result(StrongOrRawPtr<mozilla::dom::Element>(self->NamedGetter(NonNullHelper(Constify(name)), found)));
706
0
      MOZ_ASSERT(!JS_IsExceptionPending(cx));
707
0
      (void)result;
708
0
    }
709
0
710
0
    *bp = found;
711
0
    return true;
712
0
  }
713
0
  *bp = false;
714
0
  return true;
715
0
}
716
717
bool
718
DOMProxyHandler::get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JS::Value> receiver, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const
719
0
{
720
0
  MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
721
0
              "Should not have a XrayWrapper here");
722
0
723
0
  uint32_t index = GetArrayIndexFromId(cx, id);
724
0
  if (IsArrayIndex(index)) {
725
0
    mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
726
0
    bool found = false;
727
0
    auto result(StrongOrRawPtr<mozilla::dom::Element>(self->IndexedGetter(index, found)));
728
0
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
729
0
730
0
    if (found) {
731
0
      if (!result) {
732
0
        vp.setNull();
733
0
        return true;
734
0
      }
735
0
      if (!GetOrCreateDOMReflector(cx, result, vp)) {
736
0
        MOZ_ASSERT(JS_IsExceptionPending(cx));
737
0
        return false;
738
0
      }
739
0
      return true;
740
0
    }
741
0
    // Even if we don't have this index, we don't forward the
742
0
    // get on to our expando object.
743
0
  } else {
744
0
    { // Scope for expando
745
0
      JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
746
0
      if (expando) {
747
0
        bool hasProp;
748
0
        if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
749
0
          return false;
750
0
        }
751
0
752
0
        if (hasProp) {
753
0
          // Forward the get to the expando object, but our receiver is whatever our
754
0
          // receiver is.
755
0
          return JS_ForwardGetPropertyTo(cx, expando, id, receiver, vp);
756
0
        }
757
0
      }
758
0
    }
759
0
  }
760
0
761
0
  bool foundOnPrototype;
762
0
  if (!GetPropertyOnPrototype(cx, proxy, receiver, id, &foundOnPrototype, vp)) {
763
0
    return false;
764
0
  }
765
0
766
0
  if (foundOnPrototype) {
767
0
    return true;
768
0
  }
769
0
770
0
  if (!IsArrayIndex(index)) {
771
0
    FakeString name;
772
0
    bool isSymbol;
773
0
    if (!ConvertIdToString(cx, id, name, isSymbol)) {
774
0
      return false;
775
0
    }
776
0
    if (!isSymbol) {
777
0
      mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
778
0
      bool found = false;
779
0
      auto result(StrongOrRawPtr<mozilla::dom::Element>(self->NamedGetter(NonNullHelper(Constify(name)), found)));
780
0
      MOZ_ASSERT(!JS_IsExceptionPending(cx));
781
0
782
0
      if (found) {
783
0
        if (!result) {
784
0
          vp.setNull();
785
0
          return true;
786
0
        }
787
0
        if (!GetOrCreateDOMReflector(cx, result, vp)) {
788
0
          MOZ_ASSERT(JS_IsExceptionPending(cx));
789
0
          return false;
790
0
        }
791
0
        return true;
792
0
      }
793
0
    }
794
0
  }
795
0
796
0
  vp.setUndefined();
797
0
  return true;
798
0
}
799
800
const char*
801
DOMProxyHandler::className(JSContext* cx, JS::Handle<JSObject*> proxy) const
802
0
{
803
0
  return "HTMLOptionsCollection";
804
0
}
805
806
bool
807
DOMProxyHandler::finalizeInBackground(const JS::Value& priv) const
808
0
{
809
0
  return false;
810
0
}
811
812
void
813
DOMProxyHandler::finalize(JSFreeOp* fop, JSObject* proxy) const
814
0
{
815
0
  mozilla::dom::HTMLOptionsCollection* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::HTMLOptionsCollection>(proxy);
816
0
  if (self) {
817
0
    ClearWrapper(self, self, proxy);
818
0
    AddForDeferredFinalization<mozilla::dom::HTMLOptionsCollection>(self);
819
0
  }
820
0
}
821
822
const DOMProxyHandler*
823
DOMProxyHandler::getInstance()
824
0
{
825
0
  static const DOMProxyHandler instance;
826
0
  return &instance;
827
0
}
828
829
bool
830
DOMProxyHandler::delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::ObjectOpResult& opresult) const
831
0
{
832
0
  MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
833
0
            "Should not have a XrayWrapper here");
834
0
835
0
  uint32_t index = GetArrayIndexFromId(cx, id);
836
0
  if (IsArrayIndex(index)) {
837
0
    bool deleteSucceeded;
838
0
    bool found = false;
839
0
    mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
840
0
    auto result(StrongOrRawPtr<mozilla::dom::Element>(self->IndexedGetter(index, found)));
841
0
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
842
0
    (void)result;
843
0
    deleteSucceeded = !found;
844
0
    return deleteSucceeded ? opresult.succeed() : opresult.failCantDelete();
845
0
  }
846
0
  // Try named delete only if the named property visibility
847
0
  // algorithm says the property is visible.
848
0
  bool tryNamedDelete = true;
849
0
  { // Scope for expando
850
0
    JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
851
0
    if (expando) {
852
0
      bool hasProp;
853
0
      if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
854
0
        return false;
855
0
      }
856
0
      tryNamedDelete = !hasProp;
857
0
    }
858
0
  }
859
0
  if (tryNamedDelete) {
860
0
    bool hasOnProto;
861
0
    if (!HasPropertyOnPrototype(cx, proxy, id, &hasOnProto)) {
862
0
      return false;
863
0
    }
864
0
    tryNamedDelete = !hasOnProto;
865
0
  }
866
0
  if (tryNamedDelete) {
867
0
    bool found = false;
868
0
    bool deleteSucceeded;
869
0
    FakeString name;
870
0
    bool isSymbol;
871
0
    if (!ConvertIdToString(cx, id, name, isSymbol)) {
872
0
      return false;
873
0
    }
874
0
    if (!isSymbol) {
875
0
      mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
876
0
      auto result(StrongOrRawPtr<mozilla::dom::Element>(self->NamedGetter(NonNullHelper(Constify(name)), found)));
877
0
      MOZ_ASSERT(!JS_IsExceptionPending(cx));
878
0
      (void)result;
879
0
    }
880
0
    deleteSucceeded = !found;
881
0
    if (found) {
882
0
      return deleteSucceeded ? opresult.succeed() : opresult.failCantDelete();
883
0
    }
884
0
  }
885
0
886
0
  return dom::DOMProxyHandler::delete_(cx, proxy, id, opresult);
887
0
}
888
889
bool
890
DOMProxyHandler::getElements(JSContext* cx, JS::Handle<JSObject*> proxy, uint32_t begin, uint32_t end, js::ElementAdder* adder) const
891
0
{
892
0
  JS::Rooted<JS::Value> temp(cx);
893
0
  MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
894
0
             "Should not have a XrayWrapper here");
895
0
896
0
  mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
897
0
  uint32_t length = self->Length();
898
0
  // Compute the end of the indices we'll get ourselves
899
0
  uint32_t ourEnd = std::max(begin, std::min(end, length));
900
0
901
0
  for (uint32_t index = begin; index < ourEnd; ++index) {
902
0
    bool found = false;
903
0
    auto result(StrongOrRawPtr<mozilla::dom::Element>(self->IndexedGetter(index, found)));
904
0
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
905
0
906
0
    MOZ_ASSERT(found);
907
0
    if (!result) {
908
0
      temp.setNull();
909
0
      if (!adder->append(cx, temp)) return false;
910
0
      continue;
911
0
    }
912
0
    if (!GetOrCreateDOMReflector(cx, result, &temp)) {
913
0
      MOZ_ASSERT(JS_IsExceptionPending(cx));
914
0
      return false;
915
0
    }
916
0
    if (!adder->append(cx, temp)) return false;
917
0
    continue;
918
0
  }
919
0
920
0
  if (end > ourEnd) {
921
0
    JS::Rooted<JSObject*> proto(cx);
922
0
    if (!js::GetObjectProto(cx, proxy, &proto)) {
923
0
      return false;
924
0
    }
925
0
    return js::GetElementsWithAdder(cx, proto, proxy, ourEnd, end, adder);
926
0
  }
927
0
928
0
  return true;
929
0
}
930
931
bool
932
DOMProxyHandler::setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::Handle<JS::Value> v, bool* done) const
933
0
{
934
0
  MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
935
0
             "Should not have a XrayWrapper here");
936
0
  uint32_t index = GetArrayIndexFromId(cx, id);
937
0
  if (IsArrayIndex(index)) {
938
0
    mozilla::dom::HTMLOptionsCollection* self = UnwrapProxy(proxy);
939
0
    JS::Rooted<JS::Value> rootedValue(cx, v);
940
0
    mozilla::dom::HTMLOptionElement* option;
941
0
    if (v.isObject()) {
942
0
      {
943
0
        nsresult rv = UnwrapObject<prototypes::id::HTMLOptionElement, mozilla::dom::HTMLOptionElement>(&rootedValue, option);
944
0
        if (NS_FAILED(rv)) {
945
0
          ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Value being assigned to HTMLOptionsCollection setter", "HTMLOptionElement");
946
0
          return false;
947
0
        }
948
0
      }
949
0
    } else if (v.isNullOrUndefined()) {
950
0
      option = nullptr;
951
0
    } else {
952
0
      ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Value being assigned to HTMLOptionsCollection setter");
953
0
      return false;
954
0
    }
955
0
    Maybe<AutoCEReaction> ceReaction;
956
0
    if (CustomElementRegistry::IsCustomElementEnabled(cx, proxy)) {
957
0
      DocGroup* docGroup = self->GetDocGroup();
958
0
      if (docGroup) {
959
0
        ceReaction.emplace(docGroup->CustomElementReactionsStack(), cx);
960
0
      }
961
0
    }
962
0
    FastErrorResult rv;
963
0
    self->IndexedSetter(index, MOZ_KnownLive(Constify(option)), rv);
964
0
    if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
965
0
      return false;
966
0
    }
967
0
    MOZ_ASSERT(!JS_IsExceptionPending(cx));
968
0
    *done = true;
969
0
    return true;
970
0
  }
971
0
972
0
  *done = false;
973
0
  return true;
974
0
}
975
976
size_t
977
DOMProxyHandler::objectMoved(JSObject* obj, JSObject* old) const
978
0
{
979
0
  mozilla::dom::HTMLOptionsCollection* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::HTMLOptionsCollection>(obj);
980
0
  if (self) {
981
0
    UpdateWrapper(self, self, obj, old);
982
0
  }
983
0
984
0
  return 0;
985
0
}
986
987
static const DOMJSClass sClass = {
988
  PROXY_CLASS_DEF("HTMLOptionsCollection",
989
                  JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1)),
990
  { prototypes::id::HTMLCollection, prototypes::id::HTMLOptionsCollection, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
991
  IsBaseOf<nsISupports, mozilla::dom::HTMLOptionsCollection >::value,
992
  sNativePropertyHooks,
993
  FindAssociatedGlobalForNative<mozilla::dom::HTMLOptionsCollection>::Get,
994
  GetProtoObjectHandle,
995
  GetCCParticipant<mozilla::dom::HTMLOptionsCollection>::Get()
996
};
997
998
bool
999
Wrap(JSContext* aCx, mozilla::dom::HTMLOptionsCollection* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1000
0
{
1001
0
  static_assert(!IsBaseOf<NonRefcountedDOMObject, mozilla::dom::HTMLOptionsCollection>::value,
1002
0
                "Shouldn't have wrappercached things that are not refcounted.");
1003
0
  MOZ_ASSERT(static_cast<mozilla::dom::HTMLOptionsCollection*>(aObject) ==
1004
0
             reinterpret_cast<mozilla::dom::HTMLOptionsCollection*>(aObject),
1005
0
             "Multiple inheritance for mozilla::dom::HTMLOptionsCollection is broken.");
1006
0
  MOZ_ASSERT(static_cast<nsIHTMLCollection*>(aObject) ==
1007
0
             reinterpret_cast<nsIHTMLCollection*>(aObject),
1008
0
             "Multiple inheritance for nsIHTMLCollection is broken.");
1009
0
  MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1010
0
  MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1011
0
  MOZ_ASSERT(!aCache->GetWrapper(),
1012
0
             "You should probably not be using Wrap() directly; use "
1013
0
             "GetOrCreateDOMReflector instead");
1014
0
1015
0
  MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
1016
0
             "nsISupports must be on our primary inheritance chain");
1017
0
1018
0
  JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
1019
0
  if (!global) {
1020
0
    return false;
1021
0
  }
1022
0
  MOZ_ASSERT(JS_IsGlobalObject(global));
1023
0
  MOZ_ASSERT(JS::ObjectIsNotGray(global));
1024
0
1025
0
  // That might have ended up wrapping us already, due to the wonders
1026
0
  // of XBL.  Check for that, and bail out as needed.
1027
0
  aReflector.set(aCache->GetWrapper());
1028
0
  if (aReflector) {
1029
#ifdef DEBUG
1030
    AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
1031
#endif // DEBUG
1032
    return true;
1033
0
  }
1034
0
1035
0
  JSAutoRealm ar(aCx, global);
1036
0
  JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1037
0
  if (!canonicalProto) {
1038
0
    return false;
1039
0
  }
1040
0
  JS::Rooted<JSObject*> proto(aCx);
1041
0
  if (aGivenProto) {
1042
0
    proto = aGivenProto;
1043
0
    // Unfortunately, while aGivenProto was in the compartment of aCx
1044
0
    // coming in, we changed compartments to that of "parent" so may need
1045
0
    // to wrap the proto here.
1046
0
    if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1047
0
      if (!JS_WrapObject(aCx, &proto)) {
1048
0
        return false;
1049
0
      }
1050
0
    }
1051
0
  } else {
1052
0
    proto = canonicalProto;
1053
0
  }
1054
0
1055
0
  BindingJSObjectCreator<mozilla::dom::HTMLOptionsCollection> creator(aCx);
1056
0
  creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
1057
0
                            proto, aObject, JS::UndefinedHandleValue, aReflector);
1058
0
  if (!aReflector) {
1059
0
    return false;
1060
0
  }
1061
0
1062
0
  aCache->SetWrapper(aReflector);
1063
0
  creator.InitializationSucceeded();
1064
0
1065
0
  MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
1066
0
             aCache->GetWrapperPreserveColor() == aReflector);
1067
0
  // If proto != canonicalProto, we have to preserve our wrapper;
1068
0
  // otherwise we won't be able to properly recreate it later, since
1069
0
  // we won't know what proto to use.  Note that we don't check
1070
0
  // aGivenProto here, since it's entirely possible (and even
1071
0
  // somewhat common) to have a non-null aGivenProto which is the
1072
0
  // same as canonicalProto.
1073
0
  if (proto != canonicalProto) {
1074
0
    PreserveWrapper(aObject);
1075
0
  }
1076
0
1077
0
  return true;
1078
0
}
1079
1080
static bool
1081
ResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<JS::PropertyDescriptor> desc)
1082
0
{
1083
0
  return js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, wrapper, id, desc);
1084
0
}
1085
1086
static bool
1087
EnumerateOwnProperties(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> obj, JS::AutoIdVector& props)
1088
0
{
1089
0
  return js::GetProxyHandler(obj)->ownPropertyKeys(cx, wrapper, props);
1090
0
}
1091
1092
const NativePropertyHooks sNativePropertyHooks[] = { {
1093
  ResolveOwnProperty,
1094
  EnumerateOwnProperties,
1095
  nullptr,
1096
  { sNativeProperties.Upcast(), nullptr },
1097
  prototypes::id::HTMLOptionsCollection,
1098
  constructors::id::HTMLOptionsCollection,
1099
  HTMLCollection_Binding::sNativePropertyHooks,
1100
  &DefaultXrayExpandoObjectClass
1101
} };
1102
1103
void
1104
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
1105
0
{
1106
0
  JS::Handle<JSObject*> parentProto(HTMLCollection_Binding::GetProtoObjectHandle(aCx));
1107
0
  if (!parentProto) {
1108
0
    return;
1109
0
  }
1110
0
1111
0
  JS::Handle<JSObject*> constructorProto(HTMLCollection_Binding::GetConstructorObjectHandle(aCx));
1112
0
  if (!constructorProto) {
1113
0
    return;
1114
0
  }
1115
0
1116
0
  static bool sIdsInited = false;
1117
0
  if (!sIdsInited && NS_IsMainThread()) {
1118
0
    if (!InitIds(aCx, sNativeProperties.Upcast())) {
1119
0
      return;
1120
0
    }
1121
0
    sIdsInited = true;
1122
0
  }
1123
0
1124
0
  JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::HTMLOptionsCollection);
1125
0
  JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::HTMLOptionsCollection);
1126
0
  dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
1127
0
                              &sPrototypeClass.mBase, protoCache,
1128
0
                              nullptr,
1129
0
                              constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
1130
0
                              interfaceCache,
1131
0
                              sNativeProperties.Upcast(),
1132
0
                              nullptr,
1133
0
                              "HTMLOptionsCollection", aDefineOnGlobal,
1134
0
                              nullptr,
1135
0
                              false);
1136
0
}
1137
1138
JSObject*
1139
GetConstructorObject(JSContext* aCx)
1140
0
{
1141
0
  return GetConstructorObjectHandle(aCx);
1142
0
}
1143
1144
} // namespace HTMLOptionsCollection_Binding
1145
1146
1147
1148
} // namespace dom
1149
} // namespace mozilla