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