Coverage Report

Created: 2018-09-25 14:53

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