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