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