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