Line data Source code
1 : /* THIS FILE IS AUTOGENERATED FROM TestInterfaceJSMaplikeSetlikeIterable.webidl BY Codegen.py - DO NOT EDIT */
2 :
3 : #include "AtomList.h"
4 : #include "TestInterfaceJSMaplikeSetlikeIterableBinding.h"
5 : #include "WrapperFactory.h"
6 : #include "XrayWrapper.h"
7 : #include "mozilla/OwningNonNull.h"
8 : #include "mozilla/Preferences.h"
9 : #include "mozilla/dom/BindingUtils.h"
10 : #include "mozilla/dom/DOMJSClass.h"
11 : #include "mozilla/dom/DOMJSProxyHandler.h"
12 : #include "mozilla/dom/IterableIterator.h"
13 : #include "mozilla/dom/NonRefcountedDOMObject.h"
14 : #include "mozilla/dom/PrimitiveConversions.h"
15 : #include "mozilla/dom/TestInterfaceIterableDouble.h"
16 : #include "mozilla/dom/TestInterfaceIterableDoubleUnion.h"
17 : #include "mozilla/dom/TestInterfaceIterableSingle.h"
18 : #include "mozilla/dom/TestInterfaceMaplike.h"
19 : #include "mozilla/dom/TestInterfaceMaplikeObject.h"
20 : #include "mozilla/dom/TestInterfaceSetlike.h"
21 : #include "mozilla/dom/TestInterfaceSetlikeNode.h"
22 : #include "mozilla/dom/ToJSValue.h"
23 : #include "mozilla/dom/UnionConversions.h"
24 : #include "mozilla/dom/XrayExpandoClass.h"
25 : #include "nsContentUtils.h"
26 : #include "nsIGlobalObject.h"
27 : #include "nsINode.h"
28 :
29 : namespace mozilla {
30 : namespace dom {
31 :
32 : bool
33 0 : StringOrLong::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
34 : {
35 0 : switch (mType) {
36 : case eUninitialized: {
37 0 : return false;
38 : break;
39 : }
40 : case eString: {
41 0 : if (!xpc::NonVoidStringToJsval(cx, mValue.mString.Value(), rval)) {
42 0 : return false;
43 : }
44 0 : return true;
45 : break;
46 : }
47 : case eLong: {
48 0 : rval.setInt32(int32_t(mValue.mLong.Value()));
49 0 : return true;
50 : break;
51 : }
52 : default: {
53 0 : return false;
54 : break;
55 : }
56 : }
57 :
58 : return false;
59 : }
60 :
61 :
62 : nsString&
63 0 : OwningStringOrLong::RawSetAsString()
64 : {
65 0 : if (mType == eString) {
66 0 : return mValue.mString.Value();
67 : }
68 0 : MOZ_ASSERT(mType == eUninitialized);
69 0 : mType = eString;
70 0 : return mValue.mString.SetValue();
71 : }
72 :
73 : nsString&
74 0 : OwningStringOrLong::SetAsString()
75 : {
76 0 : if (mType == eString) {
77 0 : return mValue.mString.Value();
78 : }
79 0 : Uninit();
80 0 : mType = eString;
81 0 : return mValue.mString.SetValue();
82 : }
83 :
84 : bool
85 0 : OwningStringOrLong::TrySetToString(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
86 : {
87 0 : tryNext = false;
88 : { // scope for memberSlot
89 0 : nsString& memberSlot = RawSetAsString();
90 0 : if (!ConvertJSValueToString(cx, value, eStringify, eStringify, memberSlot)) {
91 0 : return false;
92 : }
93 : }
94 0 : return true;
95 : }
96 :
97 :
98 : void
99 0 : OwningStringOrLong::DestroyString()
100 : {
101 0 : MOZ_ASSERT(IsString(), "Wrong type!");
102 0 : mValue.mString.Destroy();
103 0 : mType = eUninitialized;
104 0 : }
105 :
106 :
107 :
108 :
109 : int32_t&
110 0 : OwningStringOrLong::RawSetAsLong()
111 : {
112 0 : if (mType == eLong) {
113 0 : return mValue.mLong.Value();
114 : }
115 0 : MOZ_ASSERT(mType == eUninitialized);
116 0 : mType = eLong;
117 0 : return mValue.mLong.SetValue();
118 : }
119 :
120 : int32_t&
121 0 : OwningStringOrLong::SetAsLong()
122 : {
123 0 : if (mType == eLong) {
124 0 : return mValue.mLong.Value();
125 : }
126 0 : Uninit();
127 0 : mType = eLong;
128 0 : return mValue.mLong.SetValue();
129 : }
130 :
131 : bool
132 0 : OwningStringOrLong::TrySetToLong(JSContext* cx, JS::Handle<JS::Value> value, bool& tryNext, bool passedToJSImpl)
133 : {
134 0 : tryNext = false;
135 : { // scope for memberSlot
136 0 : int32_t& memberSlot = RawSetAsLong();
137 0 : if (!ValueToPrimitive<int32_t, eDefault>(cx, value, &memberSlot)) {
138 0 : return false;
139 : }
140 : }
141 0 : return true;
142 : }
143 :
144 : void
145 0 : OwningStringOrLong::DestroyLong()
146 : {
147 0 : MOZ_ASSERT(IsLong(), "Wrong type!");
148 0 : mValue.mLong.Destroy();
149 0 : mType = eUninitialized;
150 0 : }
151 :
152 :
153 :
154 :
155 : void
156 0 : OwningStringOrLong::Uninit()
157 : {
158 0 : switch (mType) {
159 : case eUninitialized: {
160 0 : break;
161 : }
162 : case eString: {
163 0 : DestroyString();
164 0 : break;
165 : }
166 : case eLong: {
167 0 : DestroyLong();
168 0 : break;
169 : }
170 : }
171 0 : }
172 :
173 : bool
174 0 : OwningStringOrLong::ToJSVal(JSContext* cx, JS::Handle<JSObject*> scopeObj, JS::MutableHandle<JS::Value> rval) const
175 : {
176 0 : switch (mType) {
177 : case eUninitialized: {
178 0 : return false;
179 : break;
180 : }
181 : case eString: {
182 0 : if (!xpc::NonVoidStringToJsval(cx, mValue.mString.Value(), rval)) {
183 0 : return false;
184 : }
185 0 : return true;
186 : break;
187 : }
188 : case eLong: {
189 0 : rval.setInt32(int32_t(mValue.mLong.Value()));
190 0 : return true;
191 : break;
192 : }
193 : default: {
194 0 : return false;
195 : break;
196 : }
197 : }
198 :
199 : return false;
200 : }
201 :
202 : void
203 0 : OwningStringOrLong::TraceUnion(JSTracer* trc)
204 : {
205 0 : }
206 :
207 : OwningStringOrLong&
208 0 : OwningStringOrLong::operator=(const OwningStringOrLong& aOther)
209 : {
210 0 : switch (aOther.mType) {
211 : case eUninitialized: {
212 0 : MOZ_ASSERT(mType == eUninitialized,
213 : "We need to destroy ourselves?");
214 0 : break;
215 : }
216 : case eString: {
217 0 : SetAsString() = aOther.GetAsString();
218 0 : break;
219 : }
220 : case eLong: {
221 0 : SetAsLong() = aOther.GetAsLong();
222 0 : break;
223 : }
224 : }
225 0 : return *this;
226 : }
227 :
228 :
229 : namespace TestInterfaceIterableDoubleBinding {
230 :
231 : static bool
232 0 : entries(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceIterableDouble* self, const JSJitMethodCallArgs& args)
233 : {
234 : typedef mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble> itrType;
235 : RefPtr<itrType> result(new itrType(self,
236 : itrType::IterableIteratorType::Entries,
237 0 : &TestInterfaceIterableDoubleIteratorBinding::Wrap));
238 : static_assert(!IsPointer<decltype(result)>::value,
239 : "NewObject implies that we need to keep the object alive with a strong reference.");
240 0 : if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
241 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
242 0 : return false;
243 : }
244 0 : return true;
245 : }
246 :
247 : static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
248 : static const JSTypedMethodJitInfo entries_methodinfo = {
249 : {
250 : { (JSJitGetterOp)entries },
251 : { prototypes::id::TestInterfaceIterableDouble },
252 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::Depth },
253 : JSJitInfo::Method,
254 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
255 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
256 : false, /* isInfallible. False in setters. */
257 : false, /* isMovable. Not relevant for setters. */
258 : false, /* isEliminatable. Not relevant for setters. */
259 : false, /* isAlwaysInSlot. Only relevant for getters. */
260 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
261 : true, /* isTypedMethod. Only relevant for methods. */
262 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
263 : },
264 : entries_methodinfo_argTypes
265 : };
266 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
267 : static_assert(0 < 1, "There is no slot for us");
268 :
269 : static bool
270 0 : keys(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceIterableDouble* self, const JSJitMethodCallArgs& args)
271 : {
272 : typedef mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble> itrType;
273 : RefPtr<itrType> result(new itrType(self,
274 : itrType::IterableIteratorType::Keys,
275 0 : &TestInterfaceIterableDoubleIteratorBinding::Wrap));
276 : static_assert(!IsPointer<decltype(result)>::value,
277 : "NewObject implies that we need to keep the object alive with a strong reference.");
278 0 : if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
279 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
280 0 : return false;
281 : }
282 0 : return true;
283 : }
284 :
285 : static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
286 : static const JSTypedMethodJitInfo keys_methodinfo = {
287 : {
288 : { (JSJitGetterOp)keys },
289 : { prototypes::id::TestInterfaceIterableDouble },
290 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::Depth },
291 : JSJitInfo::Method,
292 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
293 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
294 : false, /* isInfallible. False in setters. */
295 : false, /* isMovable. Not relevant for setters. */
296 : false, /* isEliminatable. Not relevant for setters. */
297 : false, /* isAlwaysInSlot. Only relevant for getters. */
298 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
299 : true, /* isTypedMethod. Only relevant for methods. */
300 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
301 : },
302 : keys_methodinfo_argTypes
303 : };
304 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
305 : static_assert(0 < 1, "There is no slot for us");
306 :
307 : static bool
308 0 : values(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceIterableDouble* self, const JSJitMethodCallArgs& args)
309 : {
310 : typedef mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble> itrType;
311 : RefPtr<itrType> result(new itrType(self,
312 : itrType::IterableIteratorType::Values,
313 0 : &TestInterfaceIterableDoubleIteratorBinding::Wrap));
314 : static_assert(!IsPointer<decltype(result)>::value,
315 : "NewObject implies that we need to keep the object alive with a strong reference.");
316 0 : if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
317 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
318 0 : return false;
319 : }
320 0 : return true;
321 : }
322 :
323 : static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
324 : static const JSTypedMethodJitInfo values_methodinfo = {
325 : {
326 : { (JSJitGetterOp)values },
327 : { prototypes::id::TestInterfaceIterableDouble },
328 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::Depth },
329 : JSJitInfo::Method,
330 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
331 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
332 : false, /* isInfallible. False in setters. */
333 : false, /* isMovable. Not relevant for setters. */
334 : false, /* isEliminatable. Not relevant for setters. */
335 : false, /* isAlwaysInSlot. Only relevant for getters. */
336 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
337 : true, /* isTypedMethod. Only relevant for methods. */
338 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
339 : },
340 : values_methodinfo_argTypes
341 : };
342 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
343 : static_assert(0 < 1, "There is no slot for us");
344 :
345 : static bool
346 0 : forEach(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceIterableDouble* self, const JSJitMethodCallArgs& args)
347 : {
348 0 : JS::Rooted<JSObject*> arg0(cx);
349 0 : if (args.get(0).isObject()) {
350 0 : arg0 = &args.get(0).toObject();
351 : } else {
352 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceIterableDouble.forEach");
353 0 : return false;
354 : }
355 0 : JS::Rooted<JS::Value> arg1(cx);
356 0 : if (args.hasDefined(1)) {
357 0 : arg1 = args.get(1);
358 : } else {
359 0 : arg1 = JS::UndefinedValue();
360 : }
361 0 : if (!JS::IsCallable(arg0)) {
362 0 : ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 1 of TestInterfaceIterableDouble.forEach");
363 0 : return false;
364 : }
365 0 : JS::AutoValueArray<3> callArgs(cx);
366 0 : callArgs[2].setObject(*obj);
367 0 : JS::Rooted<JS::Value> ignoredReturnVal(cx);
368 0 : for (size_t i = 0; i < self->GetIterableLength(); ++i) {
369 0 : if (!ToJSValue(cx, self->GetValueAtIndex(i), callArgs[0])) {
370 0 : return false;
371 : }
372 0 : if (!ToJSValue(cx, self->GetKeyAtIndex(i), callArgs[1])) {
373 0 : return false;
374 : }
375 0 : if (!JS::Call(cx, arg1, arg0, JS::HandleValueArray(callArgs),
376 : &ignoredReturnVal)) {
377 0 : return false;
378 : }
379 : }
380 0 : args.rval().setUndefined();
381 0 : return true;
382 : }
383 :
384 : static const JSJitInfo forEach_methodinfo = {
385 : { (JSJitGetterOp)forEach },
386 : { prototypes::id::TestInterfaceIterableDouble },
387 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::Depth },
388 : JSJitInfo::Method,
389 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
390 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
391 : false, /* isInfallible. False in setters. */
392 : false, /* isMovable. Not relevant for setters. */
393 : false, /* isEliminatable. Not relevant for setters. */
394 : false, /* isAlwaysInSlot. Only relevant for getters. */
395 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
396 : false, /* isTypedMethod. Only relevant for methods. */
397 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
398 : };
399 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
400 : static_assert(0 < 1, "There is no slot for us");
401 :
402 : static bool
403 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
404 : {
405 0 : mozilla::dom::TestInterfaceIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDouble>(obj);
406 : // We don't want to preserve if we don't have a wrapper, and we
407 : // obviously can't preserve if we're not initialized.
408 0 : if (self && self->GetWrapperPreserveColor()) {
409 0 : PreserveWrapper(self);
410 : }
411 0 : return true;
412 : }
413 :
414 : static void
415 0 : _finalize(js::FreeOp* fop, JSObject* obj)
416 : {
417 0 : mozilla::dom::TestInterfaceIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDouble>(obj);
418 0 : if (self) {
419 0 : ClearWrapper(self, self, obj);
420 0 : AddForDeferredFinalization<mozilla::dom::TestInterfaceIterableDouble>(self);
421 : }
422 0 : }
423 :
424 : static void
425 0 : _objectMoved(JSObject* obj, const JSObject* old)
426 : {
427 0 : mozilla::dom::TestInterfaceIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDouble>(obj);
428 0 : if (self) {
429 0 : UpdateWrapper(self, self, obj, old);
430 : }
431 0 : }
432 :
433 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
434 : #if defined(__clang__)
435 : #pragma clang diagnostic push
436 : #pragma clang diagnostic ignored "-Wmissing-braces"
437 : #endif
438 : static const JSFunctionSpec sMethods_specs[] = {
439 : JS_FNSPEC("entries", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
440 : JS_FNSPEC("keys", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
441 : JS_FNSPEC("values", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
442 : JS_FNSPEC("forEach", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
443 : JS_FS_END
444 : };
445 : #if defined(__clang__)
446 : #pragma clang diagnostic pop
447 : #endif
448 :
449 :
450 : // Can't be const because the pref-enabled boolean needs to be writable
451 : static Prefable<const JSFunctionSpec> sMethods[] = {
452 : { nullptr, &sMethods_specs[0] },
453 : { nullptr, nullptr }
454 : };
455 :
456 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
457 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
458 : static_assert(4 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
459 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
460 :
461 :
462 : static uint16_t sNativeProperties_sortedPropertyIndices[4];
463 : static PropertyInfo sNativeProperties_propertyInfos[4];
464 :
465 : static const NativePropertiesN<1> sNativeProperties = {
466 : false, 0,
467 : false, 0,
468 : true, 0 /* sMethods */,
469 : false, 0,
470 : false, 0,
471 : false, 0,
472 : false, 0,
473 : 0,
474 : 4,
475 : sNativeProperties_sortedPropertyIndices,
476 : {
477 : { sMethods, &sNativeProperties_propertyInfos[0] }
478 : }
479 : };
480 : static_assert(4 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
481 : "We have a property info count that is oversized");
482 :
483 : static bool
484 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
485 : {
486 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
487 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
488 0 : if (!args.isConstructing()) {
489 : // XXXbz wish I could get the name from the callee instead of
490 : // Adding more relocations
491 0 : return ThrowConstructorWithoutNew(cx, "TestInterfaceIterableDouble");
492 : }
493 :
494 0 : GlobalObject global(cx, obj);
495 0 : if (global.Failed()) {
496 0 : return false;
497 : }
498 :
499 0 : JS::Rooted<JSObject*> desiredProto(cx);
500 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
501 0 : return false;
502 : }
503 :
504 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
505 0 : Maybe<JSAutoCompartment> ac;
506 0 : if (objIsXray) {
507 0 : obj = js::CheckedUnwrap(obj);
508 0 : if (!obj) {
509 0 : return false;
510 : }
511 0 : ac.emplace(cx, obj);
512 0 : if (!JS_WrapObject(cx, &desiredProto)) {
513 0 : return false;
514 : }
515 : }
516 0 : binding_detail::FastErrorResult rv;
517 0 : auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceIterableDouble>(mozilla::dom::TestInterfaceIterableDouble::Constructor(global, rv)));
518 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
519 0 : return false;
520 : }
521 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
522 : static_assert(!IsPointer<decltype(result)>::value,
523 : "NewObject implies that we need to keep the object alive with a strong reference.");
524 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
525 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
526 0 : return false;
527 : }
528 0 : return true;
529 : }
530 :
531 : static const js::ClassOps sInterfaceObjectClassOps = {
532 : nullptr, /* addProperty */
533 : nullptr, /* delProperty */
534 : nullptr, /* getProperty */
535 : nullptr, /* setProperty */
536 : nullptr, /* enumerate */
537 : nullptr, /* newEnumerate */
538 : nullptr, /* resolve */
539 : nullptr, /* mayResolve */
540 : nullptr, /* finalize */
541 : _constructor, /* call */
542 : nullptr, /* hasInstance */
543 : _constructor, /* construct */
544 : nullptr, /* trace */
545 : };
546 :
547 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
548 : {
549 : "Function",
550 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
551 : &sInterfaceObjectClassOps,
552 : JS_NULL_CLASS_SPEC,
553 : JS_NULL_CLASS_EXT,
554 : &sInterfaceObjectClassObjectOps
555 : },
556 : eInterface,
557 : true,
558 : prototypes::id::TestInterfaceIterableDouble,
559 : PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::Depth,
560 : sNativePropertyHooks,
561 : "function TestInterfaceIterableDouble() {\n [native code]\n}",
562 : JS::GetRealmFunctionPrototype
563 : };
564 :
565 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
566 : {
567 : "TestInterfaceIterableDoublePrototype",
568 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
569 : JS_NULL_CLASS_OPS,
570 : JS_NULL_CLASS_SPEC,
571 : JS_NULL_CLASS_EXT,
572 : JS_NULL_OBJECT_OPS
573 : },
574 : eInterfacePrototype,
575 : false,
576 : prototypes::id::TestInterfaceIterableDouble,
577 : PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::Depth,
578 : sNativePropertyHooks,
579 : "[object TestInterfaceIterableDoublePrototype]",
580 : JS::GetRealmObjectPrototype
581 : };
582 :
583 : bool
584 0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
585 : {
586 : static bool sPrefValue;
587 : static bool sPrefCacheSetUp = false;
588 0 : if (!sPrefCacheSetUp) {
589 0 : sPrefCacheSetUp = true;
590 0 : Preferences::AddBoolVarCache(&sPrefValue, "dom.expose_test_interfaces");
591 : }
592 :
593 0 : return sPrefValue;
594 : }
595 :
596 : JSObject*
597 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
598 : {
599 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
600 : }
601 :
602 : static const js::ClassOps sClassOps = {
603 : _addProperty, /* addProperty */
604 : nullptr, /* delProperty */
605 : nullptr, /* getProperty */
606 : nullptr, /* setProperty */
607 : nullptr, /* enumerate */
608 : nullptr, /* newEnumerate */
609 : nullptr, /* resolve */
610 : nullptr, /* mayResolve */
611 : _finalize, /* finalize */
612 : nullptr, /* call */
613 : nullptr, /* hasInstance */
614 : nullptr, /* construct */
615 : nullptr, /* trace */
616 : };
617 :
618 : static const js::ClassExtension sClassExtension = {
619 : nullptr, /* weakmapKeyDelegateOp */
620 : _objectMoved /* objectMovedOp */
621 : };
622 :
623 : static const DOMJSClass sClass = {
624 : { "TestInterfaceIterableDouble",
625 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
626 : &sClassOps,
627 : JS_NULL_CLASS_SPEC,
628 : &sClassExtension,
629 : JS_NULL_OBJECT_OPS
630 : },
631 : { prototypes::id::TestInterfaceIterableDouble, 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 },
632 : IsBaseOf<nsISupports, mozilla::dom::TestInterfaceIterableDouble >::value,
633 : sNativePropertyHooks,
634 : FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceIterableDouble>::Get,
635 : GetProtoObjectHandle,
636 : GetCCParticipant<mozilla::dom::TestInterfaceIterableDouble>::Get()
637 : };
638 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
639 : "Must have the right minimal number of reserved slots.");
640 : static_assert(1 >= 1,
641 : "Must have enough reserved slots.");
642 :
643 : const JSClass*
644 0 : GetJSClass()
645 : {
646 0 : return sClass.ToJSClass();
647 : }
648 :
649 : bool
650 0 : Wrap(JSContext* aCx, mozilla::dom::TestInterfaceIterableDouble* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
651 : {
652 : MOZ_ASSERT(static_cast<mozilla::dom::TestInterfaceIterableDouble*>(aObject) ==
653 : reinterpret_cast<mozilla::dom::TestInterfaceIterableDouble*>(aObject),
654 : "Multiple inheritance for mozilla::dom::TestInterfaceIterableDouble is broken.");
655 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
656 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
657 0 : MOZ_ASSERT(!aCache->GetWrapper(),
658 : "You should probably not be using Wrap() directly; use "
659 : "GetOrCreateDOMReflector instead");
660 :
661 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
662 : "nsISupports must be on our primary inheritance chain");
663 :
664 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
665 0 : if (!global) {
666 0 : return false;
667 : }
668 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
669 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
670 :
671 : // That might have ended up wrapping us already, due to the wonders
672 : // of XBL. Check for that, and bail out as needed.
673 0 : aReflector.set(aCache->GetWrapper());
674 0 : if (aReflector) {
675 : #ifdef DEBUG
676 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
677 : #endif // DEBUG
678 0 : return true;
679 : }
680 :
681 0 : JSAutoCompartment ac(aCx, global);
682 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
683 0 : if (!canonicalProto) {
684 0 : return false;
685 : }
686 0 : JS::Rooted<JSObject*> proto(aCx);
687 0 : if (aGivenProto) {
688 0 : proto = aGivenProto;
689 : // Unfortunately, while aGivenProto was in the compartment of aCx
690 : // coming in, we changed compartments to that of "parent" so may need
691 : // to wrap the proto here.
692 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
693 0 : if (!JS_WrapObject(aCx, &proto)) {
694 0 : return false;
695 : }
696 : }
697 : } else {
698 0 : proto = canonicalProto;
699 : }
700 :
701 0 : BindingJSObjectCreator<mozilla::dom::TestInterfaceIterableDouble> creator(aCx);
702 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
703 0 : if (!aReflector) {
704 0 : return false;
705 : }
706 :
707 0 : aCache->SetWrapper(aReflector);
708 0 : creator.InitializationSucceeded();
709 :
710 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
711 : aCache->GetWrapperPreserveColor() == aReflector);
712 : // If proto != canonicalProto, we have to preserve our wrapper;
713 : // otherwise we won't be able to properly recreate it later, since
714 : // we won't know what proto to use. Note that we don't check
715 : // aGivenProto here, since it's entirely possible (and even
716 : // somewhat common) to have a non-null aGivenProto which is the
717 : // same as canonicalProto.
718 0 : if (proto != canonicalProto) {
719 0 : PreserveWrapper(aObject);
720 : }
721 :
722 0 : return true;
723 : }
724 :
725 : const NativePropertyHooks sNativePropertyHooks[] = { {
726 : nullptr,
727 : nullptr,
728 : nullptr,
729 : { sNativeProperties.Upcast(), nullptr },
730 : prototypes::id::TestInterfaceIterableDouble,
731 : constructors::id::TestInterfaceIterableDouble,
732 : nullptr,
733 : &DefaultXrayExpandoObjectClass
734 : } };
735 :
736 : void
737 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
738 : {
739 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
740 0 : if (!parentProto) {
741 0 : return;
742 : }
743 :
744 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
745 0 : if (!constructorProto) {
746 0 : return;
747 : }
748 :
749 : static bool sIdsInited = false;
750 0 : if (!sIdsInited && NS_IsMainThread()) {
751 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
752 0 : return;
753 : }
754 0 : sIdsInited = true;
755 : }
756 :
757 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableDouble);
758 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceIterableDouble);
759 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
760 : &sPrototypeClass.mBase, protoCache,
761 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
762 : interfaceCache,
763 : sNativeProperties.Upcast(),
764 : nullptr,
765 : "TestInterfaceIterableDouble", aDefineOnGlobal,
766 : nullptr,
767 0 : false);
768 :
769 : // Set up aliases on the interface prototype object we just created.
770 0 : JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
771 0 : if (!proto) {
772 0 : *protoCache = nullptr;
773 0 : if (interfaceCache) {
774 0 : *interfaceCache = nullptr;
775 : }
776 0 : return;
777 : }
778 :
779 0 : JS::Rooted<JS::Value> aliasedVal(aCx);
780 :
781 0 : if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
782 0 : *protoCache = nullptr;
783 0 : if (interfaceCache) {
784 0 : *interfaceCache = nullptr;
785 : }
786 0 : return;
787 : }
788 0 : JS::Rooted<jsid> iteratorId(aCx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::iterator)));
789 0 : if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
790 0 : *protoCache = nullptr;
791 0 : if (interfaceCache) {
792 0 : *interfaceCache = nullptr;
793 : }
794 0 : return;
795 : }
796 : }
797 :
798 : JS::Handle<JSObject*>
799 0 : GetProtoObjectHandle(JSContext* aCx)
800 : {
801 : /* Get the interface prototype object for this class. This will create the
802 : object as needed. */
803 0 : bool aDefineOnGlobal = true;
804 :
805 : /* Make sure our global is sane. Hopefully we can remove this sometime */
806 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
807 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
808 0 : return nullptr;
809 : }
810 :
811 : /* Check to see whether the interface objects are already installed */
812 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
813 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceIterableDouble)) {
814 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
815 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
816 : }
817 :
818 : /*
819 : * The object might _still_ be null, but that's OK.
820 : *
821 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
822 : * traced by TraceProtoAndIfaceCache() and its contents are never
823 : * changed after they have been set.
824 : *
825 : * Calling address() avoids the read read barrier that does gray
826 : * unmarking, but it's not possible for the object to be gray here.
827 : */
828 :
829 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceIterableDouble);
830 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
831 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
832 : }
833 :
834 : JS::Handle<JSObject*>
835 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
836 : {
837 : /* Get the interface object for this class. This will create the object as
838 : needed. */
839 :
840 : /* Make sure our global is sane. Hopefully we can remove this sometime */
841 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
842 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
843 0 : return nullptr;
844 : }
845 :
846 : /* Check to see whether the interface objects are already installed */
847 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
848 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::TestInterfaceIterableDouble)) {
849 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
850 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
851 : }
852 :
853 : /*
854 : * The object might _still_ be null, but that's OK.
855 : *
856 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
857 : * traced by TraceProtoAndIfaceCache() and its contents are never
858 : * changed after they have been set.
859 : *
860 : * Calling address() avoids the read read barrier that does gray
861 : * unmarking, but it's not possible for the object to be gray here.
862 : */
863 :
864 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::TestInterfaceIterableDouble);
865 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
866 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
867 : }
868 :
869 : JSObject*
870 0 : GetConstructorObject(JSContext* aCx)
871 : {
872 0 : return GetConstructorObjectHandle(aCx);
873 : }
874 :
875 : } // namespace TestInterfaceIterableDoubleBinding
876 :
877 :
878 :
879 : namespace TestInterfaceIterableDoubleIteratorBinding {
880 :
881 : static bool
882 0 : next(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>* self, const JSJitMethodCallArgs& args)
883 : {
884 0 : binding_detail::FastErrorResult rv;
885 0 : JS::Rooted<JSObject*> result(cx);
886 0 : self->Next(cx, &result, rv);
887 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
888 0 : return false;
889 : }
890 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
891 0 : JS::ExposeObjectToActiveJS(result);
892 0 : args.rval().setObject(*result);
893 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
894 0 : return false;
895 : }
896 0 : return true;
897 : }
898 :
899 : static const JSJitInfo next_methodinfo = {
900 : { (JSJitGetterOp)next },
901 : { prototypes::id::TestInterfaceIterableDoubleIterator },
902 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleIterator>::Depth },
903 : JSJitInfo::Method,
904 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
905 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
906 : false, /* isInfallible. False in setters. */
907 : false, /* isMovable. Not relevant for setters. */
908 : false, /* isEliminatable. Not relevant for setters. */
909 : false, /* isAlwaysInSlot. Only relevant for getters. */
910 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
911 : false, /* isTypedMethod. Only relevant for methods. */
912 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
913 : };
914 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
915 : static_assert(0 < 1, "There is no slot for us");
916 :
917 : static void
918 0 : _finalize(js::FreeOp* fop, JSObject* obj)
919 : {
920 0 : mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>>(obj);
921 0 : if (self) {
922 0 : AddForDeferredFinalization<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>>(self);
923 : }
924 0 : }
925 :
926 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
927 : #if defined(__clang__)
928 : #pragma clang diagnostic push
929 : #pragma clang diagnostic ignored "-Wmissing-braces"
930 : #endif
931 : static const JSFunctionSpec sMethods_specs[] = {
932 : JS_FNSPEC("next", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&next_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
933 : JS_FS_END
934 : };
935 : #if defined(__clang__)
936 : #pragma clang diagnostic pop
937 : #endif
938 :
939 :
940 : // Can't be const because the pref-enabled boolean needs to be writable
941 : static Prefable<const JSFunctionSpec> sMethods[] = {
942 : { nullptr, &sMethods_specs[0] },
943 : { nullptr, nullptr }
944 : };
945 :
946 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
947 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
948 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
949 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
950 :
951 :
952 : static uint16_t sNativeProperties_sortedPropertyIndices[1];
953 : static PropertyInfo sNativeProperties_propertyInfos[1];
954 :
955 : static const NativePropertiesN<1> sNativeProperties = {
956 : false, 0,
957 : false, 0,
958 : true, 0 /* sMethods */,
959 : false, 0,
960 : false, 0,
961 : false, 0,
962 : false, 0,
963 : -1,
964 : 1,
965 : sNativeProperties_sortedPropertyIndices,
966 : {
967 : { sMethods, &sNativeProperties_propertyInfos[0] }
968 : }
969 : };
970 : static_assert(1 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
971 : "We have a property info count that is oversized");
972 :
973 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
974 : {
975 : "TestInterfaceIterableDoubleIteratorPrototype",
976 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
977 : JS_NULL_CLASS_OPS,
978 : JS_NULL_CLASS_SPEC,
979 : JS_NULL_CLASS_EXT,
980 : JS_NULL_OBJECT_OPS
981 : },
982 : eInterfacePrototype,
983 : false,
984 : prototypes::id::TestInterfaceIterableDoubleIterator,
985 : PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleIterator>::Depth,
986 : sNativePropertyHooks,
987 : "[object TestInterfaceIterableDoubleIteratorPrototype]",
988 : JS::GetRealmIteratorPrototype
989 : };
990 :
991 : static const js::ClassOps sClassOps = {
992 : nullptr, /* addProperty */
993 : nullptr, /* delProperty */
994 : nullptr, /* getProperty */
995 : nullptr, /* setProperty */
996 : nullptr, /* enumerate */
997 : nullptr, /* newEnumerate */
998 : nullptr, /* resolve */
999 : nullptr, /* mayResolve */
1000 : _finalize, /* finalize */
1001 : nullptr, /* call */
1002 : nullptr, /* hasInstance */
1003 : nullptr, /* construct */
1004 : nullptr, /* trace */
1005 : };
1006 :
1007 : static const js::ClassExtension sClassExtension = {
1008 : nullptr, /* weakmapKeyDelegateOp */
1009 : nullptr /* objectMovedOp */
1010 : };
1011 :
1012 : static const DOMJSClass sClass = {
1013 : { "TestInterfaceIterableDoubleIterator",
1014 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
1015 : &sClassOps,
1016 : JS_NULL_CLASS_SPEC,
1017 : &sClassExtension,
1018 : JS_NULL_OBJECT_OPS
1019 : },
1020 : { prototypes::id::TestInterfaceIterableDoubleIterator, 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 },
1021 : IsBaseOf<nsISupports, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble> >::value,
1022 : sNativePropertyHooks,
1023 : FindAssociatedGlobalForNative<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>>::Get,
1024 : GetProtoObjectHandle,
1025 : GetCCParticipant<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>>::Get()
1026 : };
1027 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
1028 : "Must have the right minimal number of reserved slots.");
1029 : static_assert(1 >= 1,
1030 : "Must have enough reserved slots.");
1031 :
1032 : const JSClass*
1033 0 : GetJSClass()
1034 : {
1035 0 : return sClass.ToJSClass();
1036 : }
1037 :
1038 : bool
1039 0 : Wrap(JSContext* aCx, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>* aObject, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1040 : {
1041 : MOZ_ASSERT(static_cast<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>*>(aObject) ==
1042 : reinterpret_cast<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>*>(aObject),
1043 : "Multiple inheritance for mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble> is broken.");
1044 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1045 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1046 :
1047 0 : JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
1048 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1049 0 : if (!canonicalProto) {
1050 0 : return false;
1051 : }
1052 0 : JS::Rooted<JSObject*> proto(aCx);
1053 0 : if (aGivenProto) {
1054 0 : proto = aGivenProto;
1055 : // Unfortunately, while aGivenProto was in the compartment of aCx
1056 : // coming in, we changed compartments to that of "parent" so may need
1057 : // to wrap the proto here.
1058 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1059 0 : if (!JS_WrapObject(aCx, &proto)) {
1060 0 : return false;
1061 : }
1062 : }
1063 : } else {
1064 0 : proto = canonicalProto;
1065 : }
1066 :
1067 0 : BindingJSObjectCreator<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>> creator(aCx);
1068 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
1069 0 : if (!aReflector) {
1070 0 : return false;
1071 : }
1072 :
1073 :
1074 :
1075 0 : creator.InitializationSucceeded();
1076 0 : return true;
1077 : }
1078 :
1079 : const NativePropertyHooks sNativePropertyHooks[] = { {
1080 : nullptr,
1081 : nullptr,
1082 : nullptr,
1083 : { sNativeProperties.Upcast(), nullptr },
1084 : prototypes::id::TestInterfaceIterableDoubleIterator,
1085 : constructors::id::_ID_Count,
1086 : nullptr,
1087 : &DefaultXrayExpandoObjectClass
1088 : } };
1089 :
1090 : void
1091 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
1092 : {
1093 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmIteratorPrototype(aCx));
1094 0 : if (!parentProto) {
1095 0 : return;
1096 : }
1097 :
1098 : static bool sIdsInited = false;
1099 0 : if (!sIdsInited && NS_IsMainThread()) {
1100 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
1101 0 : return;
1102 : }
1103 0 : sIdsInited = true;
1104 : }
1105 :
1106 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableDoubleIterator);
1107 0 : JS::Heap<JSObject*>* interfaceCache = nullptr;
1108 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
1109 : &sPrototypeClass.mBase, protoCache,
1110 : nullptr, nullptr, 0, nullptr,
1111 : interfaceCache,
1112 : sNativeProperties.Upcast(),
1113 : nullptr,
1114 : nullptr, aDefineOnGlobal,
1115 : nullptr,
1116 0 : false);
1117 : }
1118 :
1119 : JS::Handle<JSObject*>
1120 0 : GetProtoObjectHandle(JSContext* aCx)
1121 : {
1122 : /* Get the interface prototype object for this class. This will create the
1123 : object as needed. */
1124 0 : bool aDefineOnGlobal = true;
1125 :
1126 : /* Make sure our global is sane. Hopefully we can remove this sometime */
1127 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
1128 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
1129 0 : return nullptr;
1130 : }
1131 :
1132 : /* Check to see whether the interface objects are already installed */
1133 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
1134 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceIterableDoubleIterator)) {
1135 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
1136 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
1137 : }
1138 :
1139 : /*
1140 : * The object might _still_ be null, but that's OK.
1141 : *
1142 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
1143 : * traced by TraceProtoAndIfaceCache() and its contents are never
1144 : * changed after they have been set.
1145 : *
1146 : * Calling address() avoids the read read barrier that does gray
1147 : * unmarking, but it's not possible for the object to be gray here.
1148 : */
1149 :
1150 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceIterableDoubleIterator);
1151 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
1152 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
1153 : }
1154 :
1155 : } // namespace TestInterfaceIterableDoubleIteratorBinding
1156 :
1157 :
1158 :
1159 : namespace TestInterfaceIterableDoubleUnionBinding {
1160 :
1161 : static bool
1162 0 : entries(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceIterableDoubleUnion* self, const JSJitMethodCallArgs& args)
1163 : {
1164 : typedef mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion> itrType;
1165 : RefPtr<itrType> result(new itrType(self,
1166 : itrType::IterableIteratorType::Entries,
1167 0 : &TestInterfaceIterableDoubleUnionIteratorBinding::Wrap));
1168 : static_assert(!IsPointer<decltype(result)>::value,
1169 : "NewObject implies that we need to keep the object alive with a strong reference.");
1170 0 : if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
1171 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
1172 0 : return false;
1173 : }
1174 0 : return true;
1175 : }
1176 :
1177 : static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
1178 : static const JSTypedMethodJitInfo entries_methodinfo = {
1179 : {
1180 : { (JSJitGetterOp)entries },
1181 : { prototypes::id::TestInterfaceIterableDoubleUnion },
1182 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::Depth },
1183 : JSJitInfo::Method,
1184 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
1185 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
1186 : false, /* isInfallible. False in setters. */
1187 : false, /* isMovable. Not relevant for setters. */
1188 : false, /* isEliminatable. Not relevant for setters. */
1189 : false, /* isAlwaysInSlot. Only relevant for getters. */
1190 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
1191 : true, /* isTypedMethod. Only relevant for methods. */
1192 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
1193 : },
1194 : entries_methodinfo_argTypes
1195 : };
1196 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1197 : static_assert(0 < 1, "There is no slot for us");
1198 :
1199 : static bool
1200 0 : keys(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceIterableDoubleUnion* self, const JSJitMethodCallArgs& args)
1201 : {
1202 : typedef mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion> itrType;
1203 : RefPtr<itrType> result(new itrType(self,
1204 : itrType::IterableIteratorType::Keys,
1205 0 : &TestInterfaceIterableDoubleUnionIteratorBinding::Wrap));
1206 : static_assert(!IsPointer<decltype(result)>::value,
1207 : "NewObject implies that we need to keep the object alive with a strong reference.");
1208 0 : if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
1209 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
1210 0 : return false;
1211 : }
1212 0 : return true;
1213 : }
1214 :
1215 : static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
1216 : static const JSTypedMethodJitInfo keys_methodinfo = {
1217 : {
1218 : { (JSJitGetterOp)keys },
1219 : { prototypes::id::TestInterfaceIterableDoubleUnion },
1220 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::Depth },
1221 : JSJitInfo::Method,
1222 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
1223 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
1224 : false, /* isInfallible. False in setters. */
1225 : false, /* isMovable. Not relevant for setters. */
1226 : false, /* isEliminatable. Not relevant for setters. */
1227 : false, /* isAlwaysInSlot. Only relevant for getters. */
1228 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
1229 : true, /* isTypedMethod. Only relevant for methods. */
1230 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
1231 : },
1232 : keys_methodinfo_argTypes
1233 : };
1234 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1235 : static_assert(0 < 1, "There is no slot for us");
1236 :
1237 : static bool
1238 0 : values(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceIterableDoubleUnion* self, const JSJitMethodCallArgs& args)
1239 : {
1240 : typedef mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion> itrType;
1241 : RefPtr<itrType> result(new itrType(self,
1242 : itrType::IterableIteratorType::Values,
1243 0 : &TestInterfaceIterableDoubleUnionIteratorBinding::Wrap));
1244 : static_assert(!IsPointer<decltype(result)>::value,
1245 : "NewObject implies that we need to keep the object alive with a strong reference.");
1246 0 : if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
1247 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
1248 0 : return false;
1249 : }
1250 0 : return true;
1251 : }
1252 :
1253 : static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
1254 : static const JSTypedMethodJitInfo values_methodinfo = {
1255 : {
1256 : { (JSJitGetterOp)values },
1257 : { prototypes::id::TestInterfaceIterableDoubleUnion },
1258 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::Depth },
1259 : JSJitInfo::Method,
1260 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
1261 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
1262 : false, /* isInfallible. False in setters. */
1263 : false, /* isMovable. Not relevant for setters. */
1264 : false, /* isEliminatable. Not relevant for setters. */
1265 : false, /* isAlwaysInSlot. Only relevant for getters. */
1266 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
1267 : true, /* isTypedMethod. Only relevant for methods. */
1268 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
1269 : },
1270 : values_methodinfo_argTypes
1271 : };
1272 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1273 : static_assert(0 < 1, "There is no slot for us");
1274 :
1275 : static bool
1276 0 : forEach(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceIterableDoubleUnion* self, const JSJitMethodCallArgs& args)
1277 : {
1278 0 : JS::Rooted<JSObject*> arg0(cx);
1279 0 : if (args.get(0).isObject()) {
1280 0 : arg0 = &args.get(0).toObject();
1281 : } else {
1282 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceIterableDoubleUnion.forEach");
1283 0 : return false;
1284 : }
1285 0 : JS::Rooted<JS::Value> arg1(cx);
1286 0 : if (args.hasDefined(1)) {
1287 0 : arg1 = args.get(1);
1288 : } else {
1289 0 : arg1 = JS::UndefinedValue();
1290 : }
1291 0 : if (!JS::IsCallable(arg0)) {
1292 0 : ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 1 of TestInterfaceIterableDoubleUnion.forEach");
1293 0 : return false;
1294 : }
1295 0 : JS::AutoValueArray<3> callArgs(cx);
1296 0 : callArgs[2].setObject(*obj);
1297 0 : JS::Rooted<JS::Value> ignoredReturnVal(cx);
1298 0 : for (size_t i = 0; i < self->GetIterableLength(); ++i) {
1299 0 : if (!ToJSValue(cx, self->GetValueAtIndex(i), callArgs[0])) {
1300 0 : return false;
1301 : }
1302 0 : if (!ToJSValue(cx, self->GetKeyAtIndex(i), callArgs[1])) {
1303 0 : return false;
1304 : }
1305 0 : if (!JS::Call(cx, arg1, arg0, JS::HandleValueArray(callArgs),
1306 : &ignoredReturnVal)) {
1307 0 : return false;
1308 : }
1309 : }
1310 0 : args.rval().setUndefined();
1311 0 : return true;
1312 : }
1313 :
1314 : static const JSJitInfo forEach_methodinfo = {
1315 : { (JSJitGetterOp)forEach },
1316 : { prototypes::id::TestInterfaceIterableDoubleUnion },
1317 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::Depth },
1318 : JSJitInfo::Method,
1319 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
1320 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
1321 : false, /* isInfallible. False in setters. */
1322 : false, /* isMovable. Not relevant for setters. */
1323 : false, /* isEliminatable. Not relevant for setters. */
1324 : false, /* isAlwaysInSlot. Only relevant for getters. */
1325 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
1326 : false, /* isTypedMethod. Only relevant for methods. */
1327 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
1328 : };
1329 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1330 : static_assert(0 < 1, "There is no slot for us");
1331 :
1332 : static bool
1333 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
1334 : {
1335 0 : mozilla::dom::TestInterfaceIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDoubleUnion>(obj);
1336 : // We don't want to preserve if we don't have a wrapper, and we
1337 : // obviously can't preserve if we're not initialized.
1338 0 : if (self && self->GetWrapperPreserveColor()) {
1339 0 : PreserveWrapper(self);
1340 : }
1341 0 : return true;
1342 : }
1343 :
1344 : static void
1345 0 : _finalize(js::FreeOp* fop, JSObject* obj)
1346 : {
1347 0 : mozilla::dom::TestInterfaceIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDoubleUnion>(obj);
1348 0 : if (self) {
1349 0 : ClearWrapper(self, self, obj);
1350 0 : AddForDeferredFinalization<mozilla::dom::TestInterfaceIterableDoubleUnion>(self);
1351 : }
1352 0 : }
1353 :
1354 : static void
1355 0 : _objectMoved(JSObject* obj, const JSObject* old)
1356 : {
1357 0 : mozilla::dom::TestInterfaceIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDoubleUnion>(obj);
1358 0 : if (self) {
1359 0 : UpdateWrapper(self, self, obj, old);
1360 : }
1361 0 : }
1362 :
1363 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
1364 : #if defined(__clang__)
1365 : #pragma clang diagnostic push
1366 : #pragma clang diagnostic ignored "-Wmissing-braces"
1367 : #endif
1368 : static const JSFunctionSpec sMethods_specs[] = {
1369 : JS_FNSPEC("entries", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
1370 : JS_FNSPEC("keys", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
1371 : JS_FNSPEC("values", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
1372 : JS_FNSPEC("forEach", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
1373 : JS_FS_END
1374 : };
1375 : #if defined(__clang__)
1376 : #pragma clang diagnostic pop
1377 : #endif
1378 :
1379 :
1380 : // Can't be const because the pref-enabled boolean needs to be writable
1381 : static Prefable<const JSFunctionSpec> sMethods[] = {
1382 : { nullptr, &sMethods_specs[0] },
1383 : { nullptr, nullptr }
1384 : };
1385 :
1386 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
1387 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
1388 : static_assert(4 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
1389 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
1390 :
1391 :
1392 : static uint16_t sNativeProperties_sortedPropertyIndices[4];
1393 : static PropertyInfo sNativeProperties_propertyInfos[4];
1394 :
1395 : static const NativePropertiesN<1> sNativeProperties = {
1396 : false, 0,
1397 : false, 0,
1398 : true, 0 /* sMethods */,
1399 : false, 0,
1400 : false, 0,
1401 : false, 0,
1402 : false, 0,
1403 : 0,
1404 : 4,
1405 : sNativeProperties_sortedPropertyIndices,
1406 : {
1407 : { sMethods, &sNativeProperties_propertyInfos[0] }
1408 : }
1409 : };
1410 : static_assert(4 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
1411 : "We have a property info count that is oversized");
1412 :
1413 : static bool
1414 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
1415 : {
1416 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
1417 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
1418 0 : if (!args.isConstructing()) {
1419 : // XXXbz wish I could get the name from the callee instead of
1420 : // Adding more relocations
1421 0 : return ThrowConstructorWithoutNew(cx, "TestInterfaceIterableDoubleUnion");
1422 : }
1423 :
1424 0 : GlobalObject global(cx, obj);
1425 0 : if (global.Failed()) {
1426 0 : return false;
1427 : }
1428 :
1429 0 : JS::Rooted<JSObject*> desiredProto(cx);
1430 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
1431 0 : return false;
1432 : }
1433 :
1434 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
1435 0 : Maybe<JSAutoCompartment> ac;
1436 0 : if (objIsXray) {
1437 0 : obj = js::CheckedUnwrap(obj);
1438 0 : if (!obj) {
1439 0 : return false;
1440 : }
1441 0 : ac.emplace(cx, obj);
1442 0 : if (!JS_WrapObject(cx, &desiredProto)) {
1443 0 : return false;
1444 : }
1445 : }
1446 0 : binding_detail::FastErrorResult rv;
1447 0 : auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceIterableDoubleUnion>(mozilla::dom::TestInterfaceIterableDoubleUnion::Constructor(global, rv)));
1448 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
1449 0 : return false;
1450 : }
1451 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
1452 : static_assert(!IsPointer<decltype(result)>::value,
1453 : "NewObject implies that we need to keep the object alive with a strong reference.");
1454 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
1455 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
1456 0 : return false;
1457 : }
1458 0 : return true;
1459 : }
1460 :
1461 : static const js::ClassOps sInterfaceObjectClassOps = {
1462 : nullptr, /* addProperty */
1463 : nullptr, /* delProperty */
1464 : nullptr, /* getProperty */
1465 : nullptr, /* setProperty */
1466 : nullptr, /* enumerate */
1467 : nullptr, /* newEnumerate */
1468 : nullptr, /* resolve */
1469 : nullptr, /* mayResolve */
1470 : nullptr, /* finalize */
1471 : _constructor, /* call */
1472 : nullptr, /* hasInstance */
1473 : _constructor, /* construct */
1474 : nullptr, /* trace */
1475 : };
1476 :
1477 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
1478 : {
1479 : "Function",
1480 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
1481 : &sInterfaceObjectClassOps,
1482 : JS_NULL_CLASS_SPEC,
1483 : JS_NULL_CLASS_EXT,
1484 : &sInterfaceObjectClassObjectOps
1485 : },
1486 : eInterface,
1487 : true,
1488 : prototypes::id::TestInterfaceIterableDoubleUnion,
1489 : PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::Depth,
1490 : sNativePropertyHooks,
1491 : "function TestInterfaceIterableDoubleUnion() {\n [native code]\n}",
1492 : JS::GetRealmFunctionPrototype
1493 : };
1494 :
1495 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
1496 : {
1497 : "TestInterfaceIterableDoubleUnionPrototype",
1498 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
1499 : JS_NULL_CLASS_OPS,
1500 : JS_NULL_CLASS_SPEC,
1501 : JS_NULL_CLASS_EXT,
1502 : JS_NULL_OBJECT_OPS
1503 : },
1504 : eInterfacePrototype,
1505 : false,
1506 : prototypes::id::TestInterfaceIterableDoubleUnion,
1507 : PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::Depth,
1508 : sNativePropertyHooks,
1509 : "[object TestInterfaceIterableDoubleUnionPrototype]",
1510 : JS::GetRealmObjectPrototype
1511 : };
1512 :
1513 : bool
1514 0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
1515 : {
1516 : static bool sPrefValue;
1517 : static bool sPrefCacheSetUp = false;
1518 0 : if (!sPrefCacheSetUp) {
1519 0 : sPrefCacheSetUp = true;
1520 0 : Preferences::AddBoolVarCache(&sPrefValue, "dom.expose_test_interfaces");
1521 : }
1522 :
1523 0 : return sPrefValue;
1524 : }
1525 :
1526 : JSObject*
1527 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
1528 : {
1529 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
1530 : }
1531 :
1532 : static const js::ClassOps sClassOps = {
1533 : _addProperty, /* addProperty */
1534 : nullptr, /* delProperty */
1535 : nullptr, /* getProperty */
1536 : nullptr, /* setProperty */
1537 : nullptr, /* enumerate */
1538 : nullptr, /* newEnumerate */
1539 : nullptr, /* resolve */
1540 : nullptr, /* mayResolve */
1541 : _finalize, /* finalize */
1542 : nullptr, /* call */
1543 : nullptr, /* hasInstance */
1544 : nullptr, /* construct */
1545 : nullptr, /* trace */
1546 : };
1547 :
1548 : static const js::ClassExtension sClassExtension = {
1549 : nullptr, /* weakmapKeyDelegateOp */
1550 : _objectMoved /* objectMovedOp */
1551 : };
1552 :
1553 : static const DOMJSClass sClass = {
1554 : { "TestInterfaceIterableDoubleUnion",
1555 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
1556 : &sClassOps,
1557 : JS_NULL_CLASS_SPEC,
1558 : &sClassExtension,
1559 : JS_NULL_OBJECT_OPS
1560 : },
1561 : { prototypes::id::TestInterfaceIterableDoubleUnion, 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 },
1562 : IsBaseOf<nsISupports, mozilla::dom::TestInterfaceIterableDoubleUnion >::value,
1563 : sNativePropertyHooks,
1564 : FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceIterableDoubleUnion>::Get,
1565 : GetProtoObjectHandle,
1566 : GetCCParticipant<mozilla::dom::TestInterfaceIterableDoubleUnion>::Get()
1567 : };
1568 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
1569 : "Must have the right minimal number of reserved slots.");
1570 : static_assert(1 >= 1,
1571 : "Must have enough reserved slots.");
1572 :
1573 : const JSClass*
1574 0 : GetJSClass()
1575 : {
1576 0 : return sClass.ToJSClass();
1577 : }
1578 :
1579 : bool
1580 0 : Wrap(JSContext* aCx, mozilla::dom::TestInterfaceIterableDoubleUnion* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1581 : {
1582 : MOZ_ASSERT(static_cast<mozilla::dom::TestInterfaceIterableDoubleUnion*>(aObject) ==
1583 : reinterpret_cast<mozilla::dom::TestInterfaceIterableDoubleUnion*>(aObject),
1584 : "Multiple inheritance for mozilla::dom::TestInterfaceIterableDoubleUnion is broken.");
1585 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1586 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1587 0 : MOZ_ASSERT(!aCache->GetWrapper(),
1588 : "You should probably not be using Wrap() directly; use "
1589 : "GetOrCreateDOMReflector instead");
1590 :
1591 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
1592 : "nsISupports must be on our primary inheritance chain");
1593 :
1594 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
1595 0 : if (!global) {
1596 0 : return false;
1597 : }
1598 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
1599 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
1600 :
1601 : // That might have ended up wrapping us already, due to the wonders
1602 : // of XBL. Check for that, and bail out as needed.
1603 0 : aReflector.set(aCache->GetWrapper());
1604 0 : if (aReflector) {
1605 : #ifdef DEBUG
1606 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
1607 : #endif // DEBUG
1608 0 : return true;
1609 : }
1610 :
1611 0 : JSAutoCompartment ac(aCx, global);
1612 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1613 0 : if (!canonicalProto) {
1614 0 : return false;
1615 : }
1616 0 : JS::Rooted<JSObject*> proto(aCx);
1617 0 : if (aGivenProto) {
1618 0 : proto = aGivenProto;
1619 : // Unfortunately, while aGivenProto was in the compartment of aCx
1620 : // coming in, we changed compartments to that of "parent" so may need
1621 : // to wrap the proto here.
1622 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1623 0 : if (!JS_WrapObject(aCx, &proto)) {
1624 0 : return false;
1625 : }
1626 : }
1627 : } else {
1628 0 : proto = canonicalProto;
1629 : }
1630 :
1631 0 : BindingJSObjectCreator<mozilla::dom::TestInterfaceIterableDoubleUnion> creator(aCx);
1632 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
1633 0 : if (!aReflector) {
1634 0 : return false;
1635 : }
1636 :
1637 0 : aCache->SetWrapper(aReflector);
1638 0 : creator.InitializationSucceeded();
1639 :
1640 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
1641 : aCache->GetWrapperPreserveColor() == aReflector);
1642 : // If proto != canonicalProto, we have to preserve our wrapper;
1643 : // otherwise we won't be able to properly recreate it later, since
1644 : // we won't know what proto to use. Note that we don't check
1645 : // aGivenProto here, since it's entirely possible (and even
1646 : // somewhat common) to have a non-null aGivenProto which is the
1647 : // same as canonicalProto.
1648 0 : if (proto != canonicalProto) {
1649 0 : PreserveWrapper(aObject);
1650 : }
1651 :
1652 0 : return true;
1653 : }
1654 :
1655 : const NativePropertyHooks sNativePropertyHooks[] = { {
1656 : nullptr,
1657 : nullptr,
1658 : nullptr,
1659 : { sNativeProperties.Upcast(), nullptr },
1660 : prototypes::id::TestInterfaceIterableDoubleUnion,
1661 : constructors::id::TestInterfaceIterableDoubleUnion,
1662 : nullptr,
1663 : &DefaultXrayExpandoObjectClass
1664 : } };
1665 :
1666 : void
1667 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
1668 : {
1669 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
1670 0 : if (!parentProto) {
1671 0 : return;
1672 : }
1673 :
1674 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
1675 0 : if (!constructorProto) {
1676 0 : return;
1677 : }
1678 :
1679 : static bool sIdsInited = false;
1680 0 : if (!sIdsInited && NS_IsMainThread()) {
1681 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
1682 0 : return;
1683 : }
1684 0 : sIdsInited = true;
1685 : }
1686 :
1687 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableDoubleUnion);
1688 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceIterableDoubleUnion);
1689 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
1690 : &sPrototypeClass.mBase, protoCache,
1691 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
1692 : interfaceCache,
1693 : sNativeProperties.Upcast(),
1694 : nullptr,
1695 : "TestInterfaceIterableDoubleUnion", aDefineOnGlobal,
1696 : nullptr,
1697 0 : false);
1698 :
1699 : // Set up aliases on the interface prototype object we just created.
1700 0 : JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
1701 0 : if (!proto) {
1702 0 : *protoCache = nullptr;
1703 0 : if (interfaceCache) {
1704 0 : *interfaceCache = nullptr;
1705 : }
1706 0 : return;
1707 : }
1708 :
1709 0 : JS::Rooted<JS::Value> aliasedVal(aCx);
1710 :
1711 0 : if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
1712 0 : *protoCache = nullptr;
1713 0 : if (interfaceCache) {
1714 0 : *interfaceCache = nullptr;
1715 : }
1716 0 : return;
1717 : }
1718 0 : JS::Rooted<jsid> iteratorId(aCx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::iterator)));
1719 0 : if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
1720 0 : *protoCache = nullptr;
1721 0 : if (interfaceCache) {
1722 0 : *interfaceCache = nullptr;
1723 : }
1724 0 : return;
1725 : }
1726 : }
1727 :
1728 : JS::Handle<JSObject*>
1729 0 : GetProtoObjectHandle(JSContext* aCx)
1730 : {
1731 : /* Get the interface prototype object for this class. This will create the
1732 : object as needed. */
1733 0 : bool aDefineOnGlobal = true;
1734 :
1735 : /* Make sure our global is sane. Hopefully we can remove this sometime */
1736 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
1737 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
1738 0 : return nullptr;
1739 : }
1740 :
1741 : /* Check to see whether the interface objects are already installed */
1742 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
1743 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceIterableDoubleUnion)) {
1744 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
1745 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
1746 : }
1747 :
1748 : /*
1749 : * The object might _still_ be null, but that's OK.
1750 : *
1751 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
1752 : * traced by TraceProtoAndIfaceCache() and its contents are never
1753 : * changed after they have been set.
1754 : *
1755 : * Calling address() avoids the read read barrier that does gray
1756 : * unmarking, but it's not possible for the object to be gray here.
1757 : */
1758 :
1759 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceIterableDoubleUnion);
1760 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
1761 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
1762 : }
1763 :
1764 : JS::Handle<JSObject*>
1765 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
1766 : {
1767 : /* Get the interface object for this class. This will create the object as
1768 : needed. */
1769 :
1770 : /* Make sure our global is sane. Hopefully we can remove this sometime */
1771 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
1772 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
1773 0 : return nullptr;
1774 : }
1775 :
1776 : /* Check to see whether the interface objects are already installed */
1777 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
1778 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::TestInterfaceIterableDoubleUnion)) {
1779 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
1780 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
1781 : }
1782 :
1783 : /*
1784 : * The object might _still_ be null, but that's OK.
1785 : *
1786 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
1787 : * traced by TraceProtoAndIfaceCache() and its contents are never
1788 : * changed after they have been set.
1789 : *
1790 : * Calling address() avoids the read read barrier that does gray
1791 : * unmarking, but it's not possible for the object to be gray here.
1792 : */
1793 :
1794 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::TestInterfaceIterableDoubleUnion);
1795 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
1796 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
1797 : }
1798 :
1799 : JSObject*
1800 0 : GetConstructorObject(JSContext* aCx)
1801 : {
1802 0 : return GetConstructorObjectHandle(aCx);
1803 : }
1804 :
1805 : } // namespace TestInterfaceIterableDoubleUnionBinding
1806 :
1807 :
1808 :
1809 : namespace TestInterfaceIterableDoubleUnionIteratorBinding {
1810 :
1811 : static bool
1812 0 : next(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>* self, const JSJitMethodCallArgs& args)
1813 : {
1814 0 : binding_detail::FastErrorResult rv;
1815 0 : JS::Rooted<JSObject*> result(cx);
1816 0 : self->Next(cx, &result, rv);
1817 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
1818 0 : return false;
1819 : }
1820 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
1821 0 : JS::ExposeObjectToActiveJS(result);
1822 0 : args.rval().setObject(*result);
1823 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
1824 0 : return false;
1825 : }
1826 0 : return true;
1827 : }
1828 :
1829 : static const JSJitInfo next_methodinfo = {
1830 : { (JSJitGetterOp)next },
1831 : { prototypes::id::TestInterfaceIterableDoubleUnionIterator },
1832 : { PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnionIterator>::Depth },
1833 : JSJitInfo::Method,
1834 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
1835 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
1836 : false, /* isInfallible. False in setters. */
1837 : false, /* isMovable. Not relevant for setters. */
1838 : false, /* isEliminatable. Not relevant for setters. */
1839 : false, /* isAlwaysInSlot. Only relevant for getters. */
1840 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
1841 : false, /* isTypedMethod. Only relevant for methods. */
1842 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
1843 : };
1844 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
1845 : static_assert(0 < 1, "There is no slot for us");
1846 :
1847 : static void
1848 0 : _finalize(js::FreeOp* fop, JSObject* obj)
1849 : {
1850 0 : mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>>(obj);
1851 0 : if (self) {
1852 0 : AddForDeferredFinalization<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>>(self);
1853 : }
1854 0 : }
1855 :
1856 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
1857 : #if defined(__clang__)
1858 : #pragma clang diagnostic push
1859 : #pragma clang diagnostic ignored "-Wmissing-braces"
1860 : #endif
1861 : static const JSFunctionSpec sMethods_specs[] = {
1862 : JS_FNSPEC("next", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&next_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
1863 : JS_FS_END
1864 : };
1865 : #if defined(__clang__)
1866 : #pragma clang diagnostic pop
1867 : #endif
1868 :
1869 :
1870 : // Can't be const because the pref-enabled boolean needs to be writable
1871 : static Prefable<const JSFunctionSpec> sMethods[] = {
1872 : { nullptr, &sMethods_specs[0] },
1873 : { nullptr, nullptr }
1874 : };
1875 :
1876 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
1877 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
1878 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
1879 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
1880 :
1881 :
1882 : static uint16_t sNativeProperties_sortedPropertyIndices[1];
1883 : static PropertyInfo sNativeProperties_propertyInfos[1];
1884 :
1885 : static const NativePropertiesN<1> sNativeProperties = {
1886 : false, 0,
1887 : false, 0,
1888 : true, 0 /* sMethods */,
1889 : false, 0,
1890 : false, 0,
1891 : false, 0,
1892 : false, 0,
1893 : -1,
1894 : 1,
1895 : sNativeProperties_sortedPropertyIndices,
1896 : {
1897 : { sMethods, &sNativeProperties_propertyInfos[0] }
1898 : }
1899 : };
1900 : static_assert(1 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
1901 : "We have a property info count that is oversized");
1902 :
1903 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
1904 : {
1905 : "TestInterfaceIterableDoubleUnionIteratorPrototype",
1906 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
1907 : JS_NULL_CLASS_OPS,
1908 : JS_NULL_CLASS_SPEC,
1909 : JS_NULL_CLASS_EXT,
1910 : JS_NULL_OBJECT_OPS
1911 : },
1912 : eInterfacePrototype,
1913 : false,
1914 : prototypes::id::TestInterfaceIterableDoubleUnionIterator,
1915 : PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnionIterator>::Depth,
1916 : sNativePropertyHooks,
1917 : "[object TestInterfaceIterableDoubleUnionIteratorPrototype]",
1918 : JS::GetRealmIteratorPrototype
1919 : };
1920 :
1921 : static const js::ClassOps sClassOps = {
1922 : nullptr, /* addProperty */
1923 : nullptr, /* delProperty */
1924 : nullptr, /* getProperty */
1925 : nullptr, /* setProperty */
1926 : nullptr, /* enumerate */
1927 : nullptr, /* newEnumerate */
1928 : nullptr, /* resolve */
1929 : nullptr, /* mayResolve */
1930 : _finalize, /* finalize */
1931 : nullptr, /* call */
1932 : nullptr, /* hasInstance */
1933 : nullptr, /* construct */
1934 : nullptr, /* trace */
1935 : };
1936 :
1937 : static const js::ClassExtension sClassExtension = {
1938 : nullptr, /* weakmapKeyDelegateOp */
1939 : nullptr /* objectMovedOp */
1940 : };
1941 :
1942 : static const DOMJSClass sClass = {
1943 : { "TestInterfaceIterableDoubleUnionIterator",
1944 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
1945 : &sClassOps,
1946 : JS_NULL_CLASS_SPEC,
1947 : &sClassExtension,
1948 : JS_NULL_OBJECT_OPS
1949 : },
1950 : { prototypes::id::TestInterfaceIterableDoubleUnionIterator, 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 },
1951 : IsBaseOf<nsISupports, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion> >::value,
1952 : sNativePropertyHooks,
1953 : FindAssociatedGlobalForNative<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>>::Get,
1954 : GetProtoObjectHandle,
1955 : GetCCParticipant<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>>::Get()
1956 : };
1957 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
1958 : "Must have the right minimal number of reserved slots.");
1959 : static_assert(1 >= 1,
1960 : "Must have enough reserved slots.");
1961 :
1962 : const JSClass*
1963 0 : GetJSClass()
1964 : {
1965 0 : return sClass.ToJSClass();
1966 : }
1967 :
1968 : bool
1969 0 : Wrap(JSContext* aCx, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>* aObject, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
1970 : {
1971 : MOZ_ASSERT(static_cast<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>*>(aObject) ==
1972 : reinterpret_cast<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>*>(aObject),
1973 : "Multiple inheritance for mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion> is broken.");
1974 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
1975 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
1976 :
1977 0 : JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
1978 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
1979 0 : if (!canonicalProto) {
1980 0 : return false;
1981 : }
1982 0 : JS::Rooted<JSObject*> proto(aCx);
1983 0 : if (aGivenProto) {
1984 0 : proto = aGivenProto;
1985 : // Unfortunately, while aGivenProto was in the compartment of aCx
1986 : // coming in, we changed compartments to that of "parent" so may need
1987 : // to wrap the proto here.
1988 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
1989 0 : if (!JS_WrapObject(aCx, &proto)) {
1990 0 : return false;
1991 : }
1992 : }
1993 : } else {
1994 0 : proto = canonicalProto;
1995 : }
1996 :
1997 0 : BindingJSObjectCreator<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>> creator(aCx);
1998 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
1999 0 : if (!aReflector) {
2000 0 : return false;
2001 : }
2002 :
2003 :
2004 :
2005 0 : creator.InitializationSucceeded();
2006 0 : return true;
2007 : }
2008 :
2009 : const NativePropertyHooks sNativePropertyHooks[] = { {
2010 : nullptr,
2011 : nullptr,
2012 : nullptr,
2013 : { sNativeProperties.Upcast(), nullptr },
2014 : prototypes::id::TestInterfaceIterableDoubleUnionIterator,
2015 : constructors::id::_ID_Count,
2016 : nullptr,
2017 : &DefaultXrayExpandoObjectClass
2018 : } };
2019 :
2020 : void
2021 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
2022 : {
2023 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmIteratorPrototype(aCx));
2024 0 : if (!parentProto) {
2025 0 : return;
2026 : }
2027 :
2028 : static bool sIdsInited = false;
2029 0 : if (!sIdsInited && NS_IsMainThread()) {
2030 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
2031 0 : return;
2032 : }
2033 0 : sIdsInited = true;
2034 : }
2035 :
2036 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableDoubleUnionIterator);
2037 0 : JS::Heap<JSObject*>* interfaceCache = nullptr;
2038 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
2039 : &sPrototypeClass.mBase, protoCache,
2040 : nullptr, nullptr, 0, nullptr,
2041 : interfaceCache,
2042 : sNativeProperties.Upcast(),
2043 : nullptr,
2044 : nullptr, aDefineOnGlobal,
2045 : nullptr,
2046 0 : false);
2047 : }
2048 :
2049 : JS::Handle<JSObject*>
2050 0 : GetProtoObjectHandle(JSContext* aCx)
2051 : {
2052 : /* Get the interface prototype object for this class. This will create the
2053 : object as needed. */
2054 0 : bool aDefineOnGlobal = true;
2055 :
2056 : /* Make sure our global is sane. Hopefully we can remove this sometime */
2057 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
2058 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
2059 0 : return nullptr;
2060 : }
2061 :
2062 : /* Check to see whether the interface objects are already installed */
2063 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
2064 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceIterableDoubleUnionIterator)) {
2065 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
2066 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
2067 : }
2068 :
2069 : /*
2070 : * The object might _still_ be null, but that's OK.
2071 : *
2072 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
2073 : * traced by TraceProtoAndIfaceCache() and its contents are never
2074 : * changed after they have been set.
2075 : *
2076 : * Calling address() avoids the read read barrier that does gray
2077 : * unmarking, but it's not possible for the object to be gray here.
2078 : */
2079 :
2080 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceIterableDoubleUnionIterator);
2081 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
2082 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
2083 : }
2084 :
2085 : } // namespace TestInterfaceIterableDoubleUnionIteratorBinding
2086 :
2087 :
2088 :
2089 : namespace TestInterfaceIterableSingleBinding {
2090 :
2091 : static bool
2092 0 : get_length(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceIterableSingle* self, JSJitGetterCallArgs args)
2093 : {
2094 0 : uint32_t result(self->Length());
2095 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
2096 0 : args.rval().setNumber(result);
2097 0 : return true;
2098 : }
2099 :
2100 : static const JSJitInfo length_getterinfo = {
2101 : { (JSJitGetterOp)get_length },
2102 : { prototypes::id::TestInterfaceIterableSingle },
2103 : { PrototypeTraits<prototypes::id::TestInterfaceIterableSingle>::Depth },
2104 : JSJitInfo::Getter,
2105 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
2106 : JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
2107 : true, /* isInfallible. False in setters. */
2108 : false, /* isMovable. Not relevant for setters. */
2109 : false, /* isEliminatable. Not relevant for setters. */
2110 : false, /* isAlwaysInSlot. Only relevant for getters. */
2111 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
2112 : false, /* isTypedMethod. Only relevant for methods. */
2113 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
2114 : };
2115 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
2116 : static_assert(0 < 1, "There is no slot for us");
2117 :
2118 : static void
2119 0 : _objectMoved(JSObject* obj, const JSObject* old)
2120 : {
2121 0 : mozilla::dom::TestInterfaceIterableSingle* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableSingle>(obj);
2122 0 : if (self) {
2123 0 : UpdateWrapper(self, self, obj, old);
2124 : }
2125 0 : }
2126 :
2127 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
2128 : #if defined(__clang__)
2129 : #pragma clang diagnostic push
2130 : #pragma clang diagnostic ignored "-Wmissing-braces"
2131 : #endif
2132 : static const JSFunctionSpec sMethods_specs[] = {
2133 : JS_SYM_FNSPEC(iterator, nullptr, nullptr, 0, 0, "ArrayValues"),
2134 : JS_FNSPEC("keys", nullptr, nullptr, 0, JSPROP_ENUMERATE, "ArrayKeys"),
2135 : JS_FNSPEC("values", nullptr, nullptr, 0, JSPROP_ENUMERATE, "ArrayValues"),
2136 : JS_FNSPEC("entries", nullptr, nullptr, 0, JSPROP_ENUMERATE, "ArrayEntries"),
2137 : JS_FNSPEC("forEach", nullptr, nullptr, 1, JSPROP_ENUMERATE, "ArrayForEach"),
2138 : JS_FS_END
2139 : };
2140 : #if defined(__clang__)
2141 : #pragma clang diagnostic pop
2142 : #endif
2143 :
2144 :
2145 : // Can't be const because the pref-enabled boolean needs to be writable
2146 : static Prefable<const JSFunctionSpec> sMethods[] = {
2147 : { nullptr, &sMethods_specs[0] },
2148 : { nullptr, nullptr }
2149 : };
2150 :
2151 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
2152 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
2153 : static_assert(5 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
2154 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
2155 :
2156 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
2157 : #if defined(__clang__)
2158 : #pragma clang diagnostic push
2159 : #pragma clang diagnostic ignored "-Wmissing-braces"
2160 : #endif
2161 : static const JSPropertySpec sAttributes_specs[] = {
2162 : { "length", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &length_getterinfo, nullptr, nullptr },
2163 : { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
2164 : };
2165 : #if defined(__clang__)
2166 : #pragma clang diagnostic pop
2167 : #endif
2168 :
2169 :
2170 : // Can't be const because the pref-enabled boolean needs to be writable
2171 : static Prefable<const JSPropertySpec> sAttributes[] = {
2172 : { nullptr, &sAttributes_specs[0] },
2173 : { nullptr, nullptr }
2174 : };
2175 :
2176 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
2177 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
2178 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
2179 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
2180 :
2181 :
2182 : static uint16_t sNativeProperties_sortedPropertyIndices[6];
2183 : static PropertyInfo sNativeProperties_propertyInfos[6];
2184 :
2185 : static const NativePropertiesN<2> sNativeProperties = {
2186 : false, 0,
2187 : false, 0,
2188 : true, 0 /* sMethods */,
2189 : true, 1 /* sAttributes */,
2190 : false, 0,
2191 : false, 0,
2192 : false, 0,
2193 : -1,
2194 : 6,
2195 : sNativeProperties_sortedPropertyIndices,
2196 : {
2197 : { sMethods, &sNativeProperties_propertyInfos[0] },
2198 : { sAttributes, &sNativeProperties_propertyInfos[5] }
2199 : }
2200 : };
2201 : static_assert(6 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
2202 : "We have a property info count that is oversized");
2203 :
2204 : static bool
2205 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
2206 : {
2207 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
2208 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
2209 0 : if (!args.isConstructing()) {
2210 : // XXXbz wish I could get the name from the callee instead of
2211 : // Adding more relocations
2212 0 : return ThrowConstructorWithoutNew(cx, "TestInterfaceIterableSingle");
2213 : }
2214 :
2215 0 : GlobalObject global(cx, obj);
2216 0 : if (global.Failed()) {
2217 0 : return false;
2218 : }
2219 :
2220 0 : JS::Rooted<JSObject*> desiredProto(cx);
2221 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
2222 0 : return false;
2223 : }
2224 :
2225 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
2226 0 : Maybe<JSAutoCompartment> ac;
2227 0 : if (objIsXray) {
2228 0 : obj = js::CheckedUnwrap(obj);
2229 0 : if (!obj) {
2230 0 : return false;
2231 : }
2232 0 : ac.emplace(cx, obj);
2233 0 : if (!JS_WrapObject(cx, &desiredProto)) {
2234 0 : return false;
2235 : }
2236 : }
2237 0 : binding_detail::FastErrorResult rv;
2238 0 : auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceIterableSingle>(mozilla::dom::TestInterfaceIterableSingle::Constructor(global, rv)));
2239 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
2240 0 : return false;
2241 : }
2242 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
2243 : static_assert(!IsPointer<decltype(result)>::value,
2244 : "NewObject implies that we need to keep the object alive with a strong reference.");
2245 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
2246 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
2247 0 : return false;
2248 : }
2249 0 : return true;
2250 : }
2251 :
2252 : static const js::ClassOps sInterfaceObjectClassOps = {
2253 : nullptr, /* addProperty */
2254 : nullptr, /* delProperty */
2255 : nullptr, /* getProperty */
2256 : nullptr, /* setProperty */
2257 : nullptr, /* enumerate */
2258 : nullptr, /* newEnumerate */
2259 : nullptr, /* resolve */
2260 : nullptr, /* mayResolve */
2261 : nullptr, /* finalize */
2262 : _constructor, /* call */
2263 : nullptr, /* hasInstance */
2264 : _constructor, /* construct */
2265 : nullptr, /* trace */
2266 : };
2267 :
2268 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
2269 : {
2270 : "Function",
2271 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
2272 : &sInterfaceObjectClassOps,
2273 : JS_NULL_CLASS_SPEC,
2274 : JS_NULL_CLASS_EXT,
2275 : &sInterfaceObjectClassObjectOps
2276 : },
2277 : eInterface,
2278 : true,
2279 : prototypes::id::TestInterfaceIterableSingle,
2280 : PrototypeTraits<prototypes::id::TestInterfaceIterableSingle>::Depth,
2281 : sNativePropertyHooks,
2282 : "function TestInterfaceIterableSingle() {\n [native code]\n}",
2283 : JS::GetRealmFunctionPrototype
2284 : };
2285 :
2286 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
2287 : {
2288 : "TestInterfaceIterableSinglePrototype",
2289 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
2290 : JS_NULL_CLASS_OPS,
2291 : JS_NULL_CLASS_SPEC,
2292 : JS_NULL_CLASS_EXT,
2293 : JS_NULL_OBJECT_OPS
2294 : },
2295 : eInterfacePrototype,
2296 : false,
2297 : prototypes::id::TestInterfaceIterableSingle,
2298 : PrototypeTraits<prototypes::id::TestInterfaceIterableSingle>::Depth,
2299 : sNativePropertyHooks,
2300 : "[object TestInterfaceIterableSinglePrototype]",
2301 : JS::GetRealmObjectPrototype
2302 : };
2303 :
2304 : bool
2305 0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
2306 : {
2307 : static bool sPrefValue;
2308 : static bool sPrefCacheSetUp = false;
2309 0 : if (!sPrefCacheSetUp) {
2310 0 : sPrefCacheSetUp = true;
2311 0 : Preferences::AddBoolVarCache(&sPrefValue, "dom.expose_test_interfaces");
2312 : }
2313 :
2314 0 : return sPrefValue;
2315 : }
2316 :
2317 : JSObject*
2318 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
2319 : {
2320 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
2321 : }
2322 :
2323 : static_assert(IsBaseOf<nsISupports, mozilla::dom::TestInterfaceIterableSingle >::value,
2324 : "We don't support non-nsISupports native classes for "
2325 : "proxy-based bindings yet");
2326 :
2327 :
2328 : class DOMProxyHandler : public mozilla::dom::DOMProxyHandler
2329 : {
2330 : public:
2331 : explicit constexpr DOMProxyHandler()
2332 : {
2333 : }
2334 :
2335 : virtual bool
2336 : getOwnPropDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool ignoreNamedProps, JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
2337 :
2338 : virtual bool
2339 : defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& opresult, bool* defined) const override;
2340 :
2341 : using mozilla::dom::DOMProxyHandler::defineProperty;
2342 :
2343 : virtual bool
2344 : ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy, unsigned flags, JS::AutoIdVector& props) const override;
2345 :
2346 : virtual bool
2347 : hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) const override;
2348 :
2349 : virtual bool
2350 : get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JS::Value> receiver, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
2351 :
2352 : virtual const char*
2353 : className(JSContext* cx, JS::Handle<JSObject*> proxy) const override;
2354 :
2355 : virtual bool
2356 : finalizeInBackground(const JS::Value& priv) const override;
2357 :
2358 : virtual void
2359 : finalize(JSFreeOp* fop, JSObject* proxy) const override;
2360 :
2361 : static const DOMProxyHandler*
2362 : getInstance();
2363 :
2364 : virtual bool
2365 : delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::ObjectOpResult& opresult) const override;
2366 :
2367 : virtual bool
2368 : getElements(JSContext* cx, JS::Handle<JSObject*> proxy, uint32_t begin, uint32_t end, js::ElementAdder* adder) const override;
2369 : };
2370 :
2371 : MOZ_ALWAYS_INLINE bool
2372 0 : IsProxy(JSObject* obj)
2373 : {
2374 0 : return js::IsProxy(obj) && js::GetProxyHandler(obj) == DOMProxyHandler::getInstance();
2375 : }
2376 :
2377 : MOZ_ALWAYS_INLINE mozilla::dom::TestInterfaceIterableSingle*
2378 0 : UnwrapProxy(JSObject* obj)
2379 : {
2380 0 : MOZ_ASSERT(js::IsProxy(obj));
2381 0 : if (js::GetProxyHandler(obj) != DOMProxyHandler::getInstance()) {
2382 0 : MOZ_ASSERT(xpc::WrapperFactory::IsXrayWrapper(obj));
2383 0 : obj = js::UncheckedUnwrap(obj);
2384 : }
2385 0 : MOZ_ASSERT(IsProxy(obj));
2386 0 : return static_cast<mozilla::dom::TestInterfaceIterableSingle*>(js::GetProxyReservedSlot(obj, DOM_OBJECT_SLOT).toPrivate());
2387 : }
2388 :
2389 : bool
2390 0 : DOMProxyHandler::getOwnPropDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool ignoreNamedProps, JS::MutableHandle<JS::PropertyDescriptor> desc) const
2391 : {
2392 0 : bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
2393 0 : uint32_t index = GetArrayIndexFromId(cx, id);
2394 0 : if (IsArrayIndex(index)) {
2395 0 : mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
2396 0 : bool found = false;
2397 0 : int32_t result(self->IndexedGetter(index, found));
2398 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
2399 :
2400 0 : if (found) {
2401 0 : desc.value().setInt32(int32_t(result));
2402 0 : FillPropertyDescriptor(desc, proxy, true);
2403 0 : return true;
2404 : }
2405 : }
2406 :
2407 0 : JS::Rooted<JSObject*> expando(cx);
2408 0 : if (!isXray && (expando = GetExpandoObject(proxy))) {
2409 0 : if (!JS_GetOwnPropertyDescriptorById(cx, expando, id, desc)) {
2410 0 : return false;
2411 : }
2412 0 : if (desc.object()) {
2413 : // Pretend the property lives on the wrapper.
2414 0 : desc.object().set(proxy);
2415 0 : return true;
2416 : }
2417 : }
2418 :
2419 0 : desc.object().set(nullptr);
2420 0 : return true;
2421 : }
2422 :
2423 : bool
2424 0 : DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& opresult, bool* defined) const
2425 : {
2426 0 : if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
2427 0 : *defined = true;
2428 0 : return opresult.failNoIndexedSetter();
2429 : }
2430 0 : return mozilla::dom::DOMProxyHandler::defineProperty(cx, proxy, id, desc, opresult, defined);
2431 : }
2432 :
2433 :
2434 : bool
2435 0 : DOMProxyHandler::ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy, unsigned flags, JS::AutoIdVector& props) const
2436 : {
2437 0 : bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
2438 :
2439 0 : uint32_t length = UnwrapProxy(proxy)->Length();
2440 0 : MOZ_ASSERT(int32_t(length) >= 0);
2441 0 : for (int32_t i = 0; i < int32_t(length); ++i) {
2442 0 : if (!props.append(INT_TO_JSID(i))) {
2443 0 : return false;
2444 : }
2445 : }
2446 :
2447 0 : JS::Rooted<JSObject*> expando(cx);
2448 0 : if (!isXray && (expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
2449 0 : !js::GetPropertyKeys(cx, expando, flags, &props)) {
2450 0 : return false;
2451 : }
2452 :
2453 0 : return true;
2454 : }
2455 :
2456 : bool
2457 0 : DOMProxyHandler::hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) const
2458 : {
2459 0 : MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
2460 : "Should not have a XrayWrapper here");
2461 :
2462 0 : uint32_t index = GetArrayIndexFromId(cx, id);
2463 0 : if (IsArrayIndex(index)) {
2464 0 : bool found = false;
2465 0 : mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
2466 0 : int32_t result(self->IndexedGetter(index, found));
2467 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
2468 : (void)result;
2469 :
2470 0 : *bp = found;
2471 0 : return true;
2472 : }
2473 :
2474 :
2475 0 : JS::Rooted<JSObject*> expando(cx, GetExpandoObject(proxy));
2476 0 : if (expando) {
2477 0 : bool b = true;
2478 0 : bool ok = JS_HasPropertyById(cx, expando, id, &b);
2479 0 : *bp = !!b;
2480 0 : if (!ok || *bp) {
2481 0 : return ok;
2482 : }
2483 : }
2484 :
2485 0 : *bp = false;
2486 0 : return true;
2487 : }
2488 :
2489 : bool
2490 0 : DOMProxyHandler::get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JS::Value> receiver, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const
2491 : {
2492 0 : MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
2493 : "Should not have a XrayWrapper here");
2494 :
2495 0 : uint32_t index = GetArrayIndexFromId(cx, id);
2496 0 : if (IsArrayIndex(index)) {
2497 0 : mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
2498 0 : bool found = false;
2499 0 : int32_t result(self->IndexedGetter(index, found));
2500 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
2501 :
2502 0 : if (found) {
2503 0 : vp.setInt32(int32_t(result));
2504 0 : return true;
2505 : }
2506 : // Even if we don't have this index, we don't forward the
2507 : // get on to our expando object.
2508 : } else {
2509 : { // Scope for expando
2510 0 : JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
2511 0 : if (expando) {
2512 : bool hasProp;
2513 0 : if (!JS_HasPropertyById(cx, expando, id, &hasProp)) {
2514 0 : return false;
2515 : }
2516 :
2517 0 : if (hasProp) {
2518 : // Forward the get to the expando object, but our receiver is whatever our
2519 : // receiver is.
2520 0 : return JS_ForwardGetPropertyTo(cx, expando, id, receiver, vp);
2521 : }
2522 : }
2523 : }
2524 : }
2525 :
2526 : bool foundOnPrototype;
2527 0 : if (!GetPropertyOnPrototype(cx, proxy, receiver, id, &foundOnPrototype, vp)) {
2528 0 : return false;
2529 : }
2530 :
2531 0 : if (foundOnPrototype) {
2532 0 : return true;
2533 : }
2534 :
2535 0 : vp.setUndefined();
2536 0 : return true;
2537 : }
2538 :
2539 : const char*
2540 0 : DOMProxyHandler::className(JSContext* cx, JS::Handle<JSObject*> proxy) const
2541 : {
2542 0 : return "TestInterfaceIterableSingle";
2543 : }
2544 :
2545 : bool
2546 0 : DOMProxyHandler::finalizeInBackground(const JS::Value& priv) const
2547 : {
2548 0 : return false;
2549 : }
2550 :
2551 : void
2552 0 : DOMProxyHandler::finalize(JSFreeOp* fop, JSObject* proxy) const
2553 : {
2554 0 : mozilla::dom::TestInterfaceIterableSingle* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableSingle>(proxy);
2555 0 : if (self) {
2556 0 : ClearWrapper(self, self, proxy);
2557 0 : AddForDeferredFinalization<mozilla::dom::TestInterfaceIterableSingle>(self);
2558 : }
2559 0 : }
2560 :
2561 : const DOMProxyHandler*
2562 0 : DOMProxyHandler::getInstance()
2563 : {
2564 : static const DOMProxyHandler instance;
2565 0 : return &instance;
2566 : }
2567 :
2568 : bool
2569 0 : DOMProxyHandler::delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::ObjectOpResult& opresult) const
2570 : {
2571 0 : MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
2572 : "Should not have a XrayWrapper here");
2573 :
2574 0 : uint32_t index = GetArrayIndexFromId(cx, id);
2575 0 : if (IsArrayIndex(index)) {
2576 : bool deleteSucceeded;
2577 0 : bool found = false;
2578 0 : mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
2579 0 : int32_t result(self->IndexedGetter(index, found));
2580 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
2581 : (void)result;
2582 0 : deleteSucceeded = !found;
2583 0 : return deleteSucceeded ? opresult.succeed() : opresult.failCantDelete();
2584 : }
2585 :
2586 0 : return dom::DOMProxyHandler::delete_(cx, proxy, id, opresult);
2587 : }
2588 :
2589 : bool
2590 0 : DOMProxyHandler::getElements(JSContext* cx, JS::Handle<JSObject*> proxy, uint32_t begin, uint32_t end, js::ElementAdder* adder) const
2591 : {
2592 0 : JS::Rooted<JS::Value> temp(cx);
2593 0 : MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
2594 : "Should not have a XrayWrapper here");
2595 :
2596 0 : mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
2597 0 : uint32_t length = self->Length();
2598 : // Compute the end of the indices we'll get ourselves
2599 0 : uint32_t ourEnd = std::max(begin, std::min(end, length));
2600 :
2601 0 : for (uint32_t index = begin; index < ourEnd; ++index) {
2602 0 : bool found = false;
2603 0 : int32_t result(self->IndexedGetter(index, found));
2604 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
2605 :
2606 0 : MOZ_ASSERT(found);
2607 0 : temp.setInt32(int32_t(result));
2608 0 : if (!adder->append(cx, temp)) return false;
2609 0 : continue;
2610 : }
2611 :
2612 0 : if (end > ourEnd) {
2613 0 : JS::Rooted<JSObject*> proto(cx);
2614 0 : if (!js::GetObjectProto(cx, proxy, &proto)) {
2615 0 : return false;
2616 : }
2617 0 : return js::GetElementsWithAdder(cx, proto, proxy, ourEnd, end, adder);
2618 : }
2619 :
2620 0 : return true;
2621 : }
2622 :
2623 : static const js::ClassExtension sClassExtension = PROXY_MAKE_EXT(
2624 : _objectMoved
2625 : );
2626 :
2627 : static const DOMJSClass sClass = {
2628 : PROXY_CLASS_WITH_EXT("TestInterfaceIterableSingle",
2629 : JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1),
2630 : &sClassExtension),
2631 : { prototypes::id::TestInterfaceIterableSingle, 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 },
2632 : IsBaseOf<nsISupports, mozilla::dom::TestInterfaceIterableSingle >::value,
2633 : sNativePropertyHooks,
2634 : FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceIterableSingle>::Get,
2635 : GetProtoObjectHandle,
2636 : GetCCParticipant<mozilla::dom::TestInterfaceIterableSingle>::Get()
2637 : };
2638 :
2639 : bool
2640 0 : Wrap(JSContext* aCx, mozilla::dom::TestInterfaceIterableSingle* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
2641 : {
2642 : MOZ_ASSERT(static_cast<mozilla::dom::TestInterfaceIterableSingle*>(aObject) ==
2643 : reinterpret_cast<mozilla::dom::TestInterfaceIterableSingle*>(aObject),
2644 : "Multiple inheritance for mozilla::dom::TestInterfaceIterableSingle is broken.");
2645 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
2646 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
2647 0 : MOZ_ASSERT(!aCache->GetWrapper(),
2648 : "You should probably not be using Wrap() directly; use "
2649 : "GetOrCreateDOMReflector instead");
2650 :
2651 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
2652 : "nsISupports must be on our primary inheritance chain");
2653 :
2654 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
2655 0 : if (!global) {
2656 0 : return false;
2657 : }
2658 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
2659 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
2660 :
2661 : // That might have ended up wrapping us already, due to the wonders
2662 : // of XBL. Check for that, and bail out as needed.
2663 0 : aReflector.set(aCache->GetWrapper());
2664 0 : if (aReflector) {
2665 : #ifdef DEBUG
2666 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
2667 : #endif // DEBUG
2668 0 : return true;
2669 : }
2670 :
2671 0 : JSAutoCompartment ac(aCx, global);
2672 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
2673 0 : if (!canonicalProto) {
2674 0 : return false;
2675 : }
2676 0 : JS::Rooted<JSObject*> proto(aCx);
2677 0 : if (aGivenProto) {
2678 0 : proto = aGivenProto;
2679 : // Unfortunately, while aGivenProto was in the compartment of aCx
2680 : // coming in, we changed compartments to that of "parent" so may need
2681 : // to wrap the proto here.
2682 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
2683 0 : if (!JS_WrapObject(aCx, &proto)) {
2684 0 : return false;
2685 : }
2686 : }
2687 : } else {
2688 0 : proto = canonicalProto;
2689 : }
2690 :
2691 0 : BindingJSObjectCreator<mozilla::dom::TestInterfaceIterableSingle> creator(aCx);
2692 0 : JS::Rooted<JS::Value> expandoValue(aCx, JS::UndefinedValue());
2693 0 : creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
2694 0 : proto, aObject, expandoValue, aReflector);
2695 0 : if (!aReflector) {
2696 0 : return false;
2697 : }
2698 :
2699 :
2700 0 : aCache->SetWrapper(aReflector);
2701 0 : creator.InitializationSucceeded();
2702 :
2703 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
2704 : aCache->GetWrapperPreserveColor() == aReflector);
2705 : // If proto != canonicalProto, we have to preserve our wrapper;
2706 : // otherwise we won't be able to properly recreate it later, since
2707 : // we won't know what proto to use. Note that we don't check
2708 : // aGivenProto here, since it's entirely possible (and even
2709 : // somewhat common) to have a non-null aGivenProto which is the
2710 : // same as canonicalProto.
2711 0 : if (proto != canonicalProto) {
2712 0 : PreserveWrapper(aObject);
2713 : }
2714 :
2715 0 : return true;
2716 : }
2717 :
2718 : static bool
2719 0 : ResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<JS::PropertyDescriptor> desc)
2720 : {
2721 0 : return js::GetProxyHandler(obj)->getOwnPropertyDescriptor(cx, wrapper, id, desc);
2722 : }
2723 :
2724 : static bool
2725 0 : EnumerateOwnProperties(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> obj, JS::AutoIdVector& props)
2726 : {
2727 0 : return js::GetProxyHandler(obj)->ownPropertyKeys(cx, wrapper, props);
2728 : }
2729 :
2730 : const NativePropertyHooks sNativePropertyHooks[] = { {
2731 : ResolveOwnProperty,
2732 : EnumerateOwnProperties,
2733 : nullptr,
2734 : { sNativeProperties.Upcast(), nullptr },
2735 : prototypes::id::TestInterfaceIterableSingle,
2736 : constructors::id::TestInterfaceIterableSingle,
2737 : nullptr,
2738 : &DefaultXrayExpandoObjectClass
2739 : } };
2740 :
2741 : void
2742 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
2743 : {
2744 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
2745 0 : if (!parentProto) {
2746 0 : return;
2747 : }
2748 :
2749 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
2750 0 : if (!constructorProto) {
2751 0 : return;
2752 : }
2753 :
2754 : static bool sIdsInited = false;
2755 0 : if (!sIdsInited && NS_IsMainThread()) {
2756 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
2757 0 : return;
2758 : }
2759 0 : sIdsInited = true;
2760 : }
2761 :
2762 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableSingle);
2763 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceIterableSingle);
2764 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
2765 : &sPrototypeClass.mBase, protoCache,
2766 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
2767 : interfaceCache,
2768 : sNativeProperties.Upcast(),
2769 : nullptr,
2770 : "TestInterfaceIterableSingle", aDefineOnGlobal,
2771 : nullptr,
2772 0 : false);
2773 : }
2774 :
2775 : JS::Handle<JSObject*>
2776 0 : GetProtoObjectHandle(JSContext* aCx)
2777 : {
2778 : /* Get the interface prototype object for this class. This will create the
2779 : object as needed. */
2780 0 : bool aDefineOnGlobal = true;
2781 :
2782 : /* Make sure our global is sane. Hopefully we can remove this sometime */
2783 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
2784 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
2785 0 : return nullptr;
2786 : }
2787 :
2788 : /* Check to see whether the interface objects are already installed */
2789 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
2790 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceIterableSingle)) {
2791 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
2792 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
2793 : }
2794 :
2795 : /*
2796 : * The object might _still_ be null, but that's OK.
2797 : *
2798 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
2799 : * traced by TraceProtoAndIfaceCache() and its contents are never
2800 : * changed after they have been set.
2801 : *
2802 : * Calling address() avoids the read read barrier that does gray
2803 : * unmarking, but it's not possible for the object to be gray here.
2804 : */
2805 :
2806 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceIterableSingle);
2807 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
2808 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
2809 : }
2810 :
2811 : JS::Handle<JSObject*>
2812 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
2813 : {
2814 : /* Get the interface object for this class. This will create the object as
2815 : needed. */
2816 :
2817 : /* Make sure our global is sane. Hopefully we can remove this sometime */
2818 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
2819 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
2820 0 : return nullptr;
2821 : }
2822 :
2823 : /* Check to see whether the interface objects are already installed */
2824 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
2825 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::TestInterfaceIterableSingle)) {
2826 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
2827 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
2828 : }
2829 :
2830 : /*
2831 : * The object might _still_ be null, but that's OK.
2832 : *
2833 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
2834 : * traced by TraceProtoAndIfaceCache() and its contents are never
2835 : * changed after they have been set.
2836 : *
2837 : * Calling address() avoids the read read barrier that does gray
2838 : * unmarking, but it's not possible for the object to be gray here.
2839 : */
2840 :
2841 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::TestInterfaceIterableSingle);
2842 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
2843 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
2844 : }
2845 :
2846 : JSObject*
2847 0 : GetConstructorObject(JSContext* aCx)
2848 : {
2849 0 : return GetConstructorObjectHandle(aCx);
2850 : }
2851 :
2852 : } // namespace TestInterfaceIterableSingleBinding
2853 :
2854 :
2855 :
2856 : namespace TestInterfaceJSMaplikeBinding {
2857 :
2858 : namespace MaplikeHelpers {
2859 : void
2860 0 : Clear(mozilla::dom::TestInterfaceJSMaplike* self, ErrorResult& aRv)
2861 : {
2862 0 : MOZ_ASSERT(self);
2863 0 : AutoJSAPI jsapi;
2864 0 : jsapi.Init();
2865 0 : JSContext* cx = jsapi.cx();
2866 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
2867 : // all we want is to wrap into _some_ scope and then unwrap to find
2868 : // the reflector, and wrapping has no side-effects.
2869 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
2870 0 : JS::Rooted<JS::Value> v(cx);
2871 0 : if(!ToJSValue(cx, self, &v)) {
2872 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2873 0 : return;
2874 : }
2875 : // This is a reflector, but due to trying to name things
2876 : // similarly across method generators, it's called obj here.
2877 0 : JS::Rooted<JSObject*> obj(cx);
2878 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
2879 0 : JSAutoCompartment reflectorCompartment(cx, obj);
2880 :
2881 0 : JS::Rooted<JSObject*> backingObj(cx);
2882 0 : bool created = false;
2883 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
2884 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2885 0 : return;
2886 : }
2887 0 : if (created) {
2888 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
2889 : }
2890 0 : if (!JS::MapClear(cx, backingObj)) {
2891 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2892 0 : return;
2893 : }
2894 0 : return;
2895 : }
2896 : bool
2897 0 : Delete(mozilla::dom::TestInterfaceJSMaplike* self, const nsAString& aKey, ErrorResult& aRv)
2898 : {
2899 0 : MOZ_ASSERT(self);
2900 0 : AutoJSAPI jsapi;
2901 0 : jsapi.Init();
2902 0 : JSContext* cx = jsapi.cx();
2903 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
2904 : // all we want is to wrap into _some_ scope and then unwrap to find
2905 : // the reflector, and wrapping has no side-effects.
2906 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
2907 0 : JS::Rooted<JS::Value> v(cx);
2908 0 : if(!ToJSValue(cx, self, &v)) {
2909 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2910 0 : return false;
2911 : }
2912 : // This is a reflector, but due to trying to name things
2913 : // similarly across method generators, it's called obj here.
2914 0 : JS::Rooted<JSObject*> obj(cx);
2915 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
2916 0 : JSAutoCompartment reflectorCompartment(cx, obj);
2917 : bool aRetVal;
2918 0 : JS::AutoValueVector argv(cx);
2919 0 : if (!argv.resize(1)) {
2920 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
2921 0 : return false;
2922 : }
2923 : do {
2924 0 : nsString mutableStr(aKey);
2925 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
2926 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2927 0 : return false;
2928 : }
2929 0 : break;
2930 : } while (0);
2931 :
2932 0 : JS::Rooted<JSObject*> backingObj(cx);
2933 0 : bool created = false;
2934 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
2935 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2936 0 : return false;
2937 : }
2938 0 : if (created) {
2939 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
2940 : }
2941 0 : if (!JS::MapDelete(cx, backingObj, argv[0], &aRetVal)) {
2942 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2943 0 : return false;
2944 : }
2945 0 : return aRetVal;
2946 : }
2947 : bool
2948 0 : Has(mozilla::dom::TestInterfaceJSMaplike* self, const nsAString& aKey, ErrorResult& aRv)
2949 : {
2950 0 : MOZ_ASSERT(self);
2951 0 : AutoJSAPI jsapi;
2952 0 : jsapi.Init();
2953 0 : JSContext* cx = jsapi.cx();
2954 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
2955 : // all we want is to wrap into _some_ scope and then unwrap to find
2956 : // the reflector, and wrapping has no side-effects.
2957 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
2958 0 : JS::Rooted<JS::Value> v(cx);
2959 0 : if(!ToJSValue(cx, self, &v)) {
2960 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2961 0 : return false;
2962 : }
2963 : // This is a reflector, but due to trying to name things
2964 : // similarly across method generators, it's called obj here.
2965 0 : JS::Rooted<JSObject*> obj(cx);
2966 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
2967 0 : JSAutoCompartment reflectorCompartment(cx, obj);
2968 : bool aRetVal;
2969 0 : JS::AutoValueVector argv(cx);
2970 0 : if (!argv.resize(1)) {
2971 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
2972 0 : return false;
2973 : }
2974 : do {
2975 0 : nsString mutableStr(aKey);
2976 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
2977 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2978 0 : return false;
2979 : }
2980 0 : break;
2981 : } while (0);
2982 :
2983 0 : JS::Rooted<JSObject*> backingObj(cx);
2984 0 : bool created = false;
2985 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
2986 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2987 0 : return false;
2988 : }
2989 0 : if (created) {
2990 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
2991 : }
2992 0 : if (!JS::MapHas(cx, backingObj, argv[0], &aRetVal)) {
2993 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
2994 0 : return false;
2995 : }
2996 0 : return aRetVal;
2997 : }
2998 : void
2999 0 : Set(mozilla::dom::TestInterfaceJSMaplike* self, const nsAString& aKey, int32_t aValue, ErrorResult& aRv)
3000 : {
3001 0 : MOZ_ASSERT(self);
3002 0 : AutoJSAPI jsapi;
3003 0 : jsapi.Init();
3004 0 : JSContext* cx = jsapi.cx();
3005 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
3006 : // all we want is to wrap into _some_ scope and then unwrap to find
3007 : // the reflector, and wrapping has no side-effects.
3008 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
3009 0 : JS::Rooted<JS::Value> v(cx);
3010 0 : if(!ToJSValue(cx, self, &v)) {
3011 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
3012 0 : return;
3013 : }
3014 : // This is a reflector, but due to trying to name things
3015 : // similarly across method generators, it's called obj here.
3016 0 : JS::Rooted<JSObject*> obj(cx);
3017 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
3018 0 : JSAutoCompartment reflectorCompartment(cx, obj);
3019 0 : JS::AutoValueVector argv(cx);
3020 0 : if (!argv.resize(2)) {
3021 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
3022 0 : return;
3023 : }
3024 : do {
3025 0 : argv[1].setInt32(int32_t(aValue));
3026 0 : break;
3027 : } while (0);
3028 :
3029 : do {
3030 0 : nsString mutableStr(aKey);
3031 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
3032 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
3033 0 : return;
3034 : }
3035 0 : break;
3036 : } while (0);
3037 :
3038 0 : JS::Rooted<JSObject*> backingObj(cx);
3039 0 : bool created = false;
3040 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3041 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
3042 0 : return;
3043 : }
3044 0 : if (created) {
3045 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3046 : }
3047 0 : if (!JS::MapSet(cx, backingObj, argv[0], argv[1])) {
3048 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
3049 0 : return;
3050 : }
3051 0 : return;
3052 : }
3053 : } // namespace MaplikeHelpers
3054 :
3055 : static bool
3056 0 : setInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3057 : {
3058 0 : if (MOZ_UNLIKELY(args.length() < 2)) {
3059 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "TestInterfaceJSMaplike.setInternal");
3060 : }
3061 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3062 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3063 0 : if (objIsXray) {
3064 0 : unwrappedObj.emplace(cx, obj);
3065 : }
3066 0 : binding_detail::FakeString arg0;
3067 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
3068 0 : return false;
3069 : }
3070 : int32_t arg1;
3071 0 : if (!ValueToPrimitive<int32_t, eDefault>(cx, args[1], &arg1)) {
3072 0 : return false;
3073 : }
3074 0 : if (objIsXray) {
3075 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3076 0 : if (!unwrappedObj.ref()) {
3077 0 : return false;
3078 : }
3079 : }
3080 0 : binding_detail::FastErrorResult rv;
3081 0 : self->SetInternal(NonNullHelper(Constify(arg0)), arg1, rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj));
3082 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
3083 0 : return false;
3084 : }
3085 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
3086 0 : args.rval().setUndefined();
3087 0 : return true;
3088 : }
3089 :
3090 : static const JSJitInfo setInternal_methodinfo = {
3091 : { (JSJitGetterOp)setInternal },
3092 : { prototypes::id::TestInterfaceJSMaplike },
3093 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3094 : JSJitInfo::Method,
3095 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3096 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
3097 : false, /* isInfallible. False in setters. */
3098 : false, /* isMovable. Not relevant for setters. */
3099 : false, /* isEliminatable. Not relevant for setters. */
3100 : false, /* isAlwaysInSlot. Only relevant for getters. */
3101 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3102 : false, /* isTypedMethod. Only relevant for methods. */
3103 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3104 : };
3105 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3106 : static_assert(0 < 2, "There is no slot for us");
3107 :
3108 : static bool
3109 0 : clearInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3110 : {
3111 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3112 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3113 0 : if (objIsXray) {
3114 0 : unwrappedObj.emplace(cx, obj);
3115 : }
3116 0 : if (objIsXray) {
3117 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3118 0 : if (!unwrappedObj.ref()) {
3119 0 : return false;
3120 : }
3121 : }
3122 0 : binding_detail::FastErrorResult rv;
3123 0 : self->ClearInternal(rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj));
3124 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
3125 0 : return false;
3126 : }
3127 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
3128 0 : args.rval().setUndefined();
3129 0 : return true;
3130 : }
3131 :
3132 : static const JSJitInfo clearInternal_methodinfo = {
3133 : { (JSJitGetterOp)clearInternal },
3134 : { prototypes::id::TestInterfaceJSMaplike },
3135 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3136 : JSJitInfo::Method,
3137 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3138 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
3139 : false, /* isInfallible. False in setters. */
3140 : false, /* isMovable. Not relevant for setters. */
3141 : false, /* isEliminatable. Not relevant for setters. */
3142 : false, /* isAlwaysInSlot. Only relevant for getters. */
3143 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3144 : false, /* isTypedMethod. Only relevant for methods. */
3145 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3146 : };
3147 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3148 : static_assert(0 < 2, "There is no slot for us");
3149 :
3150 : static bool
3151 0 : deleteInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3152 : {
3153 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
3154 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "TestInterfaceJSMaplike.deleteInternal");
3155 : }
3156 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3157 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3158 0 : if (objIsXray) {
3159 0 : unwrappedObj.emplace(cx, obj);
3160 : }
3161 0 : binding_detail::FakeString arg0;
3162 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
3163 0 : return false;
3164 : }
3165 0 : if (objIsXray) {
3166 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3167 0 : if (!unwrappedObj.ref()) {
3168 0 : return false;
3169 : }
3170 : }
3171 0 : binding_detail::FastErrorResult rv;
3172 0 : bool result(self->DeleteInternal(NonNullHelper(Constify(arg0)), rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj)));
3173 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
3174 0 : return false;
3175 : }
3176 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
3177 0 : args.rval().setBoolean(result);
3178 0 : return true;
3179 : }
3180 :
3181 : static const JSJitInfo deleteInternal_methodinfo = {
3182 : { (JSJitGetterOp)deleteInternal },
3183 : { prototypes::id::TestInterfaceJSMaplike },
3184 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3185 : JSJitInfo::Method,
3186 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3187 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
3188 : false, /* isInfallible. False in setters. */
3189 : false, /* isMovable. Not relevant for setters. */
3190 : false, /* isEliminatable. Not relevant for setters. */
3191 : false, /* isAlwaysInSlot. Only relevant for getters. */
3192 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3193 : false, /* isTypedMethod. Only relevant for methods. */
3194 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3195 : };
3196 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3197 : static_assert(0 < 2, "There is no slot for us");
3198 :
3199 : static bool
3200 0 : get_size(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, JSJitGetterCallArgs args)
3201 : {
3202 0 : JS::Rooted<JSObject*> backingObj(cx);
3203 0 : bool created = false;
3204 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3205 0 : return false;
3206 : }
3207 0 : if (created) {
3208 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3209 : }
3210 0 : uint32_t result = JS::MapSize(cx, backingObj);
3211 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
3212 0 : args.rval().setNumber(result);
3213 0 : return true;
3214 : }
3215 :
3216 : static const JSJitInfo size_getterinfo = {
3217 : { (JSJitGetterOp)get_size },
3218 : { prototypes::id::TestInterfaceJSMaplike },
3219 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3220 : JSJitInfo::Getter,
3221 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3222 : JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
3223 : false, /* isInfallible. False in setters. */
3224 : false, /* isMovable. Not relevant for setters. */
3225 : false, /* isEliminatable. Not relevant for setters. */
3226 : false, /* isAlwaysInSlot. Only relevant for getters. */
3227 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3228 : false, /* isTypedMethod. Only relevant for methods. */
3229 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3230 : };
3231 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3232 : static_assert(0 < 2, "There is no slot for us");
3233 :
3234 : static bool
3235 0 : entries(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3236 : {
3237 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3238 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3239 0 : if (objIsXray) {
3240 0 : unwrappedObj.emplace(cx, obj);
3241 : }
3242 0 : if (objIsXray) {
3243 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3244 0 : if (!unwrappedObj.ref()) {
3245 0 : return false;
3246 : }
3247 : }
3248 0 : JS::Rooted<JSObject*> backingObj(cx);
3249 0 : bool created = false;
3250 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3251 0 : return false;
3252 : }
3253 0 : if (created) {
3254 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3255 : }
3256 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
3257 : // after bug 1023984 is fixed.
3258 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
3259 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
3260 0 : return false;
3261 : }
3262 0 : JS::Rooted<JSObject*> result(cx);
3263 0 : JS::Rooted<JS::Value> v(cx);
3264 0 : if (!JS::MapEntries(cx, backingObj, &v)) {
3265 0 : return false;
3266 : }
3267 0 : result = &v.toObject();
3268 0 : JS::ExposeObjectToActiveJS(result);
3269 0 : args.rval().setObject(*result);
3270 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
3271 0 : return false;
3272 : }
3273 0 : return true;
3274 : }
3275 :
3276 : static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
3277 : static const JSTypedMethodJitInfo entries_methodinfo = {
3278 : {
3279 : { (JSJitGetterOp)entries },
3280 : { prototypes::id::TestInterfaceJSMaplike },
3281 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3282 : JSJitInfo::Method,
3283 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3284 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
3285 : false, /* isInfallible. False in setters. */
3286 : false, /* isMovable. Not relevant for setters. */
3287 : false, /* isEliminatable. Not relevant for setters. */
3288 : false, /* isAlwaysInSlot. Only relevant for getters. */
3289 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3290 : true, /* isTypedMethod. Only relevant for methods. */
3291 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3292 : },
3293 : entries_methodinfo_argTypes
3294 : };
3295 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3296 : static_assert(0 < 2, "There is no slot for us");
3297 :
3298 : static bool
3299 0 : keys(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3300 : {
3301 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3302 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3303 0 : if (objIsXray) {
3304 0 : unwrappedObj.emplace(cx, obj);
3305 : }
3306 0 : if (objIsXray) {
3307 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3308 0 : if (!unwrappedObj.ref()) {
3309 0 : return false;
3310 : }
3311 : }
3312 0 : JS::Rooted<JSObject*> backingObj(cx);
3313 0 : bool created = false;
3314 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3315 0 : return false;
3316 : }
3317 0 : if (created) {
3318 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3319 : }
3320 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
3321 : // after bug 1023984 is fixed.
3322 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
3323 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
3324 0 : return false;
3325 : }
3326 0 : JS::Rooted<JSObject*> result(cx);
3327 0 : JS::Rooted<JS::Value> v(cx);
3328 0 : if (!JS::MapKeys(cx, backingObj, &v)) {
3329 0 : return false;
3330 : }
3331 0 : result = &v.toObject();
3332 0 : JS::ExposeObjectToActiveJS(result);
3333 0 : args.rval().setObject(*result);
3334 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
3335 0 : return false;
3336 : }
3337 0 : return true;
3338 : }
3339 :
3340 : static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
3341 : static const JSTypedMethodJitInfo keys_methodinfo = {
3342 : {
3343 : { (JSJitGetterOp)keys },
3344 : { prototypes::id::TestInterfaceJSMaplike },
3345 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3346 : JSJitInfo::Method,
3347 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3348 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
3349 : false, /* isInfallible. False in setters. */
3350 : false, /* isMovable. Not relevant for setters. */
3351 : false, /* isEliminatable. Not relevant for setters. */
3352 : false, /* isAlwaysInSlot. Only relevant for getters. */
3353 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3354 : true, /* isTypedMethod. Only relevant for methods. */
3355 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3356 : },
3357 : keys_methodinfo_argTypes
3358 : };
3359 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3360 : static_assert(0 < 2, "There is no slot for us");
3361 :
3362 : static bool
3363 0 : values(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3364 : {
3365 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3366 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3367 0 : if (objIsXray) {
3368 0 : unwrappedObj.emplace(cx, obj);
3369 : }
3370 0 : if (objIsXray) {
3371 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3372 0 : if (!unwrappedObj.ref()) {
3373 0 : return false;
3374 : }
3375 : }
3376 0 : JS::Rooted<JSObject*> backingObj(cx);
3377 0 : bool created = false;
3378 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3379 0 : return false;
3380 : }
3381 0 : if (created) {
3382 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3383 : }
3384 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
3385 : // after bug 1023984 is fixed.
3386 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
3387 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
3388 0 : return false;
3389 : }
3390 0 : JS::Rooted<JSObject*> result(cx);
3391 0 : JS::Rooted<JS::Value> v(cx);
3392 0 : if (!JS::MapValues(cx, backingObj, &v)) {
3393 0 : return false;
3394 : }
3395 0 : result = &v.toObject();
3396 0 : JS::ExposeObjectToActiveJS(result);
3397 0 : args.rval().setObject(*result);
3398 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
3399 0 : return false;
3400 : }
3401 0 : return true;
3402 : }
3403 :
3404 : static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
3405 : static const JSTypedMethodJitInfo values_methodinfo = {
3406 : {
3407 : { (JSJitGetterOp)values },
3408 : { prototypes::id::TestInterfaceJSMaplike },
3409 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3410 : JSJitInfo::Method,
3411 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3412 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
3413 : false, /* isInfallible. False in setters. */
3414 : false, /* isMovable. Not relevant for setters. */
3415 : false, /* isEliminatable. Not relevant for setters. */
3416 : false, /* isAlwaysInSlot. Only relevant for getters. */
3417 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3418 : true, /* isTypedMethod. Only relevant for methods. */
3419 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3420 : },
3421 : values_methodinfo_argTypes
3422 : };
3423 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3424 : static_assert(0 < 2, "There is no slot for us");
3425 :
3426 : static bool
3427 0 : forEach(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3428 : {
3429 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3430 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3431 0 : if (objIsXray) {
3432 0 : unwrappedObj.emplace(cx, obj);
3433 : }
3434 0 : JS::Rooted<JSObject*> arg0(cx);
3435 0 : if (args.get(0).isObject()) {
3436 : #ifdef __clang__
3437 : #pragma clang diagnostic push
3438 : #pragma clang diagnostic ignored "-Wunreachable-code"
3439 : #pragma clang diagnostic ignored "-Wunreachable-code-return"
3440 : #endif // __clang__
3441 0 : if ((true) && !CallerSubsumes(args.get(0))) {
3442 0 : ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "argument 1 of TestInterfaceJSMaplike.forEach");
3443 0 : return false;
3444 : }
3445 : #ifdef __clang__
3446 : #pragma clang diagnostic pop
3447 : #endif // __clang__
3448 0 : arg0 = &args.get(0).toObject();
3449 : } else {
3450 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceJSMaplike.forEach");
3451 0 : return false;
3452 : }
3453 0 : JS::Rooted<JS::Value> arg1(cx);
3454 0 : if (args.hasDefined(1)) {
3455 : #ifdef __clang__
3456 : #pragma clang diagnostic push
3457 : #pragma clang diagnostic ignored "-Wunreachable-code"
3458 : #pragma clang diagnostic ignored "-Wunreachable-code-return"
3459 : #endif // __clang__
3460 0 : if ((true) && !CallerSubsumes(args.get(1))) {
3461 0 : ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "argument 2 of TestInterfaceJSMaplike.forEach");
3462 0 : return false;
3463 : }
3464 : #ifdef __clang__
3465 : #pragma clang diagnostic pop
3466 : #endif // __clang__
3467 0 : arg1 = args.get(1);
3468 : } else {
3469 0 : arg1 = JS::UndefinedValue();
3470 : }
3471 0 : if (objIsXray) {
3472 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3473 0 : if (!unwrappedObj.ref()) {
3474 0 : return false;
3475 : }
3476 : }
3477 0 : JS::Rooted<JSObject*> backingObj(cx);
3478 0 : bool created = false;
3479 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3480 0 : return false;
3481 : }
3482 0 : if (created) {
3483 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3484 : }
3485 : // Create a wrapper function.
3486 0 : JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
3487 0 : if (!func) {
3488 0 : return false;
3489 : }
3490 0 : JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
3491 0 : JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
3492 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
3493 0 : JS::ObjectValue(*arg0));
3494 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
3495 0 : JS::ObjectValue(*obj));
3496 0 : if (!JS::MapForEach(cx, backingObj, funcVal, arg1)) {
3497 0 : return false;
3498 : }
3499 0 : args.rval().setUndefined();
3500 0 : return true;
3501 : }
3502 :
3503 : static const JSJitInfo forEach_methodinfo = {
3504 : { (JSJitGetterOp)forEach },
3505 : { prototypes::id::TestInterfaceJSMaplike },
3506 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3507 : JSJitInfo::Method,
3508 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3509 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
3510 : false, /* isInfallible. False in setters. */
3511 : false, /* isMovable. Not relevant for setters. */
3512 : false, /* isEliminatable. Not relevant for setters. */
3513 : false, /* isAlwaysInSlot. Only relevant for getters. */
3514 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3515 : false, /* isTypedMethod. Only relevant for methods. */
3516 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3517 : };
3518 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3519 : static_assert(0 < 2, "There is no slot for us");
3520 :
3521 : static bool
3522 0 : has(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3523 : {
3524 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3525 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3526 0 : if (objIsXray) {
3527 0 : unwrappedObj.emplace(cx, obj);
3528 : }
3529 0 : binding_detail::FakeString arg0;
3530 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
3531 0 : return false;
3532 : }
3533 0 : if (objIsXray) {
3534 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3535 0 : if (!unwrappedObj.ref()) {
3536 0 : return false;
3537 : }
3538 : }
3539 0 : JS::Rooted<JSObject*> backingObj(cx);
3540 0 : bool created = false;
3541 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3542 0 : return false;
3543 : }
3544 0 : if (created) {
3545 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3546 : }
3547 0 : JS::Rooted<JS::Value> arg0Val(cx);
3548 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
3549 0 : return false;
3550 : }
3551 : bool result;
3552 0 : if (!JS::MapHas(cx, backingObj, arg0Val, &result)) {
3553 0 : return false;
3554 : }
3555 0 : args.rval().setBoolean(result);
3556 0 : return true;
3557 : }
3558 :
3559 : static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
3560 : static const JSTypedMethodJitInfo has_methodinfo = {
3561 : {
3562 : { (JSJitGetterOp)has },
3563 : { prototypes::id::TestInterfaceJSMaplike },
3564 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3565 : JSJitInfo::Method,
3566 : JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
3567 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
3568 : false, /* isInfallible. False in setters. */
3569 : false, /* isMovable. Not relevant for setters. */
3570 : false, /* isEliminatable. Not relevant for setters. */
3571 : false, /* isAlwaysInSlot. Only relevant for getters. */
3572 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3573 : true, /* isTypedMethod. Only relevant for methods. */
3574 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3575 : },
3576 : has_methodinfo_argTypes
3577 : };
3578 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3579 : static_assert(0 < 2, "There is no slot for us");
3580 :
3581 : static bool
3582 0 : __clear(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3583 : {
3584 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3585 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3586 0 : if (objIsXray) {
3587 0 : unwrappedObj.emplace(cx, obj);
3588 : }
3589 0 : if (objIsXray) {
3590 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3591 0 : if (!unwrappedObj.ref()) {
3592 0 : return false;
3593 : }
3594 : }
3595 0 : JS::Rooted<JSObject*> backingObj(cx);
3596 0 : bool created = false;
3597 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3598 0 : return false;
3599 : }
3600 0 : if (created) {
3601 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3602 : }
3603 0 : if (!JS::MapClear(cx, backingObj)) {
3604 0 : return false;
3605 : }
3606 0 : args.rval().setUndefined();
3607 0 : return true;
3608 : }
3609 :
3610 : static const JSJitInfo __clear_methodinfo = {
3611 : { (JSJitGetterOp)__clear },
3612 : { prototypes::id::TestInterfaceJSMaplike },
3613 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3614 : JSJitInfo::Method,
3615 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3616 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
3617 : false, /* isInfallible. False in setters. */
3618 : false, /* isMovable. Not relevant for setters. */
3619 : false, /* isEliminatable. Not relevant for setters. */
3620 : false, /* isAlwaysInSlot. Only relevant for getters. */
3621 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3622 : false, /* isTypedMethod. Only relevant for methods. */
3623 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3624 : };
3625 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3626 : static_assert(0 < 2, "There is no slot for us");
3627 :
3628 : static bool
3629 0 : __delete(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3630 : {
3631 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3632 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3633 0 : if (objIsXray) {
3634 0 : unwrappedObj.emplace(cx, obj);
3635 : }
3636 0 : binding_detail::FakeString arg0;
3637 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
3638 0 : return false;
3639 : }
3640 0 : if (objIsXray) {
3641 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3642 0 : if (!unwrappedObj.ref()) {
3643 0 : return false;
3644 : }
3645 : }
3646 0 : JS::Rooted<JSObject*> backingObj(cx);
3647 0 : bool created = false;
3648 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3649 0 : return false;
3650 : }
3651 0 : if (created) {
3652 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3653 : }
3654 0 : JS::Rooted<JS::Value> arg0Val(cx);
3655 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
3656 0 : return false;
3657 : }
3658 : bool result;
3659 0 : if (!JS::MapDelete(cx, backingObj, arg0Val, &result)) {
3660 0 : return false;
3661 : }
3662 0 : args.rval().setBoolean(result);
3663 0 : return true;
3664 : }
3665 :
3666 : static const JSJitInfo __delete_methodinfo = {
3667 : { (JSJitGetterOp)__delete },
3668 : { prototypes::id::TestInterfaceJSMaplike },
3669 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3670 : JSJitInfo::Method,
3671 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3672 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
3673 : false, /* isInfallible. False in setters. */
3674 : false, /* isMovable. Not relevant for setters. */
3675 : false, /* isEliminatable. Not relevant for setters. */
3676 : false, /* isAlwaysInSlot. Only relevant for getters. */
3677 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3678 : false, /* isTypedMethod. Only relevant for methods. */
3679 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3680 : };
3681 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3682 : static_assert(0 < 2, "There is no slot for us");
3683 :
3684 : static bool
3685 0 : get(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3686 : {
3687 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3688 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3689 0 : if (objIsXray) {
3690 0 : unwrappedObj.emplace(cx, obj);
3691 : }
3692 0 : binding_detail::FakeString arg0;
3693 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
3694 0 : return false;
3695 : }
3696 0 : if (objIsXray) {
3697 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3698 0 : if (!unwrappedObj.ref()) {
3699 0 : return false;
3700 : }
3701 : }
3702 0 : JS::Rooted<JSObject*> backingObj(cx);
3703 0 : bool created = false;
3704 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3705 0 : return false;
3706 : }
3707 0 : if (created) {
3708 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3709 : }
3710 0 : JS::Rooted<JS::Value> arg0Val(cx);
3711 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
3712 0 : return false;
3713 : }
3714 0 : JS::Rooted<JS::Value> result(cx);
3715 0 : if (!JS::MapGet(cx, backingObj, arg0Val, &result)) {
3716 0 : return false;
3717 : }
3718 0 : JS::ExposeValueToActiveJS(result);
3719 0 : args.rval().set(result);
3720 0 : if (!MaybeWrapValue(cx, args.rval())) {
3721 0 : return false;
3722 : }
3723 0 : return true;
3724 : }
3725 :
3726 : static const JSJitInfo::ArgType get_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
3727 : static const JSTypedMethodJitInfo get_methodinfo = {
3728 : {
3729 : { (JSJitGetterOp)get },
3730 : { prototypes::id::TestInterfaceJSMaplike },
3731 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3732 : JSJitInfo::Method,
3733 : JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
3734 : JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */
3735 : false, /* isInfallible. False in setters. */
3736 : false, /* isMovable. Not relevant for setters. */
3737 : false, /* isEliminatable. Not relevant for setters. */
3738 : false, /* isAlwaysInSlot. Only relevant for getters. */
3739 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3740 : true, /* isTypedMethod. Only relevant for methods. */
3741 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3742 : },
3743 : get_methodinfo_argTypes
3744 : };
3745 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3746 : static_assert(0 < 2, "There is no slot for us");
3747 :
3748 : static bool
3749 0 : __set(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceJSMaplike* self, const JSJitMethodCallArgs& args)
3750 : {
3751 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
3752 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
3753 0 : if (objIsXray) {
3754 0 : unwrappedObj.emplace(cx, obj);
3755 : }
3756 0 : binding_detail::FakeString arg0;
3757 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
3758 0 : return false;
3759 : }
3760 : int32_t arg1;
3761 0 : if (!ValueToPrimitive<int32_t, eDefault>(cx, args.get(1), &arg1)) {
3762 0 : return false;
3763 : }
3764 0 : if (objIsXray) {
3765 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
3766 0 : if (!unwrappedObj.ref()) {
3767 0 : return false;
3768 : }
3769 : }
3770 0 : JS::Rooted<JSObject*> backingObj(cx);
3771 0 : bool created = false;
3772 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
3773 0 : return false;
3774 : }
3775 0 : if (created) {
3776 0 : PreserveWrapper<mozilla::dom::TestInterfaceJSMaplike>(self);
3777 : }
3778 0 : JS::Rooted<JS::Value> arg0Val(cx);
3779 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
3780 0 : return false;
3781 : }
3782 0 : JS::Rooted<JS::Value> arg1Val(cx);
3783 0 : if (!ToJSValue(cx, arg1, &arg1Val)) {
3784 0 : return false;
3785 : }
3786 0 : JS::Rooted<JSObject*> result(cx);
3787 0 : if (!JS::MapSet(cx, backingObj, arg0Val, arg1Val)) {
3788 0 : return false;
3789 : }
3790 0 : result = obj;
3791 0 : JS::ExposeObjectToActiveJS(result);
3792 0 : args.rval().setObject(*result);
3793 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
3794 0 : return false;
3795 : }
3796 0 : return true;
3797 : }
3798 :
3799 : static const JSJitInfo __set_methodinfo = {
3800 : { (JSJitGetterOp)__set },
3801 : { prototypes::id::TestInterfaceJSMaplike },
3802 : { PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth },
3803 : JSJitInfo::Method,
3804 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
3805 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
3806 : false, /* isInfallible. False in setters. */
3807 : false, /* isMovable. Not relevant for setters. */
3808 : false, /* isEliminatable. Not relevant for setters. */
3809 : false, /* isAlwaysInSlot. Only relevant for getters. */
3810 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
3811 : false, /* isTypedMethod. Only relevant for methods. */
3812 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
3813 : };
3814 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
3815 : static_assert(0 < 2, "There is no slot for us");
3816 :
3817 : static bool
3818 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
3819 : {
3820 0 : mozilla::dom::TestInterfaceJSMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceJSMaplike>(obj);
3821 : // We don't want to preserve if we don't have a wrapper, and we
3822 : // obviously can't preserve if we're not initialized.
3823 0 : if (self && self->GetWrapperPreserveColor()) {
3824 0 : PreserveWrapper(self);
3825 : }
3826 0 : return true;
3827 : }
3828 :
3829 : static void
3830 0 : _finalize(js::FreeOp* fop, JSObject* obj)
3831 : {
3832 0 : mozilla::dom::TestInterfaceJSMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceJSMaplike>(obj);
3833 0 : if (self) {
3834 0 : ClearWrapper(self, self, obj);
3835 0 : AddForDeferredFinalization<mozilla::dom::TestInterfaceJSMaplike>(self);
3836 : }
3837 0 : }
3838 :
3839 : static void
3840 0 : _objectMoved(JSObject* obj, const JSObject* old)
3841 : {
3842 0 : mozilla::dom::TestInterfaceJSMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceJSMaplike>(obj);
3843 0 : if (self) {
3844 0 : UpdateWrapper(self, self, obj, old);
3845 : }
3846 0 : }
3847 :
3848 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
3849 : #if defined(__clang__)
3850 : #pragma clang diagnostic push
3851 : #pragma clang diagnostic ignored "-Wmissing-braces"
3852 : #endif
3853 : static const JSFunctionSpec sChromeStaticMethods_specs[] = {
3854 : JS_FNSPEC("_create", TestInterfaceJSMaplike::_Create, nullptr, 2, 0, nullptr),
3855 : JS_FS_END
3856 : };
3857 : #if defined(__clang__)
3858 : #pragma clang diagnostic pop
3859 : #endif
3860 :
3861 :
3862 : // Can't be const because the pref-enabled boolean needs to be writable
3863 : static Prefable<const JSFunctionSpec> sChromeStaticMethods[] = {
3864 : { nullptr, &sChromeStaticMethods_specs[0] },
3865 : { nullptr, nullptr }
3866 : };
3867 :
3868 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
3869 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
3870 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
3871 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
3872 :
3873 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
3874 : #if defined(__clang__)
3875 : #pragma clang diagnostic push
3876 : #pragma clang diagnostic ignored "-Wmissing-braces"
3877 : #endif
3878 : static const JSFunctionSpec sMethods_specs[] = {
3879 : JS_FNSPEC("setInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&setInternal_methodinfo), 2, JSPROP_ENUMERATE, nullptr),
3880 : JS_FNSPEC("clearInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&clearInternal_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
3881 : JS_FNSPEC("deleteInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&deleteInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
3882 : JS_FNSPEC("entries", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, 0, nullptr),
3883 : JS_FNSPEC("keys", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, 0, nullptr),
3884 : JS_FNSPEC("values", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, 0, nullptr),
3885 : JS_FNSPEC("forEach", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, 0, nullptr),
3886 : JS_FNSPEC("has", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, 0, nullptr),
3887 : JS_FNSPEC("get", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&get_methodinfo), 1, 0, nullptr),
3888 : JS_FS_END
3889 : };
3890 : #if defined(__clang__)
3891 : #pragma clang diagnostic pop
3892 : #endif
3893 :
3894 :
3895 : // Can't be const because the pref-enabled boolean needs to be writable
3896 : static Prefable<const JSFunctionSpec> sMethods[] = {
3897 : { nullptr, &sMethods_specs[0] },
3898 : { nullptr, nullptr }
3899 : };
3900 :
3901 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
3902 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
3903 : static_assert(9 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
3904 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
3905 :
3906 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
3907 : #if defined(__clang__)
3908 : #pragma clang diagnostic push
3909 : #pragma clang diagnostic ignored "-Wmissing-braces"
3910 : #endif
3911 : static const JSFunctionSpec sChromeMethods_specs[] = {
3912 : JS_FNSPEC("__clear", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&__clear_methodinfo), 0, 0, nullptr),
3913 : JS_FNSPEC("__delete", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&__delete_methodinfo), 1, 0, nullptr),
3914 : JS_FNSPEC("__set", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&__set_methodinfo), 2, 0, nullptr),
3915 : JS_FS_END
3916 : };
3917 : #if defined(__clang__)
3918 : #pragma clang diagnostic pop
3919 : #endif
3920 :
3921 :
3922 : // Can't be const because the pref-enabled boolean needs to be writable
3923 : static Prefable<const JSFunctionSpec> sChromeMethods[] = {
3924 : { nullptr, &sChromeMethods_specs[0] },
3925 : { nullptr, nullptr }
3926 : };
3927 :
3928 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
3929 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
3930 : static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
3931 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
3932 :
3933 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
3934 : #if defined(__clang__)
3935 : #pragma clang diagnostic push
3936 : #pragma clang diagnostic ignored "-Wmissing-braces"
3937 : #endif
3938 : static const JSPropertySpec sAttributes_specs[] = {
3939 : { "size", JSPROP_SHARED, GenericBindingGetter, &size_getterinfo, nullptr, nullptr },
3940 : { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
3941 : };
3942 : #if defined(__clang__)
3943 : #pragma clang diagnostic pop
3944 : #endif
3945 :
3946 :
3947 : // Can't be const because the pref-enabled boolean needs to be writable
3948 : static Prefable<const JSPropertySpec> sAttributes[] = {
3949 : { nullptr, &sAttributes_specs[0] },
3950 : { nullptr, nullptr }
3951 : };
3952 :
3953 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
3954 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
3955 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
3956 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
3957 :
3958 :
3959 : static uint16_t sNativeProperties_sortedPropertyIndices[10];
3960 : static PropertyInfo sNativeProperties_propertyInfos[10];
3961 :
3962 : static const NativePropertiesN<2> sNativeProperties = {
3963 : false, 0,
3964 : false, 0,
3965 : true, 0 /* sMethods */,
3966 : true, 1 /* sAttributes */,
3967 : false, 0,
3968 : false, 0,
3969 : false, 0,
3970 : 3,
3971 : 10,
3972 : sNativeProperties_sortedPropertyIndices,
3973 : {
3974 : { sMethods, &sNativeProperties_propertyInfos[0] },
3975 : { sAttributes, &sNativeProperties_propertyInfos[9] }
3976 : }
3977 : };
3978 : static_assert(3 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
3979 : "We have an iterator alias index that is oversized");
3980 : static_assert(10 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
3981 : "We have a property info count that is oversized");
3982 :
3983 : static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[4];
3984 : static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[4];
3985 :
3986 : static const NativePropertiesN<2> sChromeOnlyNativeProperties = {
3987 : true, 0 /* sChromeStaticMethods */,
3988 : false, 0,
3989 : true, 1 /* sChromeMethods */,
3990 : false, 0,
3991 : false, 0,
3992 : false, 0,
3993 : false, 0,
3994 : 3,
3995 : 4,
3996 : sChromeOnlyNativeProperties_sortedPropertyIndices,
3997 : {
3998 : { sChromeStaticMethods, &sChromeOnlyNativeProperties_propertyInfos[0] },
3999 : { sChromeMethods, &sChromeOnlyNativeProperties_propertyInfos[1] }
4000 : }
4001 : };
4002 : static_assert(3 < 1ull << (CHAR_BIT * sizeof(sChromeOnlyNativeProperties.iteratorAliasMethodIndex) - 1),
4003 : "We have an iterator alias index that is oversized");
4004 : static_assert(4 < 1ull << CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount),
4005 : "We have a property info count that is oversized");
4006 :
4007 : static bool
4008 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
4009 : {
4010 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
4011 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
4012 0 : if (!args.isConstructing()) {
4013 : // XXXbz wish I could get the name from the callee instead of
4014 : // Adding more relocations
4015 0 : return ThrowConstructorWithoutNew(cx, "TestInterfaceJSMaplike");
4016 : }
4017 :
4018 0 : GlobalObject global(cx, obj);
4019 0 : if (global.Failed()) {
4020 0 : return false;
4021 : }
4022 :
4023 0 : JS::Rooted<JSObject*> desiredProto(cx);
4024 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
4025 0 : return false;
4026 : }
4027 :
4028 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
4029 0 : Maybe<JSAutoCompartment> ac;
4030 0 : if (objIsXray) {
4031 0 : obj = js::CheckedUnwrap(obj);
4032 0 : if (!obj) {
4033 0 : return false;
4034 : }
4035 0 : ac.emplace(cx, obj);
4036 0 : if (!JS_WrapObject(cx, &desiredProto)) {
4037 0 : return false;
4038 : }
4039 : }
4040 0 : binding_detail::FastErrorResult rv;
4041 0 : auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceJSMaplike>(mozilla::dom::TestInterfaceJSMaplike::Constructor(global, cx, rv)));
4042 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
4043 0 : return false;
4044 : }
4045 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
4046 : static_assert(!IsPointer<decltype(result)>::value,
4047 : "NewObject implies that we need to keep the object alive with a strong reference.");
4048 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
4049 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
4050 0 : return false;
4051 : }
4052 0 : return true;
4053 : }
4054 :
4055 : static const js::ClassOps sInterfaceObjectClassOps = {
4056 : nullptr, /* addProperty */
4057 : nullptr, /* delProperty */
4058 : nullptr, /* getProperty */
4059 : nullptr, /* setProperty */
4060 : nullptr, /* enumerate */
4061 : nullptr, /* newEnumerate */
4062 : nullptr, /* resolve */
4063 : nullptr, /* mayResolve */
4064 : nullptr, /* finalize */
4065 : _constructor, /* call */
4066 : nullptr, /* hasInstance */
4067 : _constructor, /* construct */
4068 : nullptr, /* trace */
4069 : };
4070 :
4071 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
4072 : {
4073 : "Function",
4074 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
4075 : &sInterfaceObjectClassOps,
4076 : JS_NULL_CLASS_SPEC,
4077 : JS_NULL_CLASS_EXT,
4078 : &sInterfaceObjectClassObjectOps
4079 : },
4080 : eInterface,
4081 : true,
4082 : prototypes::id::TestInterfaceJSMaplike,
4083 : PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth,
4084 : sNativePropertyHooks,
4085 : "function TestInterfaceJSMaplike() {\n [native code]\n}",
4086 : JS::GetRealmFunctionPrototype
4087 : };
4088 :
4089 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
4090 : {
4091 : "TestInterfaceJSMaplikePrototype",
4092 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
4093 : JS_NULL_CLASS_OPS,
4094 : JS_NULL_CLASS_SPEC,
4095 : JS_NULL_CLASS_EXT,
4096 : JS_NULL_OBJECT_OPS
4097 : },
4098 : eInterfacePrototype,
4099 : false,
4100 : prototypes::id::TestInterfaceJSMaplike,
4101 : PrototypeTraits<prototypes::id::TestInterfaceJSMaplike>::Depth,
4102 : sNativePropertyHooks,
4103 : "[object TestInterfaceJSMaplikePrototype]",
4104 : JS::GetRealmObjectPrototype
4105 : };
4106 :
4107 : bool
4108 0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
4109 : {
4110 : static bool sPrefValue;
4111 : static bool sPrefCacheSetUp = false;
4112 0 : if (!sPrefCacheSetUp) {
4113 0 : sPrefCacheSetUp = true;
4114 0 : Preferences::AddBoolVarCache(&sPrefValue, "dom.expose_test_interfaces");
4115 : }
4116 :
4117 0 : return sPrefValue;
4118 : }
4119 :
4120 : JSObject*
4121 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
4122 : {
4123 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
4124 : }
4125 :
4126 : static const js::ClassOps sClassOps = {
4127 : _addProperty, /* addProperty */
4128 : nullptr, /* delProperty */
4129 : nullptr, /* getProperty */
4130 : nullptr, /* setProperty */
4131 : nullptr, /* enumerate */
4132 : nullptr, /* newEnumerate */
4133 : nullptr, /* resolve */
4134 : nullptr, /* mayResolve */
4135 : _finalize, /* finalize */
4136 : nullptr, /* call */
4137 : nullptr, /* hasInstance */
4138 : nullptr, /* construct */
4139 : nullptr, /* trace */
4140 : };
4141 :
4142 : static const js::ClassExtension sClassExtension = {
4143 : nullptr, /* weakmapKeyDelegateOp */
4144 : _objectMoved /* objectMovedOp */
4145 : };
4146 :
4147 : static const DOMJSClass sClass = {
4148 : { "TestInterfaceJSMaplike",
4149 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
4150 : &sClassOps,
4151 : JS_NULL_CLASS_SPEC,
4152 : &sClassExtension,
4153 : JS_NULL_OBJECT_OPS
4154 : },
4155 : { prototypes::id::TestInterfaceJSMaplike, 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 },
4156 : IsBaseOf<nsISupports, mozilla::dom::TestInterfaceJSMaplike >::value,
4157 : sNativePropertyHooks,
4158 : FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceJSMaplike>::Get,
4159 : GetProtoObjectHandle,
4160 : GetCCParticipant<mozilla::dom::TestInterfaceJSMaplike>::Get()
4161 : };
4162 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
4163 : "Must have the right minimal number of reserved slots.");
4164 : static_assert(2 >= 2,
4165 : "Must have enough reserved slots.");
4166 :
4167 : const JSClass*
4168 0 : GetJSClass()
4169 : {
4170 0 : return sClass.ToJSClass();
4171 : }
4172 :
4173 : bool
4174 0 : Wrap(JSContext* aCx, mozilla::dom::TestInterfaceJSMaplike* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
4175 : {
4176 : MOZ_ASSERT(static_cast<mozilla::dom::TestInterfaceJSMaplike*>(aObject) ==
4177 : reinterpret_cast<mozilla::dom::TestInterfaceJSMaplike*>(aObject),
4178 : "Multiple inheritance for mozilla::dom::TestInterfaceJSMaplike is broken.");
4179 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
4180 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
4181 0 : MOZ_ASSERT(!aCache->GetWrapper(),
4182 : "You should probably not be using Wrap() directly; use "
4183 : "GetOrCreateDOMReflector instead");
4184 :
4185 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
4186 : "nsISupports must be on our primary inheritance chain");
4187 :
4188 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
4189 0 : if (!global) {
4190 0 : return false;
4191 : }
4192 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
4193 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
4194 :
4195 : // That might have ended up wrapping us already, due to the wonders
4196 : // of XBL. Check for that, and bail out as needed.
4197 0 : aReflector.set(aCache->GetWrapper());
4198 0 : if (aReflector) {
4199 : #ifdef DEBUG
4200 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
4201 : #endif // DEBUG
4202 0 : return true;
4203 : }
4204 :
4205 0 : JSAutoCompartment ac(aCx, global);
4206 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
4207 0 : if (!canonicalProto) {
4208 0 : return false;
4209 : }
4210 0 : JS::Rooted<JSObject*> proto(aCx);
4211 0 : if (aGivenProto) {
4212 0 : proto = aGivenProto;
4213 : // Unfortunately, while aGivenProto was in the compartment of aCx
4214 : // coming in, we changed compartments to that of "parent" so may need
4215 : // to wrap the proto here.
4216 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
4217 0 : if (!JS_WrapObject(aCx, &proto)) {
4218 0 : return false;
4219 : }
4220 : }
4221 : } else {
4222 0 : proto = canonicalProto;
4223 : }
4224 :
4225 0 : BindingJSObjectCreator<mozilla::dom::TestInterfaceJSMaplike> creator(aCx);
4226 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
4227 0 : if (!aReflector) {
4228 0 : return false;
4229 : }
4230 :
4231 0 : aCache->SetWrapper(aReflector);
4232 0 : creator.InitializationSucceeded();
4233 :
4234 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
4235 : aCache->GetWrapperPreserveColor() == aReflector);
4236 : // If proto != canonicalProto, we have to preserve our wrapper;
4237 : // otherwise we won't be able to properly recreate it later, since
4238 : // we won't know what proto to use. Note that we don't check
4239 : // aGivenProto here, since it's entirely possible (and even
4240 : // somewhat common) to have a non-null aGivenProto which is the
4241 : // same as canonicalProto.
4242 0 : if (proto != canonicalProto) {
4243 0 : PreserveWrapper(aObject);
4244 : }
4245 :
4246 0 : return true;
4247 : }
4248 :
4249 : // This may allocate too many slots, because we only really need
4250 : // slots for our non-interface-typed members that we cache. But
4251 : // allocating slots only for those would make the slot index
4252 : // computations much more complicated, so let's do this the simple
4253 : // way for now.
4254 : DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
4255 :
4256 : const NativePropertyHooks sNativePropertyHooks[] = { {
4257 : nullptr,
4258 : nullptr,
4259 : nullptr,
4260 : { sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast() },
4261 : prototypes::id::TestInterfaceJSMaplike,
4262 : constructors::id::TestInterfaceJSMaplike,
4263 : nullptr,
4264 : &sXrayExpandoObjectClass
4265 : } };
4266 :
4267 : void
4268 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
4269 : {
4270 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
4271 0 : if (!parentProto) {
4272 0 : return;
4273 : }
4274 :
4275 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
4276 0 : if (!constructorProto) {
4277 0 : return;
4278 : }
4279 :
4280 : static bool sIdsInited = false;
4281 0 : if (!sIdsInited && NS_IsMainThread()) {
4282 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
4283 0 : return;
4284 : }
4285 0 : if (!InitIds(aCx, sChromeOnlyNativeProperties.Upcast())) {
4286 0 : return;
4287 : }
4288 0 : sIdsInited = true;
4289 : }
4290 :
4291 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceJSMaplike);
4292 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceJSMaplike);
4293 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
4294 : &sPrototypeClass.mBase, protoCache,
4295 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
4296 : interfaceCache,
4297 : sNativeProperties.Upcast(),
4298 0 : nsContentUtils::ThreadsafeIsSystemCaller(aCx) ? sChromeOnlyNativeProperties.Upcast() : nullptr,
4299 : "TestInterfaceJSMaplike", aDefineOnGlobal,
4300 : nullptr,
4301 0 : false);
4302 :
4303 : // Set up aliases on the interface prototype object we just created.
4304 0 : JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
4305 0 : if (!proto) {
4306 0 : *protoCache = nullptr;
4307 0 : if (interfaceCache) {
4308 0 : *interfaceCache = nullptr;
4309 : }
4310 0 : return;
4311 : }
4312 :
4313 0 : JS::Rooted<JS::Value> aliasedVal(aCx);
4314 :
4315 0 : if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
4316 0 : *protoCache = nullptr;
4317 0 : if (interfaceCache) {
4318 0 : *interfaceCache = nullptr;
4319 : }
4320 0 : return;
4321 : }
4322 0 : JS::Rooted<jsid> iteratorId(aCx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::iterator)));
4323 0 : if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
4324 0 : *protoCache = nullptr;
4325 0 : if (interfaceCache) {
4326 0 : *interfaceCache = nullptr;
4327 : }
4328 0 : return;
4329 : }
4330 : }
4331 :
4332 : JS::Handle<JSObject*>
4333 0 : GetProtoObjectHandle(JSContext* aCx)
4334 : {
4335 : /* Get the interface prototype object for this class. This will create the
4336 : object as needed. */
4337 0 : bool aDefineOnGlobal = true;
4338 :
4339 : /* Make sure our global is sane. Hopefully we can remove this sometime */
4340 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
4341 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
4342 0 : return nullptr;
4343 : }
4344 :
4345 : /* Check to see whether the interface objects are already installed */
4346 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
4347 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceJSMaplike)) {
4348 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
4349 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
4350 : }
4351 :
4352 : /*
4353 : * The object might _still_ be null, but that's OK.
4354 : *
4355 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
4356 : * traced by TraceProtoAndIfaceCache() and its contents are never
4357 : * changed after they have been set.
4358 : *
4359 : * Calling address() avoids the read read barrier that does gray
4360 : * unmarking, but it's not possible for the object to be gray here.
4361 : */
4362 :
4363 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceJSMaplike);
4364 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
4365 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
4366 : }
4367 :
4368 : JS::Handle<JSObject*>
4369 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
4370 : {
4371 : /* Get the interface object for this class. This will create the object as
4372 : needed. */
4373 :
4374 : /* Make sure our global is sane. Hopefully we can remove this sometime */
4375 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
4376 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
4377 0 : return nullptr;
4378 : }
4379 :
4380 : /* Check to see whether the interface objects are already installed */
4381 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
4382 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::TestInterfaceJSMaplike)) {
4383 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
4384 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
4385 : }
4386 :
4387 : /*
4388 : * The object might _still_ be null, but that's OK.
4389 : *
4390 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
4391 : * traced by TraceProtoAndIfaceCache() and its contents are never
4392 : * changed after they have been set.
4393 : *
4394 : * Calling address() avoids the read read barrier that does gray
4395 : * unmarking, but it's not possible for the object to be gray here.
4396 : */
4397 :
4398 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::TestInterfaceJSMaplike);
4399 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
4400 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
4401 : }
4402 :
4403 : JSObject*
4404 0 : GetConstructorObject(JSContext* aCx)
4405 : {
4406 0 : return GetConstructorObjectHandle(aCx);
4407 : }
4408 :
4409 : } // namespace TestInterfaceJSMaplikeBinding
4410 :
4411 :
4412 :
4413 : namespace TestInterfaceMaplikeBinding {
4414 :
4415 : namespace MaplikeHelpers {
4416 : void
4417 0 : Clear(mozilla::dom::TestInterfaceMaplike* self, ErrorResult& aRv)
4418 : {
4419 0 : MOZ_ASSERT(self);
4420 0 : AutoJSAPI jsapi;
4421 0 : jsapi.Init();
4422 0 : JSContext* cx = jsapi.cx();
4423 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
4424 : // all we want is to wrap into _some_ scope and then unwrap to find
4425 : // the reflector, and wrapping has no side-effects.
4426 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
4427 0 : JS::Rooted<JS::Value> v(cx);
4428 0 : if(!ToJSValue(cx, self, &v)) {
4429 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4430 0 : return;
4431 : }
4432 : // This is a reflector, but due to trying to name things
4433 : // similarly across method generators, it's called obj here.
4434 0 : JS::Rooted<JSObject*> obj(cx);
4435 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
4436 0 : JSAutoCompartment reflectorCompartment(cx, obj);
4437 :
4438 0 : JS::Rooted<JSObject*> backingObj(cx);
4439 0 : bool created = false;
4440 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
4441 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4442 0 : return;
4443 : }
4444 0 : if (created) {
4445 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
4446 : }
4447 0 : if (!JS::MapClear(cx, backingObj)) {
4448 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4449 0 : return;
4450 : }
4451 0 : return;
4452 : }
4453 : bool
4454 0 : Delete(mozilla::dom::TestInterfaceMaplike* self, const nsAString& aKey, ErrorResult& aRv)
4455 : {
4456 0 : MOZ_ASSERT(self);
4457 0 : AutoJSAPI jsapi;
4458 0 : jsapi.Init();
4459 0 : JSContext* cx = jsapi.cx();
4460 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
4461 : // all we want is to wrap into _some_ scope and then unwrap to find
4462 : // the reflector, and wrapping has no side-effects.
4463 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
4464 0 : JS::Rooted<JS::Value> v(cx);
4465 0 : if(!ToJSValue(cx, self, &v)) {
4466 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4467 0 : return false;
4468 : }
4469 : // This is a reflector, but due to trying to name things
4470 : // similarly across method generators, it's called obj here.
4471 0 : JS::Rooted<JSObject*> obj(cx);
4472 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
4473 0 : JSAutoCompartment reflectorCompartment(cx, obj);
4474 : bool aRetVal;
4475 0 : JS::AutoValueVector argv(cx);
4476 0 : if (!argv.resize(1)) {
4477 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
4478 0 : return false;
4479 : }
4480 : do {
4481 0 : nsString mutableStr(aKey);
4482 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
4483 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4484 0 : return false;
4485 : }
4486 0 : break;
4487 : } while (0);
4488 :
4489 0 : JS::Rooted<JSObject*> backingObj(cx);
4490 0 : bool created = false;
4491 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
4492 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4493 0 : return false;
4494 : }
4495 0 : if (created) {
4496 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
4497 : }
4498 0 : if (!JS::MapDelete(cx, backingObj, argv[0], &aRetVal)) {
4499 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4500 0 : return false;
4501 : }
4502 0 : return aRetVal;
4503 : }
4504 : bool
4505 0 : Has(mozilla::dom::TestInterfaceMaplike* self, const nsAString& aKey, ErrorResult& aRv)
4506 : {
4507 0 : MOZ_ASSERT(self);
4508 0 : AutoJSAPI jsapi;
4509 0 : jsapi.Init();
4510 0 : JSContext* cx = jsapi.cx();
4511 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
4512 : // all we want is to wrap into _some_ scope and then unwrap to find
4513 : // the reflector, and wrapping has no side-effects.
4514 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
4515 0 : JS::Rooted<JS::Value> v(cx);
4516 0 : if(!ToJSValue(cx, self, &v)) {
4517 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4518 0 : return false;
4519 : }
4520 : // This is a reflector, but due to trying to name things
4521 : // similarly across method generators, it's called obj here.
4522 0 : JS::Rooted<JSObject*> obj(cx);
4523 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
4524 0 : JSAutoCompartment reflectorCompartment(cx, obj);
4525 : bool aRetVal;
4526 0 : JS::AutoValueVector argv(cx);
4527 0 : if (!argv.resize(1)) {
4528 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
4529 0 : return false;
4530 : }
4531 : do {
4532 0 : nsString mutableStr(aKey);
4533 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
4534 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4535 0 : return false;
4536 : }
4537 0 : break;
4538 : } while (0);
4539 :
4540 0 : JS::Rooted<JSObject*> backingObj(cx);
4541 0 : bool created = false;
4542 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
4543 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4544 0 : return false;
4545 : }
4546 0 : if (created) {
4547 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
4548 : }
4549 0 : if (!JS::MapHas(cx, backingObj, argv[0], &aRetVal)) {
4550 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4551 0 : return false;
4552 : }
4553 0 : return aRetVal;
4554 : }
4555 : void
4556 0 : Set(mozilla::dom::TestInterfaceMaplike* self, const nsAString& aKey, int32_t aValue, ErrorResult& aRv)
4557 : {
4558 0 : MOZ_ASSERT(self);
4559 0 : AutoJSAPI jsapi;
4560 0 : jsapi.Init();
4561 0 : JSContext* cx = jsapi.cx();
4562 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
4563 : // all we want is to wrap into _some_ scope and then unwrap to find
4564 : // the reflector, and wrapping has no side-effects.
4565 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
4566 0 : JS::Rooted<JS::Value> v(cx);
4567 0 : if(!ToJSValue(cx, self, &v)) {
4568 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4569 0 : return;
4570 : }
4571 : // This is a reflector, but due to trying to name things
4572 : // similarly across method generators, it's called obj here.
4573 0 : JS::Rooted<JSObject*> obj(cx);
4574 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
4575 0 : JSAutoCompartment reflectorCompartment(cx, obj);
4576 0 : JS::AutoValueVector argv(cx);
4577 0 : if (!argv.resize(2)) {
4578 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
4579 0 : return;
4580 : }
4581 : do {
4582 0 : argv[1].setInt32(int32_t(aValue));
4583 0 : break;
4584 : } while (0);
4585 :
4586 : do {
4587 0 : nsString mutableStr(aKey);
4588 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
4589 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4590 0 : return;
4591 : }
4592 0 : break;
4593 : } while (0);
4594 :
4595 0 : JS::Rooted<JSObject*> backingObj(cx);
4596 0 : bool created = false;
4597 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
4598 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4599 0 : return;
4600 : }
4601 0 : if (created) {
4602 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
4603 : }
4604 0 : if (!JS::MapSet(cx, backingObj, argv[0], argv[1])) {
4605 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
4606 0 : return;
4607 : }
4608 0 : return;
4609 : }
4610 : } // namespace MaplikeHelpers
4611 :
4612 : static bool
4613 0 : setInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
4614 : {
4615 0 : if (MOZ_UNLIKELY(args.length() < 2)) {
4616 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "TestInterfaceMaplike.setInternal");
4617 : }
4618 0 : binding_detail::FakeString arg0;
4619 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
4620 0 : return false;
4621 : }
4622 : int32_t arg1;
4623 0 : if (!ValueToPrimitive<int32_t, eDefault>(cx, args[1], &arg1)) {
4624 0 : return false;
4625 : }
4626 0 : self->SetInternal(NonNullHelper(Constify(arg0)), arg1);
4627 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
4628 0 : args.rval().setUndefined();
4629 0 : return true;
4630 : }
4631 :
4632 : static const JSJitInfo setInternal_methodinfo = {
4633 : { (JSJitGetterOp)setInternal },
4634 : { prototypes::id::TestInterfaceMaplike },
4635 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
4636 : JSJitInfo::Method,
4637 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
4638 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
4639 : false, /* isInfallible. False in setters. */
4640 : false, /* isMovable. Not relevant for setters. */
4641 : false, /* isEliminatable. Not relevant for setters. */
4642 : false, /* isAlwaysInSlot. Only relevant for getters. */
4643 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
4644 : false, /* isTypedMethod. Only relevant for methods. */
4645 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
4646 : };
4647 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4648 : static_assert(0 < 2, "There is no slot for us");
4649 :
4650 : static bool
4651 0 : clearInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
4652 : {
4653 0 : self->ClearInternal();
4654 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
4655 0 : args.rval().setUndefined();
4656 0 : return true;
4657 : }
4658 :
4659 : static const JSJitInfo clearInternal_methodinfo = {
4660 : { (JSJitGetterOp)clearInternal },
4661 : { prototypes::id::TestInterfaceMaplike },
4662 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
4663 : JSJitInfo::Method,
4664 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
4665 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
4666 : true, /* isInfallible. False in setters. */
4667 : false, /* isMovable. Not relevant for setters. */
4668 : false, /* isEliminatable. Not relevant for setters. */
4669 : false, /* isAlwaysInSlot. Only relevant for getters. */
4670 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
4671 : false, /* isTypedMethod. Only relevant for methods. */
4672 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
4673 : };
4674 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4675 : static_assert(0 < 2, "There is no slot for us");
4676 :
4677 : static bool
4678 0 : deleteInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
4679 : {
4680 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
4681 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "TestInterfaceMaplike.deleteInternal");
4682 : }
4683 0 : binding_detail::FakeString arg0;
4684 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
4685 0 : return false;
4686 : }
4687 0 : bool result(self->DeleteInternal(NonNullHelper(Constify(arg0))));
4688 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
4689 0 : args.rval().setBoolean(result);
4690 0 : return true;
4691 : }
4692 :
4693 : static const JSJitInfo deleteInternal_methodinfo = {
4694 : { (JSJitGetterOp)deleteInternal },
4695 : { prototypes::id::TestInterfaceMaplike },
4696 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
4697 : JSJitInfo::Method,
4698 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
4699 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
4700 : false, /* isInfallible. False in setters. */
4701 : false, /* isMovable. Not relevant for setters. */
4702 : false, /* isEliminatable. Not relevant for setters. */
4703 : false, /* isAlwaysInSlot. Only relevant for getters. */
4704 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
4705 : false, /* isTypedMethod. Only relevant for methods. */
4706 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
4707 : };
4708 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4709 : static_assert(0 < 2, "There is no slot for us");
4710 :
4711 : static bool
4712 0 : hasInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
4713 : {
4714 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
4715 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "TestInterfaceMaplike.hasInternal");
4716 : }
4717 0 : binding_detail::FakeString arg0;
4718 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
4719 0 : return false;
4720 : }
4721 0 : bool result(self->HasInternal(NonNullHelper(Constify(arg0))));
4722 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
4723 0 : args.rval().setBoolean(result);
4724 0 : return true;
4725 : }
4726 :
4727 : static const JSJitInfo hasInternal_methodinfo = {
4728 : { (JSJitGetterOp)hasInternal },
4729 : { prototypes::id::TestInterfaceMaplike },
4730 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
4731 : JSJitInfo::Method,
4732 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
4733 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
4734 : false, /* isInfallible. False in setters. */
4735 : false, /* isMovable. Not relevant for setters. */
4736 : false, /* isEliminatable. Not relevant for setters. */
4737 : false, /* isAlwaysInSlot. Only relevant for getters. */
4738 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
4739 : false, /* isTypedMethod. Only relevant for methods. */
4740 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
4741 : };
4742 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4743 : static_assert(0 < 2, "There is no slot for us");
4744 :
4745 : static bool
4746 0 : get_size(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, JSJitGetterCallArgs args)
4747 : {
4748 0 : JS::Rooted<JSObject*> backingObj(cx);
4749 0 : bool created = false;
4750 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
4751 0 : return false;
4752 : }
4753 0 : if (created) {
4754 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
4755 : }
4756 0 : uint32_t result = JS::MapSize(cx, backingObj);
4757 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
4758 0 : args.rval().setNumber(result);
4759 0 : return true;
4760 : }
4761 :
4762 : static const JSJitInfo size_getterinfo = {
4763 : { (JSJitGetterOp)get_size },
4764 : { prototypes::id::TestInterfaceMaplike },
4765 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
4766 : JSJitInfo::Getter,
4767 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
4768 : JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
4769 : true, /* isInfallible. False in setters. */
4770 : false, /* isMovable. Not relevant for setters. */
4771 : false, /* isEliminatable. Not relevant for setters. */
4772 : false, /* isAlwaysInSlot. Only relevant for getters. */
4773 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
4774 : false, /* isTypedMethod. Only relevant for methods. */
4775 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
4776 : };
4777 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4778 : static_assert(0 < 2, "There is no slot for us");
4779 :
4780 : static bool
4781 0 : entries(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
4782 : {
4783 0 : JS::Rooted<JSObject*> backingObj(cx);
4784 0 : bool created = false;
4785 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
4786 0 : return false;
4787 : }
4788 0 : if (created) {
4789 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
4790 : }
4791 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
4792 : // after bug 1023984 is fixed.
4793 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
4794 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
4795 0 : return false;
4796 : }
4797 0 : JS::Rooted<JSObject*> result(cx);
4798 0 : JS::Rooted<JS::Value> v(cx);
4799 0 : if (!JS::MapEntries(cx, backingObj, &v)) {
4800 0 : return false;
4801 : }
4802 0 : result = &v.toObject();
4803 0 : JS::ExposeObjectToActiveJS(result);
4804 0 : args.rval().setObject(*result);
4805 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
4806 0 : return false;
4807 : }
4808 0 : return true;
4809 : }
4810 :
4811 : static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
4812 : static const JSTypedMethodJitInfo entries_methodinfo = {
4813 : {
4814 : { (JSJitGetterOp)entries },
4815 : { prototypes::id::TestInterfaceMaplike },
4816 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
4817 : JSJitInfo::Method,
4818 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
4819 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
4820 : false, /* isInfallible. False in setters. */
4821 : false, /* isMovable. Not relevant for setters. */
4822 : false, /* isEliminatable. Not relevant for setters. */
4823 : false, /* isAlwaysInSlot. Only relevant for getters. */
4824 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
4825 : true, /* isTypedMethod. Only relevant for methods. */
4826 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
4827 : },
4828 : entries_methodinfo_argTypes
4829 : };
4830 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4831 : static_assert(0 < 2, "There is no slot for us");
4832 :
4833 : static bool
4834 0 : keys(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
4835 : {
4836 0 : JS::Rooted<JSObject*> backingObj(cx);
4837 0 : bool created = false;
4838 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
4839 0 : return false;
4840 : }
4841 0 : if (created) {
4842 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
4843 : }
4844 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
4845 : // after bug 1023984 is fixed.
4846 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
4847 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
4848 0 : return false;
4849 : }
4850 0 : JS::Rooted<JSObject*> result(cx);
4851 0 : JS::Rooted<JS::Value> v(cx);
4852 0 : if (!JS::MapKeys(cx, backingObj, &v)) {
4853 0 : return false;
4854 : }
4855 0 : result = &v.toObject();
4856 0 : JS::ExposeObjectToActiveJS(result);
4857 0 : args.rval().setObject(*result);
4858 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
4859 0 : return false;
4860 : }
4861 0 : return true;
4862 : }
4863 :
4864 : static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
4865 : static const JSTypedMethodJitInfo keys_methodinfo = {
4866 : {
4867 : { (JSJitGetterOp)keys },
4868 : { prototypes::id::TestInterfaceMaplike },
4869 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
4870 : JSJitInfo::Method,
4871 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
4872 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
4873 : false, /* isInfallible. False in setters. */
4874 : false, /* isMovable. Not relevant for setters. */
4875 : false, /* isEliminatable. Not relevant for setters. */
4876 : false, /* isAlwaysInSlot. Only relevant for getters. */
4877 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
4878 : true, /* isTypedMethod. Only relevant for methods. */
4879 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
4880 : },
4881 : keys_methodinfo_argTypes
4882 : };
4883 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4884 : static_assert(0 < 2, "There is no slot for us");
4885 :
4886 : static bool
4887 0 : values(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
4888 : {
4889 0 : JS::Rooted<JSObject*> backingObj(cx);
4890 0 : bool created = false;
4891 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
4892 0 : return false;
4893 : }
4894 0 : if (created) {
4895 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
4896 : }
4897 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
4898 : // after bug 1023984 is fixed.
4899 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
4900 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
4901 0 : return false;
4902 : }
4903 0 : JS::Rooted<JSObject*> result(cx);
4904 0 : JS::Rooted<JS::Value> v(cx);
4905 0 : if (!JS::MapValues(cx, backingObj, &v)) {
4906 0 : return false;
4907 : }
4908 0 : result = &v.toObject();
4909 0 : JS::ExposeObjectToActiveJS(result);
4910 0 : args.rval().setObject(*result);
4911 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
4912 0 : return false;
4913 : }
4914 0 : return true;
4915 : }
4916 :
4917 : static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
4918 : static const JSTypedMethodJitInfo values_methodinfo = {
4919 : {
4920 : { (JSJitGetterOp)values },
4921 : { prototypes::id::TestInterfaceMaplike },
4922 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
4923 : JSJitInfo::Method,
4924 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
4925 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
4926 : false, /* isInfallible. False in setters. */
4927 : false, /* isMovable. Not relevant for setters. */
4928 : false, /* isEliminatable. Not relevant for setters. */
4929 : false, /* isAlwaysInSlot. Only relevant for getters. */
4930 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
4931 : true, /* isTypedMethod. Only relevant for methods. */
4932 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
4933 : },
4934 : values_methodinfo_argTypes
4935 : };
4936 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4937 : static_assert(0 < 2, "There is no slot for us");
4938 :
4939 : static bool
4940 0 : forEach(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
4941 : {
4942 0 : JS::Rooted<JSObject*> arg0(cx);
4943 0 : if (args.get(0).isObject()) {
4944 0 : arg0 = &args.get(0).toObject();
4945 : } else {
4946 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceMaplike.forEach");
4947 0 : return false;
4948 : }
4949 0 : JS::Rooted<JS::Value> arg1(cx);
4950 0 : if (args.hasDefined(1)) {
4951 0 : arg1 = args.get(1);
4952 : } else {
4953 0 : arg1 = JS::UndefinedValue();
4954 : }
4955 0 : JS::Rooted<JSObject*> backingObj(cx);
4956 0 : bool created = false;
4957 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
4958 0 : return false;
4959 : }
4960 0 : if (created) {
4961 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
4962 : }
4963 : // Create a wrapper function.
4964 0 : JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
4965 0 : if (!func) {
4966 0 : return false;
4967 : }
4968 0 : JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
4969 0 : JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
4970 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
4971 0 : JS::ObjectValue(*arg0));
4972 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
4973 0 : JS::ObjectValue(*obj));
4974 0 : if (!JS::MapForEach(cx, backingObj, funcVal, arg1)) {
4975 0 : return false;
4976 : }
4977 0 : args.rval().setUndefined();
4978 0 : return true;
4979 : }
4980 :
4981 : static const JSJitInfo forEach_methodinfo = {
4982 : { (JSJitGetterOp)forEach },
4983 : { prototypes::id::TestInterfaceMaplike },
4984 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
4985 : JSJitInfo::Method,
4986 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
4987 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
4988 : false, /* isInfallible. False in setters. */
4989 : false, /* isMovable. Not relevant for setters. */
4990 : false, /* isEliminatable. Not relevant for setters. */
4991 : false, /* isAlwaysInSlot. Only relevant for getters. */
4992 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
4993 : false, /* isTypedMethod. Only relevant for methods. */
4994 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
4995 : };
4996 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
4997 : static_assert(0 < 2, "There is no slot for us");
4998 :
4999 : static bool
5000 0 : has(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
5001 : {
5002 0 : binding_detail::FakeString arg0;
5003 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
5004 0 : return false;
5005 : }
5006 0 : JS::Rooted<JSObject*> backingObj(cx);
5007 0 : bool created = false;
5008 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5009 0 : return false;
5010 : }
5011 0 : if (created) {
5012 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
5013 : }
5014 0 : JS::Rooted<JS::Value> arg0Val(cx);
5015 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
5016 0 : return false;
5017 : }
5018 : bool result;
5019 0 : if (!JS::MapHas(cx, backingObj, arg0Val, &result)) {
5020 0 : return false;
5021 : }
5022 0 : args.rval().setBoolean(result);
5023 0 : return true;
5024 : }
5025 :
5026 : static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
5027 : static const JSTypedMethodJitInfo has_methodinfo = {
5028 : {
5029 : { (JSJitGetterOp)has },
5030 : { prototypes::id::TestInterfaceMaplike },
5031 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
5032 : JSJitInfo::Method,
5033 : JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
5034 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
5035 : false, /* isInfallible. False in setters. */
5036 : false, /* isMovable. Not relevant for setters. */
5037 : false, /* isEliminatable. Not relevant for setters. */
5038 : false, /* isAlwaysInSlot. Only relevant for getters. */
5039 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
5040 : true, /* isTypedMethod. Only relevant for methods. */
5041 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
5042 : },
5043 : has_methodinfo_argTypes
5044 : };
5045 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
5046 : static_assert(0 < 2, "There is no slot for us");
5047 :
5048 : static bool
5049 0 : clear(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
5050 : {
5051 0 : JS::Rooted<JSObject*> backingObj(cx);
5052 0 : bool created = false;
5053 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5054 0 : return false;
5055 : }
5056 0 : if (created) {
5057 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
5058 : }
5059 0 : if (!JS::MapClear(cx, backingObj)) {
5060 0 : return false;
5061 : }
5062 0 : args.rval().setUndefined();
5063 0 : return true;
5064 : }
5065 :
5066 : static const JSJitInfo clear_methodinfo = {
5067 : { (JSJitGetterOp)clear },
5068 : { prototypes::id::TestInterfaceMaplike },
5069 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
5070 : JSJitInfo::Method,
5071 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
5072 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
5073 : false, /* isInfallible. False in setters. */
5074 : false, /* isMovable. Not relevant for setters. */
5075 : false, /* isEliminatable. Not relevant for setters. */
5076 : false, /* isAlwaysInSlot. Only relevant for getters. */
5077 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
5078 : false, /* isTypedMethod. Only relevant for methods. */
5079 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
5080 : };
5081 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
5082 : static_assert(0 < 2, "There is no slot for us");
5083 :
5084 : static bool
5085 0 : _delete_(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
5086 : {
5087 0 : binding_detail::FakeString arg0;
5088 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
5089 0 : return false;
5090 : }
5091 0 : JS::Rooted<JSObject*> backingObj(cx);
5092 0 : bool created = false;
5093 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5094 0 : return false;
5095 : }
5096 0 : if (created) {
5097 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
5098 : }
5099 0 : JS::Rooted<JS::Value> arg0Val(cx);
5100 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
5101 0 : return false;
5102 : }
5103 : bool result;
5104 0 : if (!JS::MapDelete(cx, backingObj, arg0Val, &result)) {
5105 0 : return false;
5106 : }
5107 0 : args.rval().setBoolean(result);
5108 0 : return true;
5109 : }
5110 :
5111 : static const JSJitInfo delete_methodinfo = {
5112 : { (JSJitGetterOp)_delete_ },
5113 : { prototypes::id::TestInterfaceMaplike },
5114 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
5115 : JSJitInfo::Method,
5116 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
5117 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
5118 : false, /* isInfallible. False in setters. */
5119 : false, /* isMovable. Not relevant for setters. */
5120 : false, /* isEliminatable. Not relevant for setters. */
5121 : false, /* isAlwaysInSlot. Only relevant for getters. */
5122 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
5123 : false, /* isTypedMethod. Only relevant for methods. */
5124 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
5125 : };
5126 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
5127 : static_assert(0 < 2, "There is no slot for us");
5128 :
5129 : static bool
5130 0 : get(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
5131 : {
5132 0 : binding_detail::FakeString arg0;
5133 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
5134 0 : return false;
5135 : }
5136 0 : JS::Rooted<JSObject*> backingObj(cx);
5137 0 : bool created = false;
5138 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5139 0 : return false;
5140 : }
5141 0 : if (created) {
5142 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
5143 : }
5144 0 : JS::Rooted<JS::Value> arg0Val(cx);
5145 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
5146 0 : return false;
5147 : }
5148 0 : JS::Rooted<JS::Value> result(cx);
5149 0 : if (!JS::MapGet(cx, backingObj, arg0Val, &result)) {
5150 0 : return false;
5151 : }
5152 0 : JS::ExposeValueToActiveJS(result);
5153 0 : args.rval().set(result);
5154 0 : if (!MaybeWrapValue(cx, args.rval())) {
5155 0 : return false;
5156 : }
5157 0 : return true;
5158 : }
5159 :
5160 : static const JSJitInfo::ArgType get_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
5161 : static const JSTypedMethodJitInfo get_methodinfo = {
5162 : {
5163 : { (JSJitGetterOp)get },
5164 : { prototypes::id::TestInterfaceMaplike },
5165 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
5166 : JSJitInfo::Method,
5167 : JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
5168 : JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */
5169 : false, /* isInfallible. False in setters. */
5170 : false, /* isMovable. Not relevant for setters. */
5171 : false, /* isEliminatable. Not relevant for setters. */
5172 : false, /* isAlwaysInSlot. Only relevant for getters. */
5173 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
5174 : true, /* isTypedMethod. Only relevant for methods. */
5175 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
5176 : },
5177 : get_methodinfo_argTypes
5178 : };
5179 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
5180 : static_assert(0 < 2, "There is no slot for us");
5181 :
5182 : static bool
5183 0 : set(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplike* self, const JSJitMethodCallArgs& args)
5184 : {
5185 0 : binding_detail::FakeString arg0;
5186 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
5187 0 : return false;
5188 : }
5189 : int32_t arg1;
5190 0 : if (!ValueToPrimitive<int32_t, eDefault>(cx, args.get(1), &arg1)) {
5191 0 : return false;
5192 : }
5193 0 : JS::Rooted<JSObject*> backingObj(cx);
5194 0 : bool created = false;
5195 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5196 0 : return false;
5197 : }
5198 0 : if (created) {
5199 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
5200 : }
5201 0 : JS::Rooted<JS::Value> arg0Val(cx);
5202 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
5203 0 : return false;
5204 : }
5205 0 : JS::Rooted<JS::Value> arg1Val(cx);
5206 0 : if (!ToJSValue(cx, arg1, &arg1Val)) {
5207 0 : return false;
5208 : }
5209 0 : JS::Rooted<JSObject*> result(cx);
5210 0 : if (!JS::MapSet(cx, backingObj, arg0Val, arg1Val)) {
5211 0 : return false;
5212 : }
5213 0 : result = obj;
5214 0 : JS::ExposeObjectToActiveJS(result);
5215 0 : args.rval().setObject(*result);
5216 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
5217 0 : return false;
5218 : }
5219 0 : return true;
5220 : }
5221 :
5222 : static const JSJitInfo set_methodinfo = {
5223 : { (JSJitGetterOp)set },
5224 : { prototypes::id::TestInterfaceMaplike },
5225 : { PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
5226 : JSJitInfo::Method,
5227 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
5228 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
5229 : false, /* isInfallible. False in setters. */
5230 : false, /* isMovable. Not relevant for setters. */
5231 : false, /* isEliminatable. Not relevant for setters. */
5232 : false, /* isAlwaysInSlot. Only relevant for getters. */
5233 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
5234 : false, /* isTypedMethod. Only relevant for methods. */
5235 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
5236 : };
5237 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
5238 : static_assert(0 < 2, "There is no slot for us");
5239 :
5240 : static bool
5241 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
5242 : {
5243 0 : mozilla::dom::TestInterfaceMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplike>(obj);
5244 : // We don't want to preserve if we don't have a wrapper, and we
5245 : // obviously can't preserve if we're not initialized.
5246 0 : if (self && self->GetWrapperPreserveColor()) {
5247 0 : PreserveWrapper(self);
5248 : }
5249 0 : return true;
5250 : }
5251 :
5252 : static void
5253 0 : _finalize(js::FreeOp* fop, JSObject* obj)
5254 : {
5255 0 : mozilla::dom::TestInterfaceMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplike>(obj);
5256 0 : if (self) {
5257 0 : ClearWrapper(self, self, obj);
5258 0 : AddForDeferredFinalization<mozilla::dom::TestInterfaceMaplike>(self);
5259 : }
5260 0 : }
5261 :
5262 : static void
5263 0 : _objectMoved(JSObject* obj, const JSObject* old)
5264 : {
5265 0 : mozilla::dom::TestInterfaceMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplike>(obj);
5266 0 : if (self) {
5267 0 : UpdateWrapper(self, self, obj, old);
5268 : }
5269 0 : }
5270 :
5271 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
5272 : #if defined(__clang__)
5273 : #pragma clang diagnostic push
5274 : #pragma clang diagnostic ignored "-Wmissing-braces"
5275 : #endif
5276 : static const JSFunctionSpec sMethods_specs[] = {
5277 : JS_FNSPEC("setInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&setInternal_methodinfo), 2, JSPROP_ENUMERATE, nullptr),
5278 : JS_FNSPEC("clearInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&clearInternal_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
5279 : JS_FNSPEC("deleteInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&deleteInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
5280 : JS_FNSPEC("hasInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&hasInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
5281 : JS_FNSPEC("entries", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, 0, nullptr),
5282 : JS_FNSPEC("keys", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, 0, nullptr),
5283 : JS_FNSPEC("values", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, 0, nullptr),
5284 : JS_FNSPEC("forEach", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, 0, nullptr),
5285 : JS_FNSPEC("has", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, 0, nullptr),
5286 : JS_FNSPEC("clear", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&clear_methodinfo), 0, 0, nullptr),
5287 : JS_FNSPEC("delete", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&delete_methodinfo), 1, 0, nullptr),
5288 : JS_FNSPEC("get", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&get_methodinfo), 1, 0, nullptr),
5289 : JS_FNSPEC("set", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&set_methodinfo), 2, 0, nullptr),
5290 : JS_FS_END
5291 : };
5292 : #if defined(__clang__)
5293 : #pragma clang diagnostic pop
5294 : #endif
5295 :
5296 :
5297 : // Can't be const because the pref-enabled boolean needs to be writable
5298 : static Prefable<const JSFunctionSpec> sMethods[] = {
5299 : { nullptr, &sMethods_specs[0] },
5300 : { nullptr, nullptr }
5301 : };
5302 :
5303 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
5304 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
5305 : static_assert(13 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
5306 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
5307 :
5308 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
5309 : #if defined(__clang__)
5310 : #pragma clang diagnostic push
5311 : #pragma clang diagnostic ignored "-Wmissing-braces"
5312 : #endif
5313 : static const JSPropertySpec sAttributes_specs[] = {
5314 : { "size", JSPROP_SHARED, GenericBindingGetter, &size_getterinfo, nullptr, nullptr },
5315 : { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
5316 : };
5317 : #if defined(__clang__)
5318 : #pragma clang diagnostic pop
5319 : #endif
5320 :
5321 :
5322 : // Can't be const because the pref-enabled boolean needs to be writable
5323 : static Prefable<const JSPropertySpec> sAttributes[] = {
5324 : { nullptr, &sAttributes_specs[0] },
5325 : { nullptr, nullptr }
5326 : };
5327 :
5328 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
5329 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
5330 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
5331 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
5332 :
5333 :
5334 : static uint16_t sNativeProperties_sortedPropertyIndices[14];
5335 : static PropertyInfo sNativeProperties_propertyInfos[14];
5336 :
5337 : static const NativePropertiesN<2> sNativeProperties = {
5338 : false, 0,
5339 : false, 0,
5340 : true, 0 /* sMethods */,
5341 : true, 1 /* sAttributes */,
5342 : false, 0,
5343 : false, 0,
5344 : false, 0,
5345 : 4,
5346 : 14,
5347 : sNativeProperties_sortedPropertyIndices,
5348 : {
5349 : { sMethods, &sNativeProperties_propertyInfos[0] },
5350 : { sAttributes, &sNativeProperties_propertyInfos[13] }
5351 : }
5352 : };
5353 : static_assert(4 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
5354 : "We have an iterator alias index that is oversized");
5355 : static_assert(14 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
5356 : "We have a property info count that is oversized");
5357 :
5358 : static bool
5359 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
5360 : {
5361 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
5362 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
5363 0 : if (!args.isConstructing()) {
5364 : // XXXbz wish I could get the name from the callee instead of
5365 : // Adding more relocations
5366 0 : return ThrowConstructorWithoutNew(cx, "TestInterfaceMaplike");
5367 : }
5368 :
5369 0 : GlobalObject global(cx, obj);
5370 0 : if (global.Failed()) {
5371 0 : return false;
5372 : }
5373 :
5374 0 : JS::Rooted<JSObject*> desiredProto(cx);
5375 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
5376 0 : return false;
5377 : }
5378 :
5379 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
5380 0 : Maybe<JSAutoCompartment> ac;
5381 0 : if (objIsXray) {
5382 0 : obj = js::CheckedUnwrap(obj);
5383 0 : if (!obj) {
5384 0 : return false;
5385 : }
5386 0 : ac.emplace(cx, obj);
5387 0 : if (!JS_WrapObject(cx, &desiredProto)) {
5388 0 : return false;
5389 : }
5390 : }
5391 0 : binding_detail::FastErrorResult rv;
5392 0 : auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceMaplike>(mozilla::dom::TestInterfaceMaplike::Constructor(global, rv)));
5393 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
5394 0 : return false;
5395 : }
5396 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
5397 : static_assert(!IsPointer<decltype(result)>::value,
5398 : "NewObject implies that we need to keep the object alive with a strong reference.");
5399 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
5400 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
5401 0 : return false;
5402 : }
5403 0 : return true;
5404 : }
5405 :
5406 : static const js::ClassOps sInterfaceObjectClassOps = {
5407 : nullptr, /* addProperty */
5408 : nullptr, /* delProperty */
5409 : nullptr, /* getProperty */
5410 : nullptr, /* setProperty */
5411 : nullptr, /* enumerate */
5412 : nullptr, /* newEnumerate */
5413 : nullptr, /* resolve */
5414 : nullptr, /* mayResolve */
5415 : nullptr, /* finalize */
5416 : _constructor, /* call */
5417 : nullptr, /* hasInstance */
5418 : _constructor, /* construct */
5419 : nullptr, /* trace */
5420 : };
5421 :
5422 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
5423 : {
5424 : "Function",
5425 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
5426 : &sInterfaceObjectClassOps,
5427 : JS_NULL_CLASS_SPEC,
5428 : JS_NULL_CLASS_EXT,
5429 : &sInterfaceObjectClassObjectOps
5430 : },
5431 : eInterface,
5432 : true,
5433 : prototypes::id::TestInterfaceMaplike,
5434 : PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth,
5435 : sNativePropertyHooks,
5436 : "function TestInterfaceMaplike() {\n [native code]\n}",
5437 : JS::GetRealmFunctionPrototype
5438 : };
5439 :
5440 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
5441 : {
5442 : "TestInterfaceMaplikePrototype",
5443 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
5444 : JS_NULL_CLASS_OPS,
5445 : JS_NULL_CLASS_SPEC,
5446 : JS_NULL_CLASS_EXT,
5447 : JS_NULL_OBJECT_OPS
5448 : },
5449 : eInterfacePrototype,
5450 : false,
5451 : prototypes::id::TestInterfaceMaplike,
5452 : PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth,
5453 : sNativePropertyHooks,
5454 : "[object TestInterfaceMaplikePrototype]",
5455 : JS::GetRealmObjectPrototype
5456 : };
5457 :
5458 : bool
5459 0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
5460 : {
5461 : static bool sPrefValue;
5462 : static bool sPrefCacheSetUp = false;
5463 0 : if (!sPrefCacheSetUp) {
5464 0 : sPrefCacheSetUp = true;
5465 0 : Preferences::AddBoolVarCache(&sPrefValue, "dom.expose_test_interfaces");
5466 : }
5467 :
5468 0 : return sPrefValue;
5469 : }
5470 :
5471 : JSObject*
5472 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
5473 : {
5474 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
5475 : }
5476 :
5477 : static const js::ClassOps sClassOps = {
5478 : _addProperty, /* addProperty */
5479 : nullptr, /* delProperty */
5480 : nullptr, /* getProperty */
5481 : nullptr, /* setProperty */
5482 : nullptr, /* enumerate */
5483 : nullptr, /* newEnumerate */
5484 : nullptr, /* resolve */
5485 : nullptr, /* mayResolve */
5486 : _finalize, /* finalize */
5487 : nullptr, /* call */
5488 : nullptr, /* hasInstance */
5489 : nullptr, /* construct */
5490 : nullptr, /* trace */
5491 : };
5492 :
5493 : static const js::ClassExtension sClassExtension = {
5494 : nullptr, /* weakmapKeyDelegateOp */
5495 : _objectMoved /* objectMovedOp */
5496 : };
5497 :
5498 : static const DOMJSClass sClass = {
5499 : { "TestInterfaceMaplike",
5500 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
5501 : &sClassOps,
5502 : JS_NULL_CLASS_SPEC,
5503 : &sClassExtension,
5504 : JS_NULL_OBJECT_OPS
5505 : },
5506 : { prototypes::id::TestInterfaceMaplike, 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 },
5507 : IsBaseOf<nsISupports, mozilla::dom::TestInterfaceMaplike >::value,
5508 : sNativePropertyHooks,
5509 : FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceMaplike>::Get,
5510 : GetProtoObjectHandle,
5511 : GetCCParticipant<mozilla::dom::TestInterfaceMaplike>::Get()
5512 : };
5513 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
5514 : "Must have the right minimal number of reserved slots.");
5515 : static_assert(2 >= 2,
5516 : "Must have enough reserved slots.");
5517 :
5518 : const JSClass*
5519 0 : GetJSClass()
5520 : {
5521 0 : return sClass.ToJSClass();
5522 : }
5523 :
5524 : bool
5525 0 : Wrap(JSContext* aCx, mozilla::dom::TestInterfaceMaplike* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
5526 : {
5527 : MOZ_ASSERT(static_cast<mozilla::dom::TestInterfaceMaplike*>(aObject) ==
5528 : reinterpret_cast<mozilla::dom::TestInterfaceMaplike*>(aObject),
5529 : "Multiple inheritance for mozilla::dom::TestInterfaceMaplike is broken.");
5530 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
5531 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
5532 0 : MOZ_ASSERT(!aCache->GetWrapper(),
5533 : "You should probably not be using Wrap() directly; use "
5534 : "GetOrCreateDOMReflector instead");
5535 :
5536 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
5537 : "nsISupports must be on our primary inheritance chain");
5538 :
5539 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
5540 0 : if (!global) {
5541 0 : return false;
5542 : }
5543 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
5544 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
5545 :
5546 : // That might have ended up wrapping us already, due to the wonders
5547 : // of XBL. Check for that, and bail out as needed.
5548 0 : aReflector.set(aCache->GetWrapper());
5549 0 : if (aReflector) {
5550 : #ifdef DEBUG
5551 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
5552 : #endif // DEBUG
5553 0 : return true;
5554 : }
5555 :
5556 0 : JSAutoCompartment ac(aCx, global);
5557 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
5558 0 : if (!canonicalProto) {
5559 0 : return false;
5560 : }
5561 0 : JS::Rooted<JSObject*> proto(aCx);
5562 0 : if (aGivenProto) {
5563 0 : proto = aGivenProto;
5564 : // Unfortunately, while aGivenProto was in the compartment of aCx
5565 : // coming in, we changed compartments to that of "parent" so may need
5566 : // to wrap the proto here.
5567 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
5568 0 : if (!JS_WrapObject(aCx, &proto)) {
5569 0 : return false;
5570 : }
5571 : }
5572 : } else {
5573 0 : proto = canonicalProto;
5574 : }
5575 :
5576 0 : BindingJSObjectCreator<mozilla::dom::TestInterfaceMaplike> creator(aCx);
5577 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
5578 0 : if (!aReflector) {
5579 0 : return false;
5580 : }
5581 :
5582 0 : aCache->SetWrapper(aReflector);
5583 0 : creator.InitializationSucceeded();
5584 :
5585 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
5586 : aCache->GetWrapperPreserveColor() == aReflector);
5587 : // If proto != canonicalProto, we have to preserve our wrapper;
5588 : // otherwise we won't be able to properly recreate it later, since
5589 : // we won't know what proto to use. Note that we don't check
5590 : // aGivenProto here, since it's entirely possible (and even
5591 : // somewhat common) to have a non-null aGivenProto which is the
5592 : // same as canonicalProto.
5593 0 : if (proto != canonicalProto) {
5594 0 : PreserveWrapper(aObject);
5595 : }
5596 :
5597 0 : return true;
5598 : }
5599 :
5600 : // This may allocate too many slots, because we only really need
5601 : // slots for our non-interface-typed members that we cache. But
5602 : // allocating slots only for those would make the slot index
5603 : // computations much more complicated, so let's do this the simple
5604 : // way for now.
5605 : DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
5606 :
5607 : const NativePropertyHooks sNativePropertyHooks[] = { {
5608 : nullptr,
5609 : nullptr,
5610 : nullptr,
5611 : { sNativeProperties.Upcast(), nullptr },
5612 : prototypes::id::TestInterfaceMaplike,
5613 : constructors::id::TestInterfaceMaplike,
5614 : nullptr,
5615 : &sXrayExpandoObjectClass
5616 : } };
5617 :
5618 : void
5619 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
5620 : {
5621 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
5622 0 : if (!parentProto) {
5623 0 : return;
5624 : }
5625 :
5626 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
5627 0 : if (!constructorProto) {
5628 0 : return;
5629 : }
5630 :
5631 : static bool sIdsInited = false;
5632 0 : if (!sIdsInited && NS_IsMainThread()) {
5633 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
5634 0 : return;
5635 : }
5636 0 : sIdsInited = true;
5637 : }
5638 :
5639 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceMaplike);
5640 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceMaplike);
5641 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
5642 : &sPrototypeClass.mBase, protoCache,
5643 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
5644 : interfaceCache,
5645 : sNativeProperties.Upcast(),
5646 : nullptr,
5647 : "TestInterfaceMaplike", aDefineOnGlobal,
5648 : nullptr,
5649 0 : false);
5650 :
5651 : // Set up aliases on the interface prototype object we just created.
5652 0 : JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
5653 0 : if (!proto) {
5654 0 : *protoCache = nullptr;
5655 0 : if (interfaceCache) {
5656 0 : *interfaceCache = nullptr;
5657 : }
5658 0 : return;
5659 : }
5660 :
5661 0 : JS::Rooted<JS::Value> aliasedVal(aCx);
5662 :
5663 0 : if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
5664 0 : *protoCache = nullptr;
5665 0 : if (interfaceCache) {
5666 0 : *interfaceCache = nullptr;
5667 : }
5668 0 : return;
5669 : }
5670 0 : JS::Rooted<jsid> iteratorId(aCx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::iterator)));
5671 0 : if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
5672 0 : *protoCache = nullptr;
5673 0 : if (interfaceCache) {
5674 0 : *interfaceCache = nullptr;
5675 : }
5676 0 : return;
5677 : }
5678 : }
5679 :
5680 : JS::Handle<JSObject*>
5681 0 : GetProtoObjectHandle(JSContext* aCx)
5682 : {
5683 : /* Get the interface prototype object for this class. This will create the
5684 : object as needed. */
5685 0 : bool aDefineOnGlobal = true;
5686 :
5687 : /* Make sure our global is sane. Hopefully we can remove this sometime */
5688 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
5689 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
5690 0 : return nullptr;
5691 : }
5692 :
5693 : /* Check to see whether the interface objects are already installed */
5694 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
5695 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceMaplike)) {
5696 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
5697 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
5698 : }
5699 :
5700 : /*
5701 : * The object might _still_ be null, but that's OK.
5702 : *
5703 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
5704 : * traced by TraceProtoAndIfaceCache() and its contents are never
5705 : * changed after they have been set.
5706 : *
5707 : * Calling address() avoids the read read barrier that does gray
5708 : * unmarking, but it's not possible for the object to be gray here.
5709 : */
5710 :
5711 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceMaplike);
5712 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
5713 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
5714 : }
5715 :
5716 : JS::Handle<JSObject*>
5717 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
5718 : {
5719 : /* Get the interface object for this class. This will create the object as
5720 : needed. */
5721 :
5722 : /* Make sure our global is sane. Hopefully we can remove this sometime */
5723 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
5724 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
5725 0 : return nullptr;
5726 : }
5727 :
5728 : /* Check to see whether the interface objects are already installed */
5729 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
5730 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::TestInterfaceMaplike)) {
5731 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
5732 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
5733 : }
5734 :
5735 : /*
5736 : * The object might _still_ be null, but that's OK.
5737 : *
5738 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
5739 : * traced by TraceProtoAndIfaceCache() and its contents are never
5740 : * changed after they have been set.
5741 : *
5742 : * Calling address() avoids the read read barrier that does gray
5743 : * unmarking, but it's not possible for the object to be gray here.
5744 : */
5745 :
5746 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::TestInterfaceMaplike);
5747 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
5748 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
5749 : }
5750 :
5751 : JSObject*
5752 0 : GetConstructorObject(JSContext* aCx)
5753 : {
5754 0 : return GetConstructorObjectHandle(aCx);
5755 : }
5756 :
5757 : } // namespace TestInterfaceMaplikeBinding
5758 :
5759 :
5760 :
5761 : namespace TestInterfaceMaplikeObjectBinding {
5762 :
5763 : namespace MaplikeHelpers {
5764 : void
5765 0 : Clear(mozilla::dom::TestInterfaceMaplikeObject* self, ErrorResult& aRv)
5766 : {
5767 0 : MOZ_ASSERT(self);
5768 0 : AutoJSAPI jsapi;
5769 0 : jsapi.Init();
5770 0 : JSContext* cx = jsapi.cx();
5771 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
5772 : // all we want is to wrap into _some_ scope and then unwrap to find
5773 : // the reflector, and wrapping has no side-effects.
5774 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
5775 0 : JS::Rooted<JS::Value> v(cx);
5776 0 : if(!ToJSValue(cx, self, &v)) {
5777 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5778 0 : return;
5779 : }
5780 : // This is a reflector, but due to trying to name things
5781 : // similarly across method generators, it's called obj here.
5782 0 : JS::Rooted<JSObject*> obj(cx);
5783 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
5784 0 : JSAutoCompartment reflectorCompartment(cx, obj);
5785 :
5786 0 : JS::Rooted<JSObject*> backingObj(cx);
5787 0 : bool created = false;
5788 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5789 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5790 0 : return;
5791 : }
5792 0 : if (created) {
5793 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
5794 : }
5795 0 : if (!JS::MapClear(cx, backingObj)) {
5796 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5797 0 : return;
5798 : }
5799 0 : return;
5800 : }
5801 : bool
5802 0 : Delete(mozilla::dom::TestInterfaceMaplikeObject* self, const nsAString& aKey, ErrorResult& aRv)
5803 : {
5804 0 : MOZ_ASSERT(self);
5805 0 : AutoJSAPI jsapi;
5806 0 : jsapi.Init();
5807 0 : JSContext* cx = jsapi.cx();
5808 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
5809 : // all we want is to wrap into _some_ scope and then unwrap to find
5810 : // the reflector, and wrapping has no side-effects.
5811 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
5812 0 : JS::Rooted<JS::Value> v(cx);
5813 0 : if(!ToJSValue(cx, self, &v)) {
5814 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5815 0 : return false;
5816 : }
5817 : // This is a reflector, but due to trying to name things
5818 : // similarly across method generators, it's called obj here.
5819 0 : JS::Rooted<JSObject*> obj(cx);
5820 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
5821 0 : JSAutoCompartment reflectorCompartment(cx, obj);
5822 : bool aRetVal;
5823 0 : JS::AutoValueVector argv(cx);
5824 0 : if (!argv.resize(1)) {
5825 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
5826 0 : return false;
5827 : }
5828 : do {
5829 0 : nsString mutableStr(aKey);
5830 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
5831 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5832 0 : return false;
5833 : }
5834 0 : break;
5835 : } while (0);
5836 :
5837 0 : JS::Rooted<JSObject*> backingObj(cx);
5838 0 : bool created = false;
5839 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5840 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5841 0 : return false;
5842 : }
5843 0 : if (created) {
5844 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
5845 : }
5846 0 : if (!JS::MapDelete(cx, backingObj, argv[0], &aRetVal)) {
5847 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5848 0 : return false;
5849 : }
5850 0 : return aRetVal;
5851 : }
5852 : bool
5853 0 : Has(mozilla::dom::TestInterfaceMaplikeObject* self, const nsAString& aKey, ErrorResult& aRv)
5854 : {
5855 0 : MOZ_ASSERT(self);
5856 0 : AutoJSAPI jsapi;
5857 0 : jsapi.Init();
5858 0 : JSContext* cx = jsapi.cx();
5859 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
5860 : // all we want is to wrap into _some_ scope and then unwrap to find
5861 : // the reflector, and wrapping has no side-effects.
5862 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
5863 0 : JS::Rooted<JS::Value> v(cx);
5864 0 : if(!ToJSValue(cx, self, &v)) {
5865 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5866 0 : return false;
5867 : }
5868 : // This is a reflector, but due to trying to name things
5869 : // similarly across method generators, it's called obj here.
5870 0 : JS::Rooted<JSObject*> obj(cx);
5871 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
5872 0 : JSAutoCompartment reflectorCompartment(cx, obj);
5873 : bool aRetVal;
5874 0 : JS::AutoValueVector argv(cx);
5875 0 : if (!argv.resize(1)) {
5876 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
5877 0 : return false;
5878 : }
5879 : do {
5880 0 : nsString mutableStr(aKey);
5881 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
5882 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5883 0 : return false;
5884 : }
5885 0 : break;
5886 : } while (0);
5887 :
5888 0 : JS::Rooted<JSObject*> backingObj(cx);
5889 0 : bool created = false;
5890 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5891 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5892 0 : return false;
5893 : }
5894 0 : if (created) {
5895 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
5896 : }
5897 0 : if (!JS::MapHas(cx, backingObj, argv[0], &aRetVal)) {
5898 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5899 0 : return false;
5900 : }
5901 0 : return aRetVal;
5902 : }
5903 : void
5904 0 : Set(mozilla::dom::TestInterfaceMaplikeObject* self, const nsAString& aKey, TestInterfaceMaplike& aValue, ErrorResult& aRv)
5905 : {
5906 0 : MOZ_ASSERT(self);
5907 0 : AutoJSAPI jsapi;
5908 0 : jsapi.Init();
5909 0 : JSContext* cx = jsapi.cx();
5910 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
5911 : // all we want is to wrap into _some_ scope and then unwrap to find
5912 : // the reflector, and wrapping has no side-effects.
5913 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
5914 0 : JS::Rooted<JS::Value> v(cx);
5915 0 : if(!ToJSValue(cx, self, &v)) {
5916 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5917 0 : return;
5918 : }
5919 : // This is a reflector, but due to trying to name things
5920 : // similarly across method generators, it's called obj here.
5921 0 : JS::Rooted<JSObject*> obj(cx);
5922 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
5923 0 : JSAutoCompartment reflectorCompartment(cx, obj);
5924 0 : JS::AutoValueVector argv(cx);
5925 0 : if (!argv.resize(2)) {
5926 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
5927 0 : return;
5928 : }
5929 : do {
5930 0 : if (!GetOrCreateDOMReflector(cx, aValue, argv[1])) {
5931 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
5932 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5933 0 : return;
5934 : }
5935 0 : break;
5936 : } while (0);
5937 :
5938 : do {
5939 0 : nsString mutableStr(aKey);
5940 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
5941 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5942 0 : return;
5943 : }
5944 0 : break;
5945 : } while (0);
5946 :
5947 0 : JS::Rooted<JSObject*> backingObj(cx);
5948 0 : bool created = false;
5949 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
5950 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5951 0 : return;
5952 : }
5953 0 : if (created) {
5954 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
5955 : }
5956 0 : if (!JS::MapSet(cx, backingObj, argv[0], argv[1])) {
5957 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
5958 0 : return;
5959 : }
5960 0 : return;
5961 : }
5962 : } // namespace MaplikeHelpers
5963 :
5964 : static bool
5965 0 : setInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
5966 : {
5967 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
5968 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "TestInterfaceMaplikeObject.setInternal");
5969 : }
5970 0 : binding_detail::FakeString arg0;
5971 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
5972 0 : return false;
5973 : }
5974 0 : self->SetInternal(NonNullHelper(Constify(arg0)));
5975 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
5976 0 : args.rval().setUndefined();
5977 0 : return true;
5978 : }
5979 :
5980 : static const JSJitInfo setInternal_methodinfo = {
5981 : { (JSJitGetterOp)setInternal },
5982 : { prototypes::id::TestInterfaceMaplikeObject },
5983 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
5984 : JSJitInfo::Method,
5985 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
5986 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
5987 : false, /* isInfallible. False in setters. */
5988 : false, /* isMovable. Not relevant for setters. */
5989 : false, /* isEliminatable. Not relevant for setters. */
5990 : false, /* isAlwaysInSlot. Only relevant for getters. */
5991 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
5992 : false, /* isTypedMethod. Only relevant for methods. */
5993 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
5994 : };
5995 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
5996 : static_assert(0 < 2, "There is no slot for us");
5997 :
5998 : static bool
5999 0 : clearInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
6000 : {
6001 0 : self->ClearInternal();
6002 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
6003 0 : args.rval().setUndefined();
6004 0 : return true;
6005 : }
6006 :
6007 : static const JSJitInfo clearInternal_methodinfo = {
6008 : { (JSJitGetterOp)clearInternal },
6009 : { prototypes::id::TestInterfaceMaplikeObject },
6010 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6011 : JSJitInfo::Method,
6012 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
6013 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
6014 : true, /* isInfallible. False in setters. */
6015 : false, /* isMovable. Not relevant for setters. */
6016 : false, /* isEliminatable. Not relevant for setters. */
6017 : false, /* isAlwaysInSlot. Only relevant for getters. */
6018 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6019 : false, /* isTypedMethod. Only relevant for methods. */
6020 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6021 : };
6022 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6023 : static_assert(0 < 2, "There is no slot for us");
6024 :
6025 : static bool
6026 0 : deleteInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
6027 : {
6028 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
6029 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "TestInterfaceMaplikeObject.deleteInternal");
6030 : }
6031 0 : binding_detail::FakeString arg0;
6032 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
6033 0 : return false;
6034 : }
6035 0 : bool result(self->DeleteInternal(NonNullHelper(Constify(arg0))));
6036 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
6037 0 : args.rval().setBoolean(result);
6038 0 : return true;
6039 : }
6040 :
6041 : static const JSJitInfo deleteInternal_methodinfo = {
6042 : { (JSJitGetterOp)deleteInternal },
6043 : { prototypes::id::TestInterfaceMaplikeObject },
6044 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6045 : JSJitInfo::Method,
6046 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
6047 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
6048 : false, /* isInfallible. False in setters. */
6049 : false, /* isMovable. Not relevant for setters. */
6050 : false, /* isEliminatable. Not relevant for setters. */
6051 : false, /* isAlwaysInSlot. Only relevant for getters. */
6052 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6053 : false, /* isTypedMethod. Only relevant for methods. */
6054 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6055 : };
6056 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6057 : static_assert(0 < 2, "There is no slot for us");
6058 :
6059 : static bool
6060 0 : hasInternal(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
6061 : {
6062 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
6063 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "TestInterfaceMaplikeObject.hasInternal");
6064 : }
6065 0 : binding_detail::FakeString arg0;
6066 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
6067 0 : return false;
6068 : }
6069 0 : bool result(self->HasInternal(NonNullHelper(Constify(arg0))));
6070 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
6071 0 : args.rval().setBoolean(result);
6072 0 : return true;
6073 : }
6074 :
6075 : static const JSJitInfo hasInternal_methodinfo = {
6076 : { (JSJitGetterOp)hasInternal },
6077 : { prototypes::id::TestInterfaceMaplikeObject },
6078 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6079 : JSJitInfo::Method,
6080 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
6081 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
6082 : false, /* isInfallible. False in setters. */
6083 : false, /* isMovable. Not relevant for setters. */
6084 : false, /* isEliminatable. Not relevant for setters. */
6085 : false, /* isAlwaysInSlot. Only relevant for getters. */
6086 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6087 : false, /* isTypedMethod. Only relevant for methods. */
6088 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6089 : };
6090 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6091 : static_assert(0 < 2, "There is no slot for us");
6092 :
6093 : static bool
6094 0 : get_size(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, JSJitGetterCallArgs args)
6095 : {
6096 0 : JS::Rooted<JSObject*> backingObj(cx);
6097 0 : bool created = false;
6098 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6099 0 : return false;
6100 : }
6101 0 : if (created) {
6102 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
6103 : }
6104 0 : uint32_t result = JS::MapSize(cx, backingObj);
6105 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
6106 0 : args.rval().setNumber(result);
6107 0 : return true;
6108 : }
6109 :
6110 : static const JSJitInfo size_getterinfo = {
6111 : { (JSJitGetterOp)get_size },
6112 : { prototypes::id::TestInterfaceMaplikeObject },
6113 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6114 : JSJitInfo::Getter,
6115 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
6116 : JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
6117 : true, /* isInfallible. False in setters. */
6118 : false, /* isMovable. Not relevant for setters. */
6119 : false, /* isEliminatable. Not relevant for setters. */
6120 : false, /* isAlwaysInSlot. Only relevant for getters. */
6121 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6122 : false, /* isTypedMethod. Only relevant for methods. */
6123 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6124 : };
6125 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6126 : static_assert(0 < 2, "There is no slot for us");
6127 :
6128 : static bool
6129 0 : entries(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
6130 : {
6131 0 : JS::Rooted<JSObject*> backingObj(cx);
6132 0 : bool created = false;
6133 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6134 0 : return false;
6135 : }
6136 0 : if (created) {
6137 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
6138 : }
6139 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
6140 : // after bug 1023984 is fixed.
6141 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
6142 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
6143 0 : return false;
6144 : }
6145 0 : JS::Rooted<JSObject*> result(cx);
6146 0 : JS::Rooted<JS::Value> v(cx);
6147 0 : if (!JS::MapEntries(cx, backingObj, &v)) {
6148 0 : return false;
6149 : }
6150 0 : result = &v.toObject();
6151 0 : JS::ExposeObjectToActiveJS(result);
6152 0 : args.rval().setObject(*result);
6153 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
6154 0 : return false;
6155 : }
6156 0 : return true;
6157 : }
6158 :
6159 : static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
6160 : static const JSTypedMethodJitInfo entries_methodinfo = {
6161 : {
6162 : { (JSJitGetterOp)entries },
6163 : { prototypes::id::TestInterfaceMaplikeObject },
6164 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6165 : JSJitInfo::Method,
6166 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
6167 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
6168 : false, /* isInfallible. False in setters. */
6169 : false, /* isMovable. Not relevant for setters. */
6170 : false, /* isEliminatable. Not relevant for setters. */
6171 : false, /* isAlwaysInSlot. Only relevant for getters. */
6172 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6173 : true, /* isTypedMethod. Only relevant for methods. */
6174 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6175 : },
6176 : entries_methodinfo_argTypes
6177 : };
6178 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6179 : static_assert(0 < 2, "There is no slot for us");
6180 :
6181 : static bool
6182 0 : keys(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
6183 : {
6184 0 : JS::Rooted<JSObject*> backingObj(cx);
6185 0 : bool created = false;
6186 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6187 0 : return false;
6188 : }
6189 0 : if (created) {
6190 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
6191 : }
6192 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
6193 : // after bug 1023984 is fixed.
6194 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
6195 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
6196 0 : return false;
6197 : }
6198 0 : JS::Rooted<JSObject*> result(cx);
6199 0 : JS::Rooted<JS::Value> v(cx);
6200 0 : if (!JS::MapKeys(cx, backingObj, &v)) {
6201 0 : return false;
6202 : }
6203 0 : result = &v.toObject();
6204 0 : JS::ExposeObjectToActiveJS(result);
6205 0 : args.rval().setObject(*result);
6206 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
6207 0 : return false;
6208 : }
6209 0 : return true;
6210 : }
6211 :
6212 : static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
6213 : static const JSTypedMethodJitInfo keys_methodinfo = {
6214 : {
6215 : { (JSJitGetterOp)keys },
6216 : { prototypes::id::TestInterfaceMaplikeObject },
6217 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6218 : JSJitInfo::Method,
6219 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
6220 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
6221 : false, /* isInfallible. False in setters. */
6222 : false, /* isMovable. Not relevant for setters. */
6223 : false, /* isEliminatable. Not relevant for setters. */
6224 : false, /* isAlwaysInSlot. Only relevant for getters. */
6225 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6226 : true, /* isTypedMethod. Only relevant for methods. */
6227 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6228 : },
6229 : keys_methodinfo_argTypes
6230 : };
6231 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6232 : static_assert(0 < 2, "There is no slot for us");
6233 :
6234 : static bool
6235 0 : values(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
6236 : {
6237 0 : JS::Rooted<JSObject*> backingObj(cx);
6238 0 : bool created = false;
6239 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6240 0 : return false;
6241 : }
6242 0 : if (created) {
6243 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
6244 : }
6245 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
6246 : // after bug 1023984 is fixed.
6247 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
6248 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
6249 0 : return false;
6250 : }
6251 0 : JS::Rooted<JSObject*> result(cx);
6252 0 : JS::Rooted<JS::Value> v(cx);
6253 0 : if (!JS::MapValues(cx, backingObj, &v)) {
6254 0 : return false;
6255 : }
6256 0 : result = &v.toObject();
6257 0 : JS::ExposeObjectToActiveJS(result);
6258 0 : args.rval().setObject(*result);
6259 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
6260 0 : return false;
6261 : }
6262 0 : return true;
6263 : }
6264 :
6265 : static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
6266 : static const JSTypedMethodJitInfo values_methodinfo = {
6267 : {
6268 : { (JSJitGetterOp)values },
6269 : { prototypes::id::TestInterfaceMaplikeObject },
6270 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6271 : JSJitInfo::Method,
6272 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
6273 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
6274 : false, /* isInfallible. False in setters. */
6275 : false, /* isMovable. Not relevant for setters. */
6276 : false, /* isEliminatable. Not relevant for setters. */
6277 : false, /* isAlwaysInSlot. Only relevant for getters. */
6278 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6279 : true, /* isTypedMethod. Only relevant for methods. */
6280 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6281 : },
6282 : values_methodinfo_argTypes
6283 : };
6284 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6285 : static_assert(0 < 2, "There is no slot for us");
6286 :
6287 : static bool
6288 0 : forEach(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
6289 : {
6290 0 : JS::Rooted<JSObject*> arg0(cx);
6291 0 : if (args.get(0).isObject()) {
6292 0 : arg0 = &args.get(0).toObject();
6293 : } else {
6294 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceMaplikeObject.forEach");
6295 0 : return false;
6296 : }
6297 0 : JS::Rooted<JS::Value> arg1(cx);
6298 0 : if (args.hasDefined(1)) {
6299 0 : arg1 = args.get(1);
6300 : } else {
6301 0 : arg1 = JS::UndefinedValue();
6302 : }
6303 0 : JS::Rooted<JSObject*> backingObj(cx);
6304 0 : bool created = false;
6305 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6306 0 : return false;
6307 : }
6308 0 : if (created) {
6309 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
6310 : }
6311 : // Create a wrapper function.
6312 0 : JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
6313 0 : if (!func) {
6314 0 : return false;
6315 : }
6316 0 : JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
6317 0 : JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
6318 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
6319 0 : JS::ObjectValue(*arg0));
6320 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
6321 0 : JS::ObjectValue(*obj));
6322 0 : if (!JS::MapForEach(cx, backingObj, funcVal, arg1)) {
6323 0 : return false;
6324 : }
6325 0 : args.rval().setUndefined();
6326 0 : return true;
6327 : }
6328 :
6329 : static const JSJitInfo forEach_methodinfo = {
6330 : { (JSJitGetterOp)forEach },
6331 : { prototypes::id::TestInterfaceMaplikeObject },
6332 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6333 : JSJitInfo::Method,
6334 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
6335 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
6336 : false, /* isInfallible. False in setters. */
6337 : false, /* isMovable. Not relevant for setters. */
6338 : false, /* isEliminatable. Not relevant for setters. */
6339 : false, /* isAlwaysInSlot. Only relevant for getters. */
6340 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6341 : false, /* isTypedMethod. Only relevant for methods. */
6342 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6343 : };
6344 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6345 : static_assert(0 < 2, "There is no slot for us");
6346 :
6347 : static bool
6348 0 : has(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
6349 : {
6350 0 : binding_detail::FakeString arg0;
6351 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
6352 0 : return false;
6353 : }
6354 0 : JS::Rooted<JSObject*> backingObj(cx);
6355 0 : bool created = false;
6356 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6357 0 : return false;
6358 : }
6359 0 : if (created) {
6360 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
6361 : }
6362 0 : JS::Rooted<JS::Value> arg0Val(cx);
6363 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
6364 0 : return false;
6365 : }
6366 : bool result;
6367 0 : if (!JS::MapHas(cx, backingObj, arg0Val, &result)) {
6368 0 : return false;
6369 : }
6370 0 : args.rval().setBoolean(result);
6371 0 : return true;
6372 : }
6373 :
6374 : static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
6375 : static const JSTypedMethodJitInfo has_methodinfo = {
6376 : {
6377 : { (JSJitGetterOp)has },
6378 : { prototypes::id::TestInterfaceMaplikeObject },
6379 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6380 : JSJitInfo::Method,
6381 : JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
6382 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
6383 : false, /* isInfallible. False in setters. */
6384 : false, /* isMovable. Not relevant for setters. */
6385 : false, /* isEliminatable. Not relevant for setters. */
6386 : false, /* isAlwaysInSlot. Only relevant for getters. */
6387 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6388 : true, /* isTypedMethod. Only relevant for methods. */
6389 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6390 : },
6391 : has_methodinfo_argTypes
6392 : };
6393 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6394 : static_assert(0 < 2, "There is no slot for us");
6395 :
6396 : static bool
6397 0 : get(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceMaplikeObject* self, const JSJitMethodCallArgs& args)
6398 : {
6399 0 : binding_detail::FakeString arg0;
6400 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
6401 0 : return false;
6402 : }
6403 0 : JS::Rooted<JSObject*> backingObj(cx);
6404 0 : bool created = false;
6405 0 : if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6406 0 : return false;
6407 : }
6408 0 : if (created) {
6409 0 : PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
6410 : }
6411 0 : JS::Rooted<JS::Value> arg0Val(cx);
6412 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
6413 0 : return false;
6414 : }
6415 0 : JS::Rooted<JS::Value> result(cx);
6416 0 : if (!JS::MapGet(cx, backingObj, arg0Val, &result)) {
6417 0 : return false;
6418 : }
6419 0 : JS::ExposeValueToActiveJS(result);
6420 0 : args.rval().set(result);
6421 0 : if (!MaybeWrapValue(cx, args.rval())) {
6422 0 : return false;
6423 : }
6424 0 : return true;
6425 : }
6426 :
6427 : static const JSJitInfo::ArgType get_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
6428 : static const JSTypedMethodJitInfo get_methodinfo = {
6429 : {
6430 : { (JSJitGetterOp)get },
6431 : { prototypes::id::TestInterfaceMaplikeObject },
6432 : { PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
6433 : JSJitInfo::Method,
6434 : JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
6435 : JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */
6436 : false, /* isInfallible. False in setters. */
6437 : false, /* isMovable. Not relevant for setters. */
6438 : false, /* isEliminatable. Not relevant for setters. */
6439 : false, /* isAlwaysInSlot. Only relevant for getters. */
6440 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
6441 : true, /* isTypedMethod. Only relevant for methods. */
6442 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
6443 : },
6444 : get_methodinfo_argTypes
6445 : };
6446 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
6447 : static_assert(0 < 2, "There is no slot for us");
6448 :
6449 : static bool
6450 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
6451 : {
6452 0 : mozilla::dom::TestInterfaceMaplikeObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeObject>(obj);
6453 : // We don't want to preserve if we don't have a wrapper, and we
6454 : // obviously can't preserve if we're not initialized.
6455 0 : if (self && self->GetWrapperPreserveColor()) {
6456 0 : PreserveWrapper(self);
6457 : }
6458 0 : return true;
6459 : }
6460 :
6461 : static void
6462 0 : _finalize(js::FreeOp* fop, JSObject* obj)
6463 : {
6464 0 : mozilla::dom::TestInterfaceMaplikeObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeObject>(obj);
6465 0 : if (self) {
6466 0 : ClearWrapper(self, self, obj);
6467 0 : AddForDeferredFinalization<mozilla::dom::TestInterfaceMaplikeObject>(self);
6468 : }
6469 0 : }
6470 :
6471 : static void
6472 0 : _objectMoved(JSObject* obj, const JSObject* old)
6473 : {
6474 0 : mozilla::dom::TestInterfaceMaplikeObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeObject>(obj);
6475 0 : if (self) {
6476 0 : UpdateWrapper(self, self, obj, old);
6477 : }
6478 0 : }
6479 :
6480 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
6481 : #if defined(__clang__)
6482 : #pragma clang diagnostic push
6483 : #pragma clang diagnostic ignored "-Wmissing-braces"
6484 : #endif
6485 : static const JSFunctionSpec sMethods_specs[] = {
6486 : JS_FNSPEC("setInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&setInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
6487 : JS_FNSPEC("clearInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&clearInternal_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
6488 : JS_FNSPEC("deleteInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&deleteInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
6489 : JS_FNSPEC("hasInternal", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&hasInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
6490 : JS_FNSPEC("entries", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, 0, nullptr),
6491 : JS_FNSPEC("keys", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, 0, nullptr),
6492 : JS_FNSPEC("values", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, 0, nullptr),
6493 : JS_FNSPEC("forEach", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, 0, nullptr),
6494 : JS_FNSPEC("has", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, 0, nullptr),
6495 : JS_FNSPEC("get", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&get_methodinfo), 1, 0, nullptr),
6496 : JS_FS_END
6497 : };
6498 : #if defined(__clang__)
6499 : #pragma clang diagnostic pop
6500 : #endif
6501 :
6502 :
6503 : // Can't be const because the pref-enabled boolean needs to be writable
6504 : static Prefable<const JSFunctionSpec> sMethods[] = {
6505 : { nullptr, &sMethods_specs[0] },
6506 : { nullptr, nullptr }
6507 : };
6508 :
6509 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
6510 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
6511 : static_assert(10 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
6512 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
6513 :
6514 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
6515 : #if defined(__clang__)
6516 : #pragma clang diagnostic push
6517 : #pragma clang diagnostic ignored "-Wmissing-braces"
6518 : #endif
6519 : static const JSPropertySpec sAttributes_specs[] = {
6520 : { "size", JSPROP_SHARED, GenericBindingGetter, &size_getterinfo, nullptr, nullptr },
6521 : { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
6522 : };
6523 : #if defined(__clang__)
6524 : #pragma clang diagnostic pop
6525 : #endif
6526 :
6527 :
6528 : // Can't be const because the pref-enabled boolean needs to be writable
6529 : static Prefable<const JSPropertySpec> sAttributes[] = {
6530 : { nullptr, &sAttributes_specs[0] },
6531 : { nullptr, nullptr }
6532 : };
6533 :
6534 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
6535 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
6536 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
6537 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
6538 :
6539 :
6540 : static uint16_t sNativeProperties_sortedPropertyIndices[11];
6541 : static PropertyInfo sNativeProperties_propertyInfos[11];
6542 :
6543 : static const NativePropertiesN<2> sNativeProperties = {
6544 : false, 0,
6545 : false, 0,
6546 : true, 0 /* sMethods */,
6547 : true, 1 /* sAttributes */,
6548 : false, 0,
6549 : false, 0,
6550 : false, 0,
6551 : 4,
6552 : 11,
6553 : sNativeProperties_sortedPropertyIndices,
6554 : {
6555 : { sMethods, &sNativeProperties_propertyInfos[0] },
6556 : { sAttributes, &sNativeProperties_propertyInfos[10] }
6557 : }
6558 : };
6559 : static_assert(4 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
6560 : "We have an iterator alias index that is oversized");
6561 : static_assert(11 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
6562 : "We have a property info count that is oversized");
6563 :
6564 : static bool
6565 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
6566 : {
6567 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
6568 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
6569 0 : if (!args.isConstructing()) {
6570 : // XXXbz wish I could get the name from the callee instead of
6571 : // Adding more relocations
6572 0 : return ThrowConstructorWithoutNew(cx, "TestInterfaceMaplikeObject");
6573 : }
6574 :
6575 0 : GlobalObject global(cx, obj);
6576 0 : if (global.Failed()) {
6577 0 : return false;
6578 : }
6579 :
6580 0 : JS::Rooted<JSObject*> desiredProto(cx);
6581 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
6582 0 : return false;
6583 : }
6584 :
6585 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
6586 0 : Maybe<JSAutoCompartment> ac;
6587 0 : if (objIsXray) {
6588 0 : obj = js::CheckedUnwrap(obj);
6589 0 : if (!obj) {
6590 0 : return false;
6591 : }
6592 0 : ac.emplace(cx, obj);
6593 0 : if (!JS_WrapObject(cx, &desiredProto)) {
6594 0 : return false;
6595 : }
6596 : }
6597 0 : binding_detail::FastErrorResult rv;
6598 0 : auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceMaplikeObject>(mozilla::dom::TestInterfaceMaplikeObject::Constructor(global, rv)));
6599 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
6600 0 : return false;
6601 : }
6602 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
6603 : static_assert(!IsPointer<decltype(result)>::value,
6604 : "NewObject implies that we need to keep the object alive with a strong reference.");
6605 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
6606 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
6607 0 : return false;
6608 : }
6609 0 : return true;
6610 : }
6611 :
6612 : static const js::ClassOps sInterfaceObjectClassOps = {
6613 : nullptr, /* addProperty */
6614 : nullptr, /* delProperty */
6615 : nullptr, /* getProperty */
6616 : nullptr, /* setProperty */
6617 : nullptr, /* enumerate */
6618 : nullptr, /* newEnumerate */
6619 : nullptr, /* resolve */
6620 : nullptr, /* mayResolve */
6621 : nullptr, /* finalize */
6622 : _constructor, /* call */
6623 : nullptr, /* hasInstance */
6624 : _constructor, /* construct */
6625 : nullptr, /* trace */
6626 : };
6627 :
6628 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
6629 : {
6630 : "Function",
6631 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
6632 : &sInterfaceObjectClassOps,
6633 : JS_NULL_CLASS_SPEC,
6634 : JS_NULL_CLASS_EXT,
6635 : &sInterfaceObjectClassObjectOps
6636 : },
6637 : eInterface,
6638 : true,
6639 : prototypes::id::TestInterfaceMaplikeObject,
6640 : PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth,
6641 : sNativePropertyHooks,
6642 : "function TestInterfaceMaplikeObject() {\n [native code]\n}",
6643 : JS::GetRealmFunctionPrototype
6644 : };
6645 :
6646 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
6647 : {
6648 : "TestInterfaceMaplikeObjectPrototype",
6649 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
6650 : JS_NULL_CLASS_OPS,
6651 : JS_NULL_CLASS_SPEC,
6652 : JS_NULL_CLASS_EXT,
6653 : JS_NULL_OBJECT_OPS
6654 : },
6655 : eInterfacePrototype,
6656 : false,
6657 : prototypes::id::TestInterfaceMaplikeObject,
6658 : PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth,
6659 : sNativePropertyHooks,
6660 : "[object TestInterfaceMaplikeObjectPrototype]",
6661 : JS::GetRealmObjectPrototype
6662 : };
6663 :
6664 : bool
6665 0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
6666 : {
6667 : static bool sPrefValue;
6668 : static bool sPrefCacheSetUp = false;
6669 0 : if (!sPrefCacheSetUp) {
6670 0 : sPrefCacheSetUp = true;
6671 0 : Preferences::AddBoolVarCache(&sPrefValue, "dom.expose_test_interfaces");
6672 : }
6673 :
6674 0 : return sPrefValue;
6675 : }
6676 :
6677 : JSObject*
6678 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
6679 : {
6680 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
6681 : }
6682 :
6683 : static const js::ClassOps sClassOps = {
6684 : _addProperty, /* addProperty */
6685 : nullptr, /* delProperty */
6686 : nullptr, /* getProperty */
6687 : nullptr, /* setProperty */
6688 : nullptr, /* enumerate */
6689 : nullptr, /* newEnumerate */
6690 : nullptr, /* resolve */
6691 : nullptr, /* mayResolve */
6692 : _finalize, /* finalize */
6693 : nullptr, /* call */
6694 : nullptr, /* hasInstance */
6695 : nullptr, /* construct */
6696 : nullptr, /* trace */
6697 : };
6698 :
6699 : static const js::ClassExtension sClassExtension = {
6700 : nullptr, /* weakmapKeyDelegateOp */
6701 : _objectMoved /* objectMovedOp */
6702 : };
6703 :
6704 : static const DOMJSClass sClass = {
6705 : { "TestInterfaceMaplikeObject",
6706 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
6707 : &sClassOps,
6708 : JS_NULL_CLASS_SPEC,
6709 : &sClassExtension,
6710 : JS_NULL_OBJECT_OPS
6711 : },
6712 : { prototypes::id::TestInterfaceMaplikeObject, 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 },
6713 : IsBaseOf<nsISupports, mozilla::dom::TestInterfaceMaplikeObject >::value,
6714 : sNativePropertyHooks,
6715 : FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceMaplikeObject>::Get,
6716 : GetProtoObjectHandle,
6717 : GetCCParticipant<mozilla::dom::TestInterfaceMaplikeObject>::Get()
6718 : };
6719 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
6720 : "Must have the right minimal number of reserved slots.");
6721 : static_assert(2 >= 2,
6722 : "Must have enough reserved slots.");
6723 :
6724 : const JSClass*
6725 0 : GetJSClass()
6726 : {
6727 0 : return sClass.ToJSClass();
6728 : }
6729 :
6730 : bool
6731 0 : Wrap(JSContext* aCx, mozilla::dom::TestInterfaceMaplikeObject* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
6732 : {
6733 : MOZ_ASSERT(static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(aObject) ==
6734 : reinterpret_cast<mozilla::dom::TestInterfaceMaplikeObject*>(aObject),
6735 : "Multiple inheritance for mozilla::dom::TestInterfaceMaplikeObject is broken.");
6736 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
6737 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
6738 0 : MOZ_ASSERT(!aCache->GetWrapper(),
6739 : "You should probably not be using Wrap() directly; use "
6740 : "GetOrCreateDOMReflector instead");
6741 :
6742 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
6743 : "nsISupports must be on our primary inheritance chain");
6744 :
6745 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
6746 0 : if (!global) {
6747 0 : return false;
6748 : }
6749 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
6750 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
6751 :
6752 : // That might have ended up wrapping us already, due to the wonders
6753 : // of XBL. Check for that, and bail out as needed.
6754 0 : aReflector.set(aCache->GetWrapper());
6755 0 : if (aReflector) {
6756 : #ifdef DEBUG
6757 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
6758 : #endif // DEBUG
6759 0 : return true;
6760 : }
6761 :
6762 0 : JSAutoCompartment ac(aCx, global);
6763 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
6764 0 : if (!canonicalProto) {
6765 0 : return false;
6766 : }
6767 0 : JS::Rooted<JSObject*> proto(aCx);
6768 0 : if (aGivenProto) {
6769 0 : proto = aGivenProto;
6770 : // Unfortunately, while aGivenProto was in the compartment of aCx
6771 : // coming in, we changed compartments to that of "parent" so may need
6772 : // to wrap the proto here.
6773 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
6774 0 : if (!JS_WrapObject(aCx, &proto)) {
6775 0 : return false;
6776 : }
6777 : }
6778 : } else {
6779 0 : proto = canonicalProto;
6780 : }
6781 :
6782 0 : BindingJSObjectCreator<mozilla::dom::TestInterfaceMaplikeObject> creator(aCx);
6783 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
6784 0 : if (!aReflector) {
6785 0 : return false;
6786 : }
6787 :
6788 0 : aCache->SetWrapper(aReflector);
6789 0 : creator.InitializationSucceeded();
6790 :
6791 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
6792 : aCache->GetWrapperPreserveColor() == aReflector);
6793 : // If proto != canonicalProto, we have to preserve our wrapper;
6794 : // otherwise we won't be able to properly recreate it later, since
6795 : // we won't know what proto to use. Note that we don't check
6796 : // aGivenProto here, since it's entirely possible (and even
6797 : // somewhat common) to have a non-null aGivenProto which is the
6798 : // same as canonicalProto.
6799 0 : if (proto != canonicalProto) {
6800 0 : PreserveWrapper(aObject);
6801 : }
6802 :
6803 0 : return true;
6804 : }
6805 :
6806 : // This may allocate too many slots, because we only really need
6807 : // slots for our non-interface-typed members that we cache. But
6808 : // allocating slots only for those would make the slot index
6809 : // computations much more complicated, so let's do this the simple
6810 : // way for now.
6811 : DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
6812 :
6813 : const NativePropertyHooks sNativePropertyHooks[] = { {
6814 : nullptr,
6815 : nullptr,
6816 : nullptr,
6817 : { sNativeProperties.Upcast(), nullptr },
6818 : prototypes::id::TestInterfaceMaplikeObject,
6819 : constructors::id::TestInterfaceMaplikeObject,
6820 : nullptr,
6821 : &sXrayExpandoObjectClass
6822 : } };
6823 :
6824 : void
6825 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
6826 : {
6827 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
6828 0 : if (!parentProto) {
6829 0 : return;
6830 : }
6831 :
6832 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
6833 0 : if (!constructorProto) {
6834 0 : return;
6835 : }
6836 :
6837 : static bool sIdsInited = false;
6838 0 : if (!sIdsInited && NS_IsMainThread()) {
6839 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
6840 0 : return;
6841 : }
6842 0 : sIdsInited = true;
6843 : }
6844 :
6845 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceMaplikeObject);
6846 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceMaplikeObject);
6847 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
6848 : &sPrototypeClass.mBase, protoCache,
6849 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
6850 : interfaceCache,
6851 : sNativeProperties.Upcast(),
6852 : nullptr,
6853 : "TestInterfaceMaplikeObject", aDefineOnGlobal,
6854 : nullptr,
6855 0 : false);
6856 :
6857 : // Set up aliases on the interface prototype object we just created.
6858 0 : JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
6859 0 : if (!proto) {
6860 0 : *protoCache = nullptr;
6861 0 : if (interfaceCache) {
6862 0 : *interfaceCache = nullptr;
6863 : }
6864 0 : return;
6865 : }
6866 :
6867 0 : JS::Rooted<JS::Value> aliasedVal(aCx);
6868 :
6869 0 : if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
6870 0 : *protoCache = nullptr;
6871 0 : if (interfaceCache) {
6872 0 : *interfaceCache = nullptr;
6873 : }
6874 0 : return;
6875 : }
6876 0 : JS::Rooted<jsid> iteratorId(aCx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::iterator)));
6877 0 : if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
6878 0 : *protoCache = nullptr;
6879 0 : if (interfaceCache) {
6880 0 : *interfaceCache = nullptr;
6881 : }
6882 0 : return;
6883 : }
6884 : }
6885 :
6886 : JS::Handle<JSObject*>
6887 0 : GetProtoObjectHandle(JSContext* aCx)
6888 : {
6889 : /* Get the interface prototype object for this class. This will create the
6890 : object as needed. */
6891 0 : bool aDefineOnGlobal = true;
6892 :
6893 : /* Make sure our global is sane. Hopefully we can remove this sometime */
6894 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
6895 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
6896 0 : return nullptr;
6897 : }
6898 :
6899 : /* Check to see whether the interface objects are already installed */
6900 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
6901 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceMaplikeObject)) {
6902 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
6903 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
6904 : }
6905 :
6906 : /*
6907 : * The object might _still_ be null, but that's OK.
6908 : *
6909 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
6910 : * traced by TraceProtoAndIfaceCache() and its contents are never
6911 : * changed after they have been set.
6912 : *
6913 : * Calling address() avoids the read read barrier that does gray
6914 : * unmarking, but it's not possible for the object to be gray here.
6915 : */
6916 :
6917 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceMaplikeObject);
6918 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
6919 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
6920 : }
6921 :
6922 : JS::Handle<JSObject*>
6923 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
6924 : {
6925 : /* Get the interface object for this class. This will create the object as
6926 : needed. */
6927 :
6928 : /* Make sure our global is sane. Hopefully we can remove this sometime */
6929 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
6930 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
6931 0 : return nullptr;
6932 : }
6933 :
6934 : /* Check to see whether the interface objects are already installed */
6935 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
6936 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::TestInterfaceMaplikeObject)) {
6937 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
6938 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
6939 : }
6940 :
6941 : /*
6942 : * The object might _still_ be null, but that's OK.
6943 : *
6944 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
6945 : * traced by TraceProtoAndIfaceCache() and its contents are never
6946 : * changed after they have been set.
6947 : *
6948 : * Calling address() avoids the read read barrier that does gray
6949 : * unmarking, but it's not possible for the object to be gray here.
6950 : */
6951 :
6952 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::TestInterfaceMaplikeObject);
6953 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
6954 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
6955 : }
6956 :
6957 : JSObject*
6958 0 : GetConstructorObject(JSContext* aCx)
6959 : {
6960 0 : return GetConstructorObjectHandle(aCx);
6961 : }
6962 :
6963 : } // namespace TestInterfaceMaplikeObjectBinding
6964 :
6965 :
6966 :
6967 : namespace TestInterfaceSetlikeBinding {
6968 :
6969 : namespace SetlikeHelpers {
6970 : void
6971 0 : Clear(mozilla::dom::TestInterfaceSetlike* self, ErrorResult& aRv)
6972 : {
6973 0 : MOZ_ASSERT(self);
6974 0 : AutoJSAPI jsapi;
6975 0 : jsapi.Init();
6976 0 : JSContext* cx = jsapi.cx();
6977 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
6978 : // all we want is to wrap into _some_ scope and then unwrap to find
6979 : // the reflector, and wrapping has no side-effects.
6980 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
6981 0 : JS::Rooted<JS::Value> v(cx);
6982 0 : if(!ToJSValue(cx, self, &v)) {
6983 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
6984 0 : return;
6985 : }
6986 : // This is a reflector, but due to trying to name things
6987 : // similarly across method generators, it's called obj here.
6988 0 : JS::Rooted<JSObject*> obj(cx);
6989 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
6990 0 : JSAutoCompartment reflectorCompartment(cx, obj);
6991 :
6992 0 : JS::Rooted<JSObject*> backingObj(cx);
6993 0 : bool created = false;
6994 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
6995 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
6996 0 : return;
6997 : }
6998 0 : if (created) {
6999 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7000 : }
7001 0 : if (!JS::SetClear(cx, backingObj)) {
7002 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7003 0 : return;
7004 : }
7005 0 : return;
7006 : }
7007 : bool
7008 0 : Delete(mozilla::dom::TestInterfaceSetlike* self, const nsAString& aKey, ErrorResult& aRv)
7009 : {
7010 0 : MOZ_ASSERT(self);
7011 0 : AutoJSAPI jsapi;
7012 0 : jsapi.Init();
7013 0 : JSContext* cx = jsapi.cx();
7014 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
7015 : // all we want is to wrap into _some_ scope and then unwrap to find
7016 : // the reflector, and wrapping has no side-effects.
7017 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
7018 0 : JS::Rooted<JS::Value> v(cx);
7019 0 : if(!ToJSValue(cx, self, &v)) {
7020 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7021 0 : return false;
7022 : }
7023 : // This is a reflector, but due to trying to name things
7024 : // similarly across method generators, it's called obj here.
7025 0 : JS::Rooted<JSObject*> obj(cx);
7026 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
7027 0 : JSAutoCompartment reflectorCompartment(cx, obj);
7028 : bool aRetVal;
7029 0 : JS::AutoValueVector argv(cx);
7030 0 : if (!argv.resize(1)) {
7031 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
7032 0 : return false;
7033 : }
7034 : do {
7035 0 : nsString mutableStr(aKey);
7036 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
7037 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7038 0 : return false;
7039 : }
7040 0 : break;
7041 : } while (0);
7042 :
7043 0 : JS::Rooted<JSObject*> backingObj(cx);
7044 0 : bool created = false;
7045 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7046 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7047 0 : return false;
7048 : }
7049 0 : if (created) {
7050 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7051 : }
7052 0 : if (!JS::SetDelete(cx, backingObj, argv[0], &aRetVal)) {
7053 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7054 0 : return false;
7055 : }
7056 0 : return aRetVal;
7057 : }
7058 : bool
7059 0 : Has(mozilla::dom::TestInterfaceSetlike* self, const nsAString& aKey, ErrorResult& aRv)
7060 : {
7061 0 : MOZ_ASSERT(self);
7062 0 : AutoJSAPI jsapi;
7063 0 : jsapi.Init();
7064 0 : JSContext* cx = jsapi.cx();
7065 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
7066 : // all we want is to wrap into _some_ scope and then unwrap to find
7067 : // the reflector, and wrapping has no side-effects.
7068 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
7069 0 : JS::Rooted<JS::Value> v(cx);
7070 0 : if(!ToJSValue(cx, self, &v)) {
7071 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7072 0 : return false;
7073 : }
7074 : // This is a reflector, but due to trying to name things
7075 : // similarly across method generators, it's called obj here.
7076 0 : JS::Rooted<JSObject*> obj(cx);
7077 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
7078 0 : JSAutoCompartment reflectorCompartment(cx, obj);
7079 : bool aRetVal;
7080 0 : JS::AutoValueVector argv(cx);
7081 0 : if (!argv.resize(1)) {
7082 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
7083 0 : return false;
7084 : }
7085 : do {
7086 0 : nsString mutableStr(aKey);
7087 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
7088 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7089 0 : return false;
7090 : }
7091 0 : break;
7092 : } while (0);
7093 :
7094 0 : JS::Rooted<JSObject*> backingObj(cx);
7095 0 : bool created = false;
7096 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7097 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7098 0 : return false;
7099 : }
7100 0 : if (created) {
7101 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7102 : }
7103 0 : if (!JS::SetHas(cx, backingObj, argv[0], &aRetVal)) {
7104 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7105 0 : return false;
7106 : }
7107 0 : return aRetVal;
7108 : }
7109 : void
7110 0 : Add(mozilla::dom::TestInterfaceSetlike* self, const nsAString& aKey, ErrorResult& aRv)
7111 : {
7112 0 : MOZ_ASSERT(self);
7113 0 : AutoJSAPI jsapi;
7114 0 : jsapi.Init();
7115 0 : JSContext* cx = jsapi.cx();
7116 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
7117 : // all we want is to wrap into _some_ scope and then unwrap to find
7118 : // the reflector, and wrapping has no side-effects.
7119 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
7120 0 : JS::Rooted<JS::Value> v(cx);
7121 0 : if(!ToJSValue(cx, self, &v)) {
7122 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7123 0 : return;
7124 : }
7125 : // This is a reflector, but due to trying to name things
7126 : // similarly across method generators, it's called obj here.
7127 0 : JS::Rooted<JSObject*> obj(cx);
7128 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
7129 0 : JSAutoCompartment reflectorCompartment(cx, obj);
7130 0 : JS::AutoValueVector argv(cx);
7131 0 : if (!argv.resize(1)) {
7132 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
7133 0 : return;
7134 : }
7135 : do {
7136 0 : nsString mutableStr(aKey);
7137 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
7138 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7139 0 : return;
7140 : }
7141 0 : break;
7142 : } while (0);
7143 :
7144 0 : JS::Rooted<JSObject*> backingObj(cx);
7145 0 : bool created = false;
7146 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7147 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7148 0 : return;
7149 : }
7150 0 : if (created) {
7151 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7152 : }
7153 0 : if (!JS::SetAdd(cx, backingObj, argv[0])) {
7154 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
7155 0 : return;
7156 : }
7157 0 : return;
7158 : }
7159 : } // namespace SetlikeHelpers
7160 :
7161 : static bool
7162 0 : get_size(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlike* self, JSJitGetterCallArgs args)
7163 : {
7164 0 : JS::Rooted<JSObject*> backingObj(cx);
7165 0 : bool created = false;
7166 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7167 0 : return false;
7168 : }
7169 0 : if (created) {
7170 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7171 : }
7172 0 : uint32_t result = JS::SetSize(cx, backingObj);
7173 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
7174 0 : args.rval().setNumber(result);
7175 0 : return true;
7176 : }
7177 :
7178 : static const JSJitInfo size_getterinfo = {
7179 : { (JSJitGetterOp)get_size },
7180 : { prototypes::id::TestInterfaceSetlike },
7181 : { PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
7182 : JSJitInfo::Getter,
7183 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
7184 : JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
7185 : true, /* isInfallible. False in setters. */
7186 : false, /* isMovable. Not relevant for setters. */
7187 : false, /* isEliminatable. Not relevant for setters. */
7188 : false, /* isAlwaysInSlot. Only relevant for getters. */
7189 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
7190 : false, /* isTypedMethod. Only relevant for methods. */
7191 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
7192 : };
7193 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
7194 : static_assert(0 < 2, "There is no slot for us");
7195 :
7196 : static bool
7197 0 : entries(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlike* self, const JSJitMethodCallArgs& args)
7198 : {
7199 0 : JS::Rooted<JSObject*> backingObj(cx);
7200 0 : bool created = false;
7201 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7202 0 : return false;
7203 : }
7204 0 : if (created) {
7205 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7206 : }
7207 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
7208 : // after bug 1023984 is fixed.
7209 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
7210 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
7211 0 : return false;
7212 : }
7213 0 : JS::Rooted<JSObject*> result(cx);
7214 0 : JS::Rooted<JS::Value> v(cx);
7215 0 : if (!JS::SetEntries(cx, backingObj, &v)) {
7216 0 : return false;
7217 : }
7218 0 : result = &v.toObject();
7219 0 : JS::ExposeObjectToActiveJS(result);
7220 0 : args.rval().setObject(*result);
7221 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
7222 0 : return false;
7223 : }
7224 0 : return true;
7225 : }
7226 :
7227 : static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
7228 : static const JSTypedMethodJitInfo entries_methodinfo = {
7229 : {
7230 : { (JSJitGetterOp)entries },
7231 : { prototypes::id::TestInterfaceSetlike },
7232 : { PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
7233 : JSJitInfo::Method,
7234 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
7235 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
7236 : false, /* isInfallible. False in setters. */
7237 : false, /* isMovable. Not relevant for setters. */
7238 : false, /* isEliminatable. Not relevant for setters. */
7239 : false, /* isAlwaysInSlot. Only relevant for getters. */
7240 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
7241 : true, /* isTypedMethod. Only relevant for methods. */
7242 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
7243 : },
7244 : entries_methodinfo_argTypes
7245 : };
7246 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
7247 : static_assert(0 < 2, "There is no slot for us");
7248 :
7249 : static bool
7250 0 : keys(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlike* self, const JSJitMethodCallArgs& args)
7251 : {
7252 0 : JS::Rooted<JSObject*> backingObj(cx);
7253 0 : bool created = false;
7254 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7255 0 : return false;
7256 : }
7257 0 : if (created) {
7258 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7259 : }
7260 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
7261 : // after bug 1023984 is fixed.
7262 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
7263 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
7264 0 : return false;
7265 : }
7266 0 : JS::Rooted<JSObject*> result(cx);
7267 0 : JS::Rooted<JS::Value> v(cx);
7268 0 : if (!JS::SetKeys(cx, backingObj, &v)) {
7269 0 : return false;
7270 : }
7271 0 : result = &v.toObject();
7272 0 : JS::ExposeObjectToActiveJS(result);
7273 0 : args.rval().setObject(*result);
7274 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
7275 0 : return false;
7276 : }
7277 0 : return true;
7278 : }
7279 :
7280 : static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
7281 : static const JSTypedMethodJitInfo keys_methodinfo = {
7282 : {
7283 : { (JSJitGetterOp)keys },
7284 : { prototypes::id::TestInterfaceSetlike },
7285 : { PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
7286 : JSJitInfo::Method,
7287 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
7288 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
7289 : false, /* isInfallible. False in setters. */
7290 : false, /* isMovable. Not relevant for setters. */
7291 : false, /* isEliminatable. Not relevant for setters. */
7292 : false, /* isAlwaysInSlot. Only relevant for getters. */
7293 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
7294 : true, /* isTypedMethod. Only relevant for methods. */
7295 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
7296 : },
7297 : keys_methodinfo_argTypes
7298 : };
7299 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
7300 : static_assert(0 < 2, "There is no slot for us");
7301 :
7302 : static bool
7303 0 : values(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlike* self, const JSJitMethodCallArgs& args)
7304 : {
7305 0 : JS::Rooted<JSObject*> backingObj(cx);
7306 0 : bool created = false;
7307 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7308 0 : return false;
7309 : }
7310 0 : if (created) {
7311 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7312 : }
7313 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
7314 : // after bug 1023984 is fixed.
7315 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
7316 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
7317 0 : return false;
7318 : }
7319 0 : JS::Rooted<JSObject*> result(cx);
7320 0 : JS::Rooted<JS::Value> v(cx);
7321 0 : if (!JS::SetValues(cx, backingObj, &v)) {
7322 0 : return false;
7323 : }
7324 0 : result = &v.toObject();
7325 0 : JS::ExposeObjectToActiveJS(result);
7326 0 : args.rval().setObject(*result);
7327 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
7328 0 : return false;
7329 : }
7330 0 : return true;
7331 : }
7332 :
7333 : static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
7334 : static const JSTypedMethodJitInfo values_methodinfo = {
7335 : {
7336 : { (JSJitGetterOp)values },
7337 : { prototypes::id::TestInterfaceSetlike },
7338 : { PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
7339 : JSJitInfo::Method,
7340 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
7341 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
7342 : false, /* isInfallible. False in setters. */
7343 : false, /* isMovable. Not relevant for setters. */
7344 : false, /* isEliminatable. Not relevant for setters. */
7345 : false, /* isAlwaysInSlot. Only relevant for getters. */
7346 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
7347 : true, /* isTypedMethod. Only relevant for methods. */
7348 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
7349 : },
7350 : values_methodinfo_argTypes
7351 : };
7352 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
7353 : static_assert(0 < 2, "There is no slot for us");
7354 :
7355 : static bool
7356 0 : forEach(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlike* self, const JSJitMethodCallArgs& args)
7357 : {
7358 0 : JS::Rooted<JSObject*> arg0(cx);
7359 0 : if (args.get(0).isObject()) {
7360 0 : arg0 = &args.get(0).toObject();
7361 : } else {
7362 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceSetlike.forEach");
7363 0 : return false;
7364 : }
7365 0 : JS::Rooted<JS::Value> arg1(cx);
7366 0 : if (args.hasDefined(1)) {
7367 0 : arg1 = args.get(1);
7368 : } else {
7369 0 : arg1 = JS::UndefinedValue();
7370 : }
7371 0 : JS::Rooted<JSObject*> backingObj(cx);
7372 0 : bool created = false;
7373 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7374 0 : return false;
7375 : }
7376 0 : if (created) {
7377 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7378 : }
7379 : // Create a wrapper function.
7380 0 : JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
7381 0 : if (!func) {
7382 0 : return false;
7383 : }
7384 0 : JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
7385 0 : JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
7386 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
7387 0 : JS::ObjectValue(*arg0));
7388 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
7389 0 : JS::ObjectValue(*obj));
7390 0 : if (!JS::SetForEach(cx, backingObj, funcVal, arg1)) {
7391 0 : return false;
7392 : }
7393 0 : args.rval().setUndefined();
7394 0 : return true;
7395 : }
7396 :
7397 : static const JSJitInfo forEach_methodinfo = {
7398 : { (JSJitGetterOp)forEach },
7399 : { prototypes::id::TestInterfaceSetlike },
7400 : { PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
7401 : JSJitInfo::Method,
7402 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
7403 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
7404 : false, /* isInfallible. False in setters. */
7405 : false, /* isMovable. Not relevant for setters. */
7406 : false, /* isEliminatable. Not relevant for setters. */
7407 : false, /* isAlwaysInSlot. Only relevant for getters. */
7408 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
7409 : false, /* isTypedMethod. Only relevant for methods. */
7410 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
7411 : };
7412 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
7413 : static_assert(0 < 2, "There is no slot for us");
7414 :
7415 : static bool
7416 0 : has(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlike* self, const JSJitMethodCallArgs& args)
7417 : {
7418 0 : binding_detail::FakeString arg0;
7419 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
7420 0 : return false;
7421 : }
7422 0 : JS::Rooted<JSObject*> backingObj(cx);
7423 0 : bool created = false;
7424 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7425 0 : return false;
7426 : }
7427 0 : if (created) {
7428 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7429 : }
7430 0 : JS::Rooted<JS::Value> arg0Val(cx);
7431 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
7432 0 : return false;
7433 : }
7434 : bool result;
7435 0 : if (!JS::SetHas(cx, backingObj, arg0Val, &result)) {
7436 0 : return false;
7437 : }
7438 0 : args.rval().setBoolean(result);
7439 0 : return true;
7440 : }
7441 :
7442 : static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
7443 : static const JSTypedMethodJitInfo has_methodinfo = {
7444 : {
7445 : { (JSJitGetterOp)has },
7446 : { prototypes::id::TestInterfaceSetlike },
7447 : { PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
7448 : JSJitInfo::Method,
7449 : JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
7450 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
7451 : false, /* isInfallible. False in setters. */
7452 : false, /* isMovable. Not relevant for setters. */
7453 : false, /* isEliminatable. Not relevant for setters. */
7454 : false, /* isAlwaysInSlot. Only relevant for getters. */
7455 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
7456 : true, /* isTypedMethod. Only relevant for methods. */
7457 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
7458 : },
7459 : has_methodinfo_argTypes
7460 : };
7461 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
7462 : static_assert(0 < 2, "There is no slot for us");
7463 :
7464 : static bool
7465 0 : clear(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlike* self, const JSJitMethodCallArgs& args)
7466 : {
7467 0 : JS::Rooted<JSObject*> backingObj(cx);
7468 0 : bool created = false;
7469 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7470 0 : return false;
7471 : }
7472 0 : if (created) {
7473 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7474 : }
7475 0 : if (!JS::SetClear(cx, backingObj)) {
7476 0 : return false;
7477 : }
7478 0 : args.rval().setUndefined();
7479 0 : return true;
7480 : }
7481 :
7482 : static const JSJitInfo clear_methodinfo = {
7483 : { (JSJitGetterOp)clear },
7484 : { prototypes::id::TestInterfaceSetlike },
7485 : { PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
7486 : JSJitInfo::Method,
7487 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
7488 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
7489 : false, /* isInfallible. False in setters. */
7490 : false, /* isMovable. Not relevant for setters. */
7491 : false, /* isEliminatable. Not relevant for setters. */
7492 : false, /* isAlwaysInSlot. Only relevant for getters. */
7493 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
7494 : false, /* isTypedMethod. Only relevant for methods. */
7495 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
7496 : };
7497 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
7498 : static_assert(0 < 2, "There is no slot for us");
7499 :
7500 : static bool
7501 0 : _delete_(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlike* self, const JSJitMethodCallArgs& args)
7502 : {
7503 0 : binding_detail::FakeString arg0;
7504 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
7505 0 : return false;
7506 : }
7507 0 : JS::Rooted<JSObject*> backingObj(cx);
7508 0 : bool created = false;
7509 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7510 0 : return false;
7511 : }
7512 0 : if (created) {
7513 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7514 : }
7515 0 : JS::Rooted<JS::Value> arg0Val(cx);
7516 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
7517 0 : return false;
7518 : }
7519 : bool result;
7520 0 : if (!JS::SetDelete(cx, backingObj, arg0Val, &result)) {
7521 0 : return false;
7522 : }
7523 0 : args.rval().setBoolean(result);
7524 0 : return true;
7525 : }
7526 :
7527 : static const JSJitInfo delete_methodinfo = {
7528 : { (JSJitGetterOp)_delete_ },
7529 : { prototypes::id::TestInterfaceSetlike },
7530 : { PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
7531 : JSJitInfo::Method,
7532 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
7533 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
7534 : false, /* isInfallible. False in setters. */
7535 : false, /* isMovable. Not relevant for setters. */
7536 : false, /* isEliminatable. Not relevant for setters. */
7537 : false, /* isAlwaysInSlot. Only relevant for getters. */
7538 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
7539 : false, /* isTypedMethod. Only relevant for methods. */
7540 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
7541 : };
7542 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
7543 : static_assert(0 < 2, "There is no slot for us");
7544 :
7545 : static bool
7546 0 : add(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlike* self, const JSJitMethodCallArgs& args)
7547 : {
7548 0 : binding_detail::FakeString arg0;
7549 0 : if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
7550 0 : return false;
7551 : }
7552 0 : JS::Rooted<JSObject*> backingObj(cx);
7553 0 : bool created = false;
7554 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
7555 0 : return false;
7556 : }
7557 0 : if (created) {
7558 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
7559 : }
7560 0 : JS::Rooted<JS::Value> arg0Val(cx);
7561 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
7562 0 : return false;
7563 : }
7564 0 : JS::Rooted<JSObject*> result(cx);
7565 0 : if (!JS::SetAdd(cx, backingObj, arg0Val)) {
7566 0 : return false;
7567 : }
7568 0 : result = obj;
7569 0 : JS::ExposeObjectToActiveJS(result);
7570 0 : args.rval().setObject(*result);
7571 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
7572 0 : return false;
7573 : }
7574 0 : return true;
7575 : }
7576 :
7577 : static const JSJitInfo add_methodinfo = {
7578 : { (JSJitGetterOp)add },
7579 : { prototypes::id::TestInterfaceSetlike },
7580 : { PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
7581 : JSJitInfo::Method,
7582 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
7583 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
7584 : false, /* isInfallible. False in setters. */
7585 : false, /* isMovable. Not relevant for setters. */
7586 : false, /* isEliminatable. Not relevant for setters. */
7587 : false, /* isAlwaysInSlot. Only relevant for getters. */
7588 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
7589 : false, /* isTypedMethod. Only relevant for methods. */
7590 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
7591 : };
7592 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
7593 : static_assert(0 < 2, "There is no slot for us");
7594 :
7595 : static bool
7596 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
7597 : {
7598 0 : mozilla::dom::TestInterfaceSetlike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlike>(obj);
7599 : // We don't want to preserve if we don't have a wrapper, and we
7600 : // obviously can't preserve if we're not initialized.
7601 0 : if (self && self->GetWrapperPreserveColor()) {
7602 0 : PreserveWrapper(self);
7603 : }
7604 0 : return true;
7605 : }
7606 :
7607 : static void
7608 0 : _finalize(js::FreeOp* fop, JSObject* obj)
7609 : {
7610 0 : mozilla::dom::TestInterfaceSetlike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlike>(obj);
7611 0 : if (self) {
7612 0 : ClearWrapper(self, self, obj);
7613 0 : AddForDeferredFinalization<mozilla::dom::TestInterfaceSetlike>(self);
7614 : }
7615 0 : }
7616 :
7617 : static void
7618 0 : _objectMoved(JSObject* obj, const JSObject* old)
7619 : {
7620 0 : mozilla::dom::TestInterfaceSetlike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlike>(obj);
7621 0 : if (self) {
7622 0 : UpdateWrapper(self, self, obj, old);
7623 : }
7624 0 : }
7625 :
7626 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
7627 : #if defined(__clang__)
7628 : #pragma clang diagnostic push
7629 : #pragma clang diagnostic ignored "-Wmissing-braces"
7630 : #endif
7631 : static const JSFunctionSpec sMethods_specs[] = {
7632 : JS_FNSPEC("entries", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, 0, nullptr),
7633 : JS_FNSPEC("keys", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, 0, nullptr),
7634 : JS_FNSPEC("values", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, 0, nullptr),
7635 : JS_FNSPEC("forEach", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, 0, nullptr),
7636 : JS_FNSPEC("has", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, 0, nullptr),
7637 : JS_FNSPEC("clear", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&clear_methodinfo), 0, 0, nullptr),
7638 : JS_FNSPEC("delete", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&delete_methodinfo), 1, 0, nullptr),
7639 : JS_FNSPEC("add", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&add_methodinfo), 1, 0, nullptr),
7640 : JS_FS_END
7641 : };
7642 : #if defined(__clang__)
7643 : #pragma clang diagnostic pop
7644 : #endif
7645 :
7646 :
7647 : // Can't be const because the pref-enabled boolean needs to be writable
7648 : static Prefable<const JSFunctionSpec> sMethods[] = {
7649 : { nullptr, &sMethods_specs[0] },
7650 : { nullptr, nullptr }
7651 : };
7652 :
7653 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
7654 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
7655 : static_assert(8 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
7656 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
7657 :
7658 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
7659 : #if defined(__clang__)
7660 : #pragma clang diagnostic push
7661 : #pragma clang diagnostic ignored "-Wmissing-braces"
7662 : #endif
7663 : static const JSPropertySpec sAttributes_specs[] = {
7664 : { "size", JSPROP_SHARED, GenericBindingGetter, &size_getterinfo, nullptr, nullptr },
7665 : { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
7666 : };
7667 : #if defined(__clang__)
7668 : #pragma clang diagnostic pop
7669 : #endif
7670 :
7671 :
7672 : // Can't be const because the pref-enabled boolean needs to be writable
7673 : static Prefable<const JSPropertySpec> sAttributes[] = {
7674 : { nullptr, &sAttributes_specs[0] },
7675 : { nullptr, nullptr }
7676 : };
7677 :
7678 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
7679 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
7680 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
7681 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
7682 :
7683 :
7684 : static uint16_t sNativeProperties_sortedPropertyIndices[9];
7685 : static PropertyInfo sNativeProperties_propertyInfos[9];
7686 :
7687 : static const NativePropertiesN<2> sNativeProperties = {
7688 : false, 0,
7689 : false, 0,
7690 : true, 0 /* sMethods */,
7691 : true, 1 /* sAttributes */,
7692 : false, 0,
7693 : false, 0,
7694 : false, 0,
7695 : 2,
7696 : 9,
7697 : sNativeProperties_sortedPropertyIndices,
7698 : {
7699 : { sMethods, &sNativeProperties_propertyInfos[0] },
7700 : { sAttributes, &sNativeProperties_propertyInfos[8] }
7701 : }
7702 : };
7703 : static_assert(2 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
7704 : "We have an iterator alias index that is oversized");
7705 : static_assert(9 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
7706 : "We have a property info count that is oversized");
7707 :
7708 : static bool
7709 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
7710 : {
7711 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
7712 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
7713 0 : if (!args.isConstructing()) {
7714 : // XXXbz wish I could get the name from the callee instead of
7715 : // Adding more relocations
7716 0 : return ThrowConstructorWithoutNew(cx, "TestInterfaceSetlike");
7717 : }
7718 :
7719 0 : GlobalObject global(cx, obj);
7720 0 : if (global.Failed()) {
7721 0 : return false;
7722 : }
7723 :
7724 0 : JS::Rooted<JSObject*> desiredProto(cx);
7725 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
7726 0 : return false;
7727 : }
7728 :
7729 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
7730 0 : Maybe<JSAutoCompartment> ac;
7731 0 : if (objIsXray) {
7732 0 : obj = js::CheckedUnwrap(obj);
7733 0 : if (!obj) {
7734 0 : return false;
7735 : }
7736 0 : ac.emplace(cx, obj);
7737 0 : if (!JS_WrapObject(cx, &desiredProto)) {
7738 0 : return false;
7739 : }
7740 : }
7741 0 : binding_detail::FastErrorResult rv;
7742 0 : auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceSetlike>(mozilla::dom::TestInterfaceSetlike::Constructor(global, rv)));
7743 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
7744 0 : return false;
7745 : }
7746 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
7747 : static_assert(!IsPointer<decltype(result)>::value,
7748 : "NewObject implies that we need to keep the object alive with a strong reference.");
7749 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
7750 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
7751 0 : return false;
7752 : }
7753 0 : return true;
7754 : }
7755 :
7756 : static const js::ClassOps sInterfaceObjectClassOps = {
7757 : nullptr, /* addProperty */
7758 : nullptr, /* delProperty */
7759 : nullptr, /* getProperty */
7760 : nullptr, /* setProperty */
7761 : nullptr, /* enumerate */
7762 : nullptr, /* newEnumerate */
7763 : nullptr, /* resolve */
7764 : nullptr, /* mayResolve */
7765 : nullptr, /* finalize */
7766 : _constructor, /* call */
7767 : nullptr, /* hasInstance */
7768 : _constructor, /* construct */
7769 : nullptr, /* trace */
7770 : };
7771 :
7772 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
7773 : {
7774 : "Function",
7775 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
7776 : &sInterfaceObjectClassOps,
7777 : JS_NULL_CLASS_SPEC,
7778 : JS_NULL_CLASS_EXT,
7779 : &sInterfaceObjectClassObjectOps
7780 : },
7781 : eInterface,
7782 : true,
7783 : prototypes::id::TestInterfaceSetlike,
7784 : PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth,
7785 : sNativePropertyHooks,
7786 : "function TestInterfaceSetlike() {\n [native code]\n}",
7787 : JS::GetRealmFunctionPrototype
7788 : };
7789 :
7790 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
7791 : {
7792 : "TestInterfaceSetlikePrototype",
7793 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
7794 : JS_NULL_CLASS_OPS,
7795 : JS_NULL_CLASS_SPEC,
7796 : JS_NULL_CLASS_EXT,
7797 : JS_NULL_OBJECT_OPS
7798 : },
7799 : eInterfacePrototype,
7800 : false,
7801 : prototypes::id::TestInterfaceSetlike,
7802 : PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth,
7803 : sNativePropertyHooks,
7804 : "[object TestInterfaceSetlikePrototype]",
7805 : JS::GetRealmObjectPrototype
7806 : };
7807 :
7808 : bool
7809 0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
7810 : {
7811 : static bool sPrefValue;
7812 : static bool sPrefCacheSetUp = false;
7813 0 : if (!sPrefCacheSetUp) {
7814 0 : sPrefCacheSetUp = true;
7815 0 : Preferences::AddBoolVarCache(&sPrefValue, "dom.expose_test_interfaces");
7816 : }
7817 :
7818 0 : return sPrefValue;
7819 : }
7820 :
7821 : JSObject*
7822 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
7823 : {
7824 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
7825 : }
7826 :
7827 : static const js::ClassOps sClassOps = {
7828 : _addProperty, /* addProperty */
7829 : nullptr, /* delProperty */
7830 : nullptr, /* getProperty */
7831 : nullptr, /* setProperty */
7832 : nullptr, /* enumerate */
7833 : nullptr, /* newEnumerate */
7834 : nullptr, /* resolve */
7835 : nullptr, /* mayResolve */
7836 : _finalize, /* finalize */
7837 : nullptr, /* call */
7838 : nullptr, /* hasInstance */
7839 : nullptr, /* construct */
7840 : nullptr, /* trace */
7841 : };
7842 :
7843 : static const js::ClassExtension sClassExtension = {
7844 : nullptr, /* weakmapKeyDelegateOp */
7845 : _objectMoved /* objectMovedOp */
7846 : };
7847 :
7848 : static const DOMJSClass sClass = {
7849 : { "TestInterfaceSetlike",
7850 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
7851 : &sClassOps,
7852 : JS_NULL_CLASS_SPEC,
7853 : &sClassExtension,
7854 : JS_NULL_OBJECT_OPS
7855 : },
7856 : { prototypes::id::TestInterfaceSetlike, 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 },
7857 : IsBaseOf<nsISupports, mozilla::dom::TestInterfaceSetlike >::value,
7858 : sNativePropertyHooks,
7859 : FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceSetlike>::Get,
7860 : GetProtoObjectHandle,
7861 : GetCCParticipant<mozilla::dom::TestInterfaceSetlike>::Get()
7862 : };
7863 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
7864 : "Must have the right minimal number of reserved slots.");
7865 : static_assert(2 >= 2,
7866 : "Must have enough reserved slots.");
7867 :
7868 : const JSClass*
7869 0 : GetJSClass()
7870 : {
7871 0 : return sClass.ToJSClass();
7872 : }
7873 :
7874 : bool
7875 0 : Wrap(JSContext* aCx, mozilla::dom::TestInterfaceSetlike* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
7876 : {
7877 : MOZ_ASSERT(static_cast<mozilla::dom::TestInterfaceSetlike*>(aObject) ==
7878 : reinterpret_cast<mozilla::dom::TestInterfaceSetlike*>(aObject),
7879 : "Multiple inheritance for mozilla::dom::TestInterfaceSetlike is broken.");
7880 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
7881 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
7882 0 : MOZ_ASSERT(!aCache->GetWrapper(),
7883 : "You should probably not be using Wrap() directly; use "
7884 : "GetOrCreateDOMReflector instead");
7885 :
7886 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
7887 : "nsISupports must be on our primary inheritance chain");
7888 :
7889 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
7890 0 : if (!global) {
7891 0 : return false;
7892 : }
7893 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
7894 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
7895 :
7896 : // That might have ended up wrapping us already, due to the wonders
7897 : // of XBL. Check for that, and bail out as needed.
7898 0 : aReflector.set(aCache->GetWrapper());
7899 0 : if (aReflector) {
7900 : #ifdef DEBUG
7901 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
7902 : #endif // DEBUG
7903 0 : return true;
7904 : }
7905 :
7906 0 : JSAutoCompartment ac(aCx, global);
7907 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
7908 0 : if (!canonicalProto) {
7909 0 : return false;
7910 : }
7911 0 : JS::Rooted<JSObject*> proto(aCx);
7912 0 : if (aGivenProto) {
7913 0 : proto = aGivenProto;
7914 : // Unfortunately, while aGivenProto was in the compartment of aCx
7915 : // coming in, we changed compartments to that of "parent" so may need
7916 : // to wrap the proto here.
7917 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
7918 0 : if (!JS_WrapObject(aCx, &proto)) {
7919 0 : return false;
7920 : }
7921 : }
7922 : } else {
7923 0 : proto = canonicalProto;
7924 : }
7925 :
7926 0 : BindingJSObjectCreator<mozilla::dom::TestInterfaceSetlike> creator(aCx);
7927 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
7928 0 : if (!aReflector) {
7929 0 : return false;
7930 : }
7931 :
7932 0 : aCache->SetWrapper(aReflector);
7933 0 : creator.InitializationSucceeded();
7934 :
7935 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
7936 : aCache->GetWrapperPreserveColor() == aReflector);
7937 : // If proto != canonicalProto, we have to preserve our wrapper;
7938 : // otherwise we won't be able to properly recreate it later, since
7939 : // we won't know what proto to use. Note that we don't check
7940 : // aGivenProto here, since it's entirely possible (and even
7941 : // somewhat common) to have a non-null aGivenProto which is the
7942 : // same as canonicalProto.
7943 0 : if (proto != canonicalProto) {
7944 0 : PreserveWrapper(aObject);
7945 : }
7946 :
7947 0 : return true;
7948 : }
7949 :
7950 : // This may allocate too many slots, because we only really need
7951 : // slots for our non-interface-typed members that we cache. But
7952 : // allocating slots only for those would make the slot index
7953 : // computations much more complicated, so let's do this the simple
7954 : // way for now.
7955 : DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
7956 :
7957 : const NativePropertyHooks sNativePropertyHooks[] = { {
7958 : nullptr,
7959 : nullptr,
7960 : nullptr,
7961 : { sNativeProperties.Upcast(), nullptr },
7962 : prototypes::id::TestInterfaceSetlike,
7963 : constructors::id::TestInterfaceSetlike,
7964 : nullptr,
7965 : &sXrayExpandoObjectClass
7966 : } };
7967 :
7968 : void
7969 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
7970 : {
7971 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
7972 0 : if (!parentProto) {
7973 0 : return;
7974 : }
7975 :
7976 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
7977 0 : if (!constructorProto) {
7978 0 : return;
7979 : }
7980 :
7981 : static bool sIdsInited = false;
7982 0 : if (!sIdsInited && NS_IsMainThread()) {
7983 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
7984 0 : return;
7985 : }
7986 0 : sIdsInited = true;
7987 : }
7988 :
7989 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceSetlike);
7990 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceSetlike);
7991 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
7992 : &sPrototypeClass.mBase, protoCache,
7993 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
7994 : interfaceCache,
7995 : sNativeProperties.Upcast(),
7996 : nullptr,
7997 : "TestInterfaceSetlike", aDefineOnGlobal,
7998 : nullptr,
7999 0 : false);
8000 :
8001 : // Set up aliases on the interface prototype object we just created.
8002 0 : JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
8003 0 : if (!proto) {
8004 0 : *protoCache = nullptr;
8005 0 : if (interfaceCache) {
8006 0 : *interfaceCache = nullptr;
8007 : }
8008 0 : return;
8009 : }
8010 :
8011 0 : JS::Rooted<JS::Value> aliasedVal(aCx);
8012 :
8013 0 : if (!JS_GetProperty(aCx, proto, "values", &aliasedVal)) {
8014 0 : *protoCache = nullptr;
8015 0 : if (interfaceCache) {
8016 0 : *interfaceCache = nullptr;
8017 : }
8018 0 : return;
8019 : }
8020 0 : JS::Rooted<jsid> iteratorId(aCx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::iterator)));
8021 0 : if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
8022 0 : *protoCache = nullptr;
8023 0 : if (interfaceCache) {
8024 0 : *interfaceCache = nullptr;
8025 : }
8026 0 : return;
8027 : }
8028 : }
8029 :
8030 : JS::Handle<JSObject*>
8031 0 : GetProtoObjectHandle(JSContext* aCx)
8032 : {
8033 : /* Get the interface prototype object for this class. This will create the
8034 : object as needed. */
8035 0 : bool aDefineOnGlobal = true;
8036 :
8037 : /* Make sure our global is sane. Hopefully we can remove this sometime */
8038 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
8039 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
8040 0 : return nullptr;
8041 : }
8042 :
8043 : /* Check to see whether the interface objects are already installed */
8044 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
8045 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceSetlike)) {
8046 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
8047 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
8048 : }
8049 :
8050 : /*
8051 : * The object might _still_ be null, but that's OK.
8052 : *
8053 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
8054 : * traced by TraceProtoAndIfaceCache() and its contents are never
8055 : * changed after they have been set.
8056 : *
8057 : * Calling address() avoids the read read barrier that does gray
8058 : * unmarking, but it's not possible for the object to be gray here.
8059 : */
8060 :
8061 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceSetlike);
8062 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
8063 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
8064 : }
8065 :
8066 : JS::Handle<JSObject*>
8067 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
8068 : {
8069 : /* Get the interface object for this class. This will create the object as
8070 : needed. */
8071 :
8072 : /* Make sure our global is sane. Hopefully we can remove this sometime */
8073 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
8074 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
8075 0 : return nullptr;
8076 : }
8077 :
8078 : /* Check to see whether the interface objects are already installed */
8079 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
8080 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::TestInterfaceSetlike)) {
8081 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
8082 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
8083 : }
8084 :
8085 : /*
8086 : * The object might _still_ be null, but that's OK.
8087 : *
8088 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
8089 : * traced by TraceProtoAndIfaceCache() and its contents are never
8090 : * changed after they have been set.
8091 : *
8092 : * Calling address() avoids the read read barrier that does gray
8093 : * unmarking, but it's not possible for the object to be gray here.
8094 : */
8095 :
8096 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::TestInterfaceSetlike);
8097 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
8098 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
8099 : }
8100 :
8101 : JSObject*
8102 0 : GetConstructorObject(JSContext* aCx)
8103 : {
8104 0 : return GetConstructorObjectHandle(aCx);
8105 : }
8106 :
8107 : } // namespace TestInterfaceSetlikeBinding
8108 :
8109 :
8110 :
8111 : namespace TestInterfaceSetlikeNodeBinding {
8112 :
8113 : namespace SetlikeHelpers {
8114 : void
8115 0 : Clear(mozilla::dom::TestInterfaceSetlikeNode* self, ErrorResult& aRv)
8116 : {
8117 0 : MOZ_ASSERT(self);
8118 0 : AutoJSAPI jsapi;
8119 0 : jsapi.Init();
8120 0 : JSContext* cx = jsapi.cx();
8121 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
8122 : // all we want is to wrap into _some_ scope and then unwrap to find
8123 : // the reflector, and wrapping has no side-effects.
8124 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
8125 0 : JS::Rooted<JS::Value> v(cx);
8126 0 : if(!ToJSValue(cx, self, &v)) {
8127 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8128 0 : return;
8129 : }
8130 : // This is a reflector, but due to trying to name things
8131 : // similarly across method generators, it's called obj here.
8132 0 : JS::Rooted<JSObject*> obj(cx);
8133 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
8134 0 : JSAutoCompartment reflectorCompartment(cx, obj);
8135 :
8136 0 : JS::Rooted<JSObject*> backingObj(cx);
8137 0 : bool created = false;
8138 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8139 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8140 0 : return;
8141 : }
8142 0 : if (created) {
8143 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8144 : }
8145 0 : if (!JS::SetClear(cx, backingObj)) {
8146 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8147 0 : return;
8148 : }
8149 0 : return;
8150 : }
8151 : bool
8152 0 : Delete(mozilla::dom::TestInterfaceSetlikeNode* self, nsINode& aKey, ErrorResult& aRv)
8153 : {
8154 0 : MOZ_ASSERT(self);
8155 0 : AutoJSAPI jsapi;
8156 0 : jsapi.Init();
8157 0 : JSContext* cx = jsapi.cx();
8158 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
8159 : // all we want is to wrap into _some_ scope and then unwrap to find
8160 : // the reflector, and wrapping has no side-effects.
8161 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
8162 0 : JS::Rooted<JS::Value> v(cx);
8163 0 : if(!ToJSValue(cx, self, &v)) {
8164 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8165 0 : return false;
8166 : }
8167 : // This is a reflector, but due to trying to name things
8168 : // similarly across method generators, it's called obj here.
8169 0 : JS::Rooted<JSObject*> obj(cx);
8170 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
8171 0 : JSAutoCompartment reflectorCompartment(cx, obj);
8172 : bool aRetVal;
8173 0 : JS::AutoValueVector argv(cx);
8174 0 : if (!argv.resize(1)) {
8175 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
8176 0 : return false;
8177 : }
8178 : do {
8179 0 : if (!GetOrCreateDOMReflector(cx, aKey, argv[0])) {
8180 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
8181 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8182 0 : return false;
8183 : }
8184 0 : break;
8185 : } while (0);
8186 :
8187 0 : JS::Rooted<JSObject*> backingObj(cx);
8188 0 : bool created = false;
8189 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8190 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8191 0 : return false;
8192 : }
8193 0 : if (created) {
8194 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8195 : }
8196 0 : if (!JS::SetDelete(cx, backingObj, argv[0], &aRetVal)) {
8197 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8198 0 : return false;
8199 : }
8200 0 : return aRetVal;
8201 : }
8202 : bool
8203 0 : Has(mozilla::dom::TestInterfaceSetlikeNode* self, nsINode& aKey, ErrorResult& aRv)
8204 : {
8205 0 : MOZ_ASSERT(self);
8206 0 : AutoJSAPI jsapi;
8207 0 : jsapi.Init();
8208 0 : JSContext* cx = jsapi.cx();
8209 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
8210 : // all we want is to wrap into _some_ scope and then unwrap to find
8211 : // the reflector, and wrapping has no side-effects.
8212 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
8213 0 : JS::Rooted<JS::Value> v(cx);
8214 0 : if(!ToJSValue(cx, self, &v)) {
8215 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8216 0 : return false;
8217 : }
8218 : // This is a reflector, but due to trying to name things
8219 : // similarly across method generators, it's called obj here.
8220 0 : JS::Rooted<JSObject*> obj(cx);
8221 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
8222 0 : JSAutoCompartment reflectorCompartment(cx, obj);
8223 : bool aRetVal;
8224 0 : JS::AutoValueVector argv(cx);
8225 0 : if (!argv.resize(1)) {
8226 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
8227 0 : return false;
8228 : }
8229 : do {
8230 0 : if (!GetOrCreateDOMReflector(cx, aKey, argv[0])) {
8231 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
8232 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8233 0 : return false;
8234 : }
8235 0 : break;
8236 : } while (0);
8237 :
8238 0 : JS::Rooted<JSObject*> backingObj(cx);
8239 0 : bool created = false;
8240 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8241 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8242 0 : return false;
8243 : }
8244 0 : if (created) {
8245 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8246 : }
8247 0 : if (!JS::SetHas(cx, backingObj, argv[0], &aRetVal)) {
8248 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8249 0 : return false;
8250 : }
8251 0 : return aRetVal;
8252 : }
8253 : void
8254 0 : Add(mozilla::dom::TestInterfaceSetlikeNode* self, nsINode& aKey, ErrorResult& aRv)
8255 : {
8256 0 : MOZ_ASSERT(self);
8257 0 : AutoJSAPI jsapi;
8258 0 : jsapi.Init();
8259 0 : JSContext* cx = jsapi.cx();
8260 : // It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
8261 : // all we want is to wrap into _some_ scope and then unwrap to find
8262 : // the reflector, and wrapping has no side-effects.
8263 0 : JSAutoCompartment tempCompartment(cx, binding_detail::UnprivilegedJunkScopeOrWorkerGlobal());
8264 0 : JS::Rooted<JS::Value> v(cx);
8265 0 : if(!ToJSValue(cx, self, &v)) {
8266 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8267 0 : return;
8268 : }
8269 : // This is a reflector, but due to trying to name things
8270 : // similarly across method generators, it's called obj here.
8271 0 : JS::Rooted<JSObject*> obj(cx);
8272 0 : obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
8273 0 : JSAutoCompartment reflectorCompartment(cx, obj);
8274 0 : JS::AutoValueVector argv(cx);
8275 0 : if (!argv.resize(1)) {
8276 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
8277 0 : return;
8278 : }
8279 : do {
8280 0 : if (!GetOrCreateDOMReflector(cx, aKey, argv[0])) {
8281 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
8282 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8283 0 : return;
8284 : }
8285 0 : break;
8286 : } while (0);
8287 :
8288 0 : JS::Rooted<JSObject*> backingObj(cx);
8289 0 : bool created = false;
8290 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8291 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8292 0 : return;
8293 : }
8294 0 : if (created) {
8295 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8296 : }
8297 0 : if (!JS::SetAdd(cx, backingObj, argv[0])) {
8298 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
8299 0 : return;
8300 : }
8301 0 : return;
8302 : }
8303 : } // namespace SetlikeHelpers
8304 :
8305 : static bool
8306 0 : get_size(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlikeNode* self, JSJitGetterCallArgs args)
8307 : {
8308 0 : JS::Rooted<JSObject*> backingObj(cx);
8309 0 : bool created = false;
8310 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8311 0 : return false;
8312 : }
8313 0 : if (created) {
8314 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8315 : }
8316 0 : uint32_t result = JS::SetSize(cx, backingObj);
8317 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
8318 0 : args.rval().setNumber(result);
8319 0 : return true;
8320 : }
8321 :
8322 : static const JSJitInfo size_getterinfo = {
8323 : { (JSJitGetterOp)get_size },
8324 : { prototypes::id::TestInterfaceSetlikeNode },
8325 : { PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
8326 : JSJitInfo::Getter,
8327 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
8328 : JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
8329 : true, /* isInfallible. False in setters. */
8330 : false, /* isMovable. Not relevant for setters. */
8331 : false, /* isEliminatable. Not relevant for setters. */
8332 : false, /* isAlwaysInSlot. Only relevant for getters. */
8333 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
8334 : false, /* isTypedMethod. Only relevant for methods. */
8335 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
8336 : };
8337 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
8338 : static_assert(0 < 2, "There is no slot for us");
8339 :
8340 : static bool
8341 0 : entries(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlikeNode* self, const JSJitMethodCallArgs& args)
8342 : {
8343 0 : JS::Rooted<JSObject*> backingObj(cx);
8344 0 : bool created = false;
8345 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8346 0 : return false;
8347 : }
8348 0 : if (created) {
8349 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8350 : }
8351 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
8352 : // after bug 1023984 is fixed.
8353 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
8354 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
8355 0 : return false;
8356 : }
8357 0 : JS::Rooted<JSObject*> result(cx);
8358 0 : JS::Rooted<JS::Value> v(cx);
8359 0 : if (!JS::SetEntries(cx, backingObj, &v)) {
8360 0 : return false;
8361 : }
8362 0 : result = &v.toObject();
8363 0 : JS::ExposeObjectToActiveJS(result);
8364 0 : args.rval().setObject(*result);
8365 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
8366 0 : return false;
8367 : }
8368 0 : return true;
8369 : }
8370 :
8371 : static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
8372 : static const JSTypedMethodJitInfo entries_methodinfo = {
8373 : {
8374 : { (JSJitGetterOp)entries },
8375 : { prototypes::id::TestInterfaceSetlikeNode },
8376 : { PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
8377 : JSJitInfo::Method,
8378 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
8379 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
8380 : false, /* isInfallible. False in setters. */
8381 : false, /* isMovable. Not relevant for setters. */
8382 : false, /* isEliminatable. Not relevant for setters. */
8383 : false, /* isAlwaysInSlot. Only relevant for getters. */
8384 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
8385 : true, /* isTypedMethod. Only relevant for methods. */
8386 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
8387 : },
8388 : entries_methodinfo_argTypes
8389 : };
8390 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
8391 : static_assert(0 < 2, "There is no slot for us");
8392 :
8393 : static bool
8394 0 : keys(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlikeNode* self, const JSJitMethodCallArgs& args)
8395 : {
8396 0 : JS::Rooted<JSObject*> backingObj(cx);
8397 0 : bool created = false;
8398 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8399 0 : return false;
8400 : }
8401 0 : if (created) {
8402 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8403 : }
8404 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
8405 : // after bug 1023984 is fixed.
8406 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
8407 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
8408 0 : return false;
8409 : }
8410 0 : JS::Rooted<JSObject*> result(cx);
8411 0 : JS::Rooted<JS::Value> v(cx);
8412 0 : if (!JS::SetKeys(cx, backingObj, &v)) {
8413 0 : return false;
8414 : }
8415 0 : result = &v.toObject();
8416 0 : JS::ExposeObjectToActiveJS(result);
8417 0 : args.rval().setObject(*result);
8418 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
8419 0 : return false;
8420 : }
8421 0 : return true;
8422 : }
8423 :
8424 : static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
8425 : static const JSTypedMethodJitInfo keys_methodinfo = {
8426 : {
8427 : { (JSJitGetterOp)keys },
8428 : { prototypes::id::TestInterfaceSetlikeNode },
8429 : { PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
8430 : JSJitInfo::Method,
8431 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
8432 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
8433 : false, /* isInfallible. False in setters. */
8434 : false, /* isMovable. Not relevant for setters. */
8435 : false, /* isEliminatable. Not relevant for setters. */
8436 : false, /* isAlwaysInSlot. Only relevant for getters. */
8437 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
8438 : true, /* isTypedMethod. Only relevant for methods. */
8439 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
8440 : },
8441 : keys_methodinfo_argTypes
8442 : };
8443 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
8444 : static_assert(0 < 2, "There is no slot for us");
8445 :
8446 : static bool
8447 0 : values(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlikeNode* self, const JSJitMethodCallArgs& args)
8448 : {
8449 0 : JS::Rooted<JSObject*> backingObj(cx);
8450 0 : bool created = false;
8451 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8452 0 : return false;
8453 : }
8454 0 : if (created) {
8455 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8456 : }
8457 : // TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
8458 : // after bug 1023984 is fixed.
8459 0 : if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
8460 0 : JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
8461 0 : return false;
8462 : }
8463 0 : JS::Rooted<JSObject*> result(cx);
8464 0 : JS::Rooted<JS::Value> v(cx);
8465 0 : if (!JS::SetValues(cx, backingObj, &v)) {
8466 0 : return false;
8467 : }
8468 0 : result = &v.toObject();
8469 0 : JS::ExposeObjectToActiveJS(result);
8470 0 : args.rval().setObject(*result);
8471 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
8472 0 : return false;
8473 : }
8474 0 : return true;
8475 : }
8476 :
8477 : static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
8478 : static const JSTypedMethodJitInfo values_methodinfo = {
8479 : {
8480 : { (JSJitGetterOp)values },
8481 : { prototypes::id::TestInterfaceSetlikeNode },
8482 : { PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
8483 : JSJitInfo::Method,
8484 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
8485 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
8486 : false, /* isInfallible. False in setters. */
8487 : false, /* isMovable. Not relevant for setters. */
8488 : false, /* isEliminatable. Not relevant for setters. */
8489 : false, /* isAlwaysInSlot. Only relevant for getters. */
8490 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
8491 : true, /* isTypedMethod. Only relevant for methods. */
8492 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
8493 : },
8494 : values_methodinfo_argTypes
8495 : };
8496 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
8497 : static_assert(0 < 2, "There is no slot for us");
8498 :
8499 : static bool
8500 0 : forEach(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlikeNode* self, const JSJitMethodCallArgs& args)
8501 : {
8502 0 : JS::Rooted<JSObject*> arg0(cx);
8503 0 : if (args.get(0).isObject()) {
8504 0 : arg0 = &args.get(0).toObject();
8505 : } else {
8506 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceSetlikeNode.forEach");
8507 0 : return false;
8508 : }
8509 0 : JS::Rooted<JS::Value> arg1(cx);
8510 0 : if (args.hasDefined(1)) {
8511 0 : arg1 = args.get(1);
8512 : } else {
8513 0 : arg1 = JS::UndefinedValue();
8514 : }
8515 0 : JS::Rooted<JSObject*> backingObj(cx);
8516 0 : bool created = false;
8517 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8518 0 : return false;
8519 : }
8520 0 : if (created) {
8521 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8522 : }
8523 : // Create a wrapper function.
8524 0 : JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
8525 0 : if (!func) {
8526 0 : return false;
8527 : }
8528 0 : JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
8529 0 : JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
8530 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
8531 0 : JS::ObjectValue(*arg0));
8532 0 : js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
8533 0 : JS::ObjectValue(*obj));
8534 0 : if (!JS::SetForEach(cx, backingObj, funcVal, arg1)) {
8535 0 : return false;
8536 : }
8537 0 : args.rval().setUndefined();
8538 0 : return true;
8539 : }
8540 :
8541 : static const JSJitInfo forEach_methodinfo = {
8542 : { (JSJitGetterOp)forEach },
8543 : { prototypes::id::TestInterfaceSetlikeNode },
8544 : { PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
8545 : JSJitInfo::Method,
8546 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
8547 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
8548 : false, /* isInfallible. False in setters. */
8549 : false, /* isMovable. Not relevant for setters. */
8550 : false, /* isEliminatable. Not relevant for setters. */
8551 : false, /* isAlwaysInSlot. Only relevant for getters. */
8552 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
8553 : false, /* isTypedMethod. Only relevant for methods. */
8554 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
8555 : };
8556 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
8557 : static_assert(0 < 2, "There is no slot for us");
8558 :
8559 : static bool
8560 0 : has(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlikeNode* self, const JSJitMethodCallArgs& args)
8561 : {
8562 0 : NonNull<nsINode> arg0;
8563 0 : if (args.get(0).isObject()) {
8564 : {
8565 0 : nsresult rv = UnwrapObject<prototypes::id::Node, nsINode>(args[0], arg0);
8566 0 : if (NS_FAILED(rv)) {
8567 0 : ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 1 of TestInterfaceSetlikeNode.has", "Node");
8568 0 : return false;
8569 : }
8570 : }
8571 : } else {
8572 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceSetlikeNode.has");
8573 0 : return false;
8574 : }
8575 0 : JS::Rooted<JSObject*> backingObj(cx);
8576 0 : bool created = false;
8577 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8578 0 : return false;
8579 : }
8580 0 : if (created) {
8581 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8582 : }
8583 0 : JS::Rooted<JS::Value> arg0Val(cx);
8584 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
8585 0 : return false;
8586 : }
8587 : bool result;
8588 0 : if (!JS::SetHas(cx, backingObj, arg0Val, &result)) {
8589 0 : return false;
8590 : }
8591 0 : args.rval().setBoolean(result);
8592 0 : return true;
8593 : }
8594 :
8595 : static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::Object, JSJitInfo::ArgTypeListEnd };
8596 : static const JSTypedMethodJitInfo has_methodinfo = {
8597 : {
8598 : { (JSJitGetterOp)has },
8599 : { prototypes::id::TestInterfaceSetlikeNode },
8600 : { PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
8601 : JSJitInfo::Method,
8602 : JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
8603 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
8604 : false, /* isInfallible. False in setters. */
8605 : false, /* isMovable. Not relevant for setters. */
8606 : false, /* isEliminatable. Not relevant for setters. */
8607 : false, /* isAlwaysInSlot. Only relevant for getters. */
8608 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
8609 : true, /* isTypedMethod. Only relevant for methods. */
8610 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
8611 : },
8612 : has_methodinfo_argTypes
8613 : };
8614 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
8615 : static_assert(0 < 2, "There is no slot for us");
8616 :
8617 : static bool
8618 0 : clear(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlikeNode* self, const JSJitMethodCallArgs& args)
8619 : {
8620 0 : JS::Rooted<JSObject*> backingObj(cx);
8621 0 : bool created = false;
8622 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8623 0 : return false;
8624 : }
8625 0 : if (created) {
8626 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8627 : }
8628 0 : if (!JS::SetClear(cx, backingObj)) {
8629 0 : return false;
8630 : }
8631 0 : args.rval().setUndefined();
8632 0 : return true;
8633 : }
8634 :
8635 : static const JSJitInfo clear_methodinfo = {
8636 : { (JSJitGetterOp)clear },
8637 : { prototypes::id::TestInterfaceSetlikeNode },
8638 : { PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
8639 : JSJitInfo::Method,
8640 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
8641 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
8642 : false, /* isInfallible. False in setters. */
8643 : false, /* isMovable. Not relevant for setters. */
8644 : false, /* isEliminatable. Not relevant for setters. */
8645 : false, /* isAlwaysInSlot. Only relevant for getters. */
8646 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
8647 : false, /* isTypedMethod. Only relevant for methods. */
8648 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
8649 : };
8650 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
8651 : static_assert(0 < 2, "There is no slot for us");
8652 :
8653 : static bool
8654 0 : _delete_(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlikeNode* self, const JSJitMethodCallArgs& args)
8655 : {
8656 0 : NonNull<nsINode> arg0;
8657 0 : if (args.get(0).isObject()) {
8658 : {
8659 0 : nsresult rv = UnwrapObject<prototypes::id::Node, nsINode>(args[0], arg0);
8660 0 : if (NS_FAILED(rv)) {
8661 0 : ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 1 of TestInterfaceSetlikeNode.delete", "Node");
8662 0 : return false;
8663 : }
8664 : }
8665 : } else {
8666 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceSetlikeNode.delete");
8667 0 : return false;
8668 : }
8669 0 : JS::Rooted<JSObject*> backingObj(cx);
8670 0 : bool created = false;
8671 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8672 0 : return false;
8673 : }
8674 0 : if (created) {
8675 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8676 : }
8677 0 : JS::Rooted<JS::Value> arg0Val(cx);
8678 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
8679 0 : return false;
8680 : }
8681 : bool result;
8682 0 : if (!JS::SetDelete(cx, backingObj, arg0Val, &result)) {
8683 0 : return false;
8684 : }
8685 0 : args.rval().setBoolean(result);
8686 0 : return true;
8687 : }
8688 :
8689 : static const JSJitInfo delete_methodinfo = {
8690 : { (JSJitGetterOp)_delete_ },
8691 : { prototypes::id::TestInterfaceSetlikeNode },
8692 : { PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
8693 : JSJitInfo::Method,
8694 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
8695 : JSVAL_TYPE_BOOLEAN, /* returnType. Not relevant for setters. */
8696 : false, /* isInfallible. False in setters. */
8697 : false, /* isMovable. Not relevant for setters. */
8698 : false, /* isEliminatable. Not relevant for setters. */
8699 : false, /* isAlwaysInSlot. Only relevant for getters. */
8700 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
8701 : false, /* isTypedMethod. Only relevant for methods. */
8702 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
8703 : };
8704 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
8705 : static_assert(0 < 2, "There is no slot for us");
8706 :
8707 : static bool
8708 0 : add(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::TestInterfaceSetlikeNode* self, const JSJitMethodCallArgs& args)
8709 : {
8710 0 : NonNull<nsINode> arg0;
8711 0 : if (args.get(0).isObject()) {
8712 : {
8713 0 : nsresult rv = UnwrapObject<prototypes::id::Node, nsINode>(args[0], arg0);
8714 0 : if (NS_FAILED(rv)) {
8715 0 : ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "Argument 1 of TestInterfaceSetlikeNode.add", "Node");
8716 0 : return false;
8717 : }
8718 : }
8719 : } else {
8720 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceSetlikeNode.add");
8721 0 : return false;
8722 : }
8723 0 : JS::Rooted<JSObject*> backingObj(cx);
8724 0 : bool created = false;
8725 0 : if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
8726 0 : return false;
8727 : }
8728 0 : if (created) {
8729 0 : PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
8730 : }
8731 0 : JS::Rooted<JS::Value> arg0Val(cx);
8732 0 : if (!ToJSValue(cx, arg0, &arg0Val)) {
8733 0 : return false;
8734 : }
8735 0 : JS::Rooted<JSObject*> result(cx);
8736 0 : if (!JS::SetAdd(cx, backingObj, arg0Val)) {
8737 0 : return false;
8738 : }
8739 0 : result = obj;
8740 0 : JS::ExposeObjectToActiveJS(result);
8741 0 : args.rval().setObject(*result);
8742 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
8743 0 : return false;
8744 : }
8745 0 : return true;
8746 : }
8747 :
8748 : static const JSJitInfo add_methodinfo = {
8749 : { (JSJitGetterOp)add },
8750 : { prototypes::id::TestInterfaceSetlikeNode },
8751 : { PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
8752 : JSJitInfo::Method,
8753 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
8754 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
8755 : false, /* isInfallible. False in setters. */
8756 : false, /* isMovable. Not relevant for setters. */
8757 : false, /* isEliminatable. Not relevant for setters. */
8758 : false, /* isAlwaysInSlot. Only relevant for getters. */
8759 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
8760 : false, /* isTypedMethod. Only relevant for methods. */
8761 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
8762 : };
8763 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
8764 : static_assert(0 < 2, "There is no slot for us");
8765 :
8766 : static bool
8767 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
8768 : {
8769 0 : mozilla::dom::TestInterfaceSetlikeNode* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlikeNode>(obj);
8770 : // We don't want to preserve if we don't have a wrapper, and we
8771 : // obviously can't preserve if we're not initialized.
8772 0 : if (self && self->GetWrapperPreserveColor()) {
8773 0 : PreserveWrapper(self);
8774 : }
8775 0 : return true;
8776 : }
8777 :
8778 : static void
8779 0 : _finalize(js::FreeOp* fop, JSObject* obj)
8780 : {
8781 0 : mozilla::dom::TestInterfaceSetlikeNode* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlikeNode>(obj);
8782 0 : if (self) {
8783 0 : ClearWrapper(self, self, obj);
8784 0 : AddForDeferredFinalization<mozilla::dom::TestInterfaceSetlikeNode>(self);
8785 : }
8786 0 : }
8787 :
8788 : static void
8789 0 : _objectMoved(JSObject* obj, const JSObject* old)
8790 : {
8791 0 : mozilla::dom::TestInterfaceSetlikeNode* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlikeNode>(obj);
8792 0 : if (self) {
8793 0 : UpdateWrapper(self, self, obj, old);
8794 : }
8795 0 : }
8796 :
8797 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
8798 : #if defined(__clang__)
8799 : #pragma clang diagnostic push
8800 : #pragma clang diagnostic ignored "-Wmissing-braces"
8801 : #endif
8802 : static const JSFunctionSpec sMethods_specs[] = {
8803 : JS_FNSPEC("entries", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, 0, nullptr),
8804 : JS_FNSPEC("keys", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, 0, nullptr),
8805 : JS_FNSPEC("values", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, 0, nullptr),
8806 : JS_FNSPEC("forEach", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, 0, nullptr),
8807 : JS_FNSPEC("has", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, 0, nullptr),
8808 : JS_FNSPEC("clear", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&clear_methodinfo), 0, 0, nullptr),
8809 : JS_FNSPEC("delete", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&delete_methodinfo), 1, 0, nullptr),
8810 : JS_FNSPEC("add", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&add_methodinfo), 1, 0, nullptr),
8811 : JS_FS_END
8812 : };
8813 : #if defined(__clang__)
8814 : #pragma clang diagnostic pop
8815 : #endif
8816 :
8817 :
8818 : // Can't be const because the pref-enabled boolean needs to be writable
8819 : static Prefable<const JSFunctionSpec> sMethods[] = {
8820 : { nullptr, &sMethods_specs[0] },
8821 : { nullptr, nullptr }
8822 : };
8823 :
8824 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
8825 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
8826 : static_assert(8 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
8827 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
8828 :
8829 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
8830 : #if defined(__clang__)
8831 : #pragma clang diagnostic push
8832 : #pragma clang diagnostic ignored "-Wmissing-braces"
8833 : #endif
8834 : static const JSPropertySpec sAttributes_specs[] = {
8835 : { "size", JSPROP_SHARED, GenericBindingGetter, &size_getterinfo, nullptr, nullptr },
8836 : { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
8837 : };
8838 : #if defined(__clang__)
8839 : #pragma clang diagnostic pop
8840 : #endif
8841 :
8842 :
8843 : // Can't be const because the pref-enabled boolean needs to be writable
8844 : static Prefable<const JSPropertySpec> sAttributes[] = {
8845 : { nullptr, &sAttributes_specs[0] },
8846 : { nullptr, nullptr }
8847 : };
8848 :
8849 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
8850 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
8851 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
8852 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
8853 :
8854 :
8855 : static uint16_t sNativeProperties_sortedPropertyIndices[9];
8856 : static PropertyInfo sNativeProperties_propertyInfos[9];
8857 :
8858 : static const NativePropertiesN<2> sNativeProperties = {
8859 : false, 0,
8860 : false, 0,
8861 : true, 0 /* sMethods */,
8862 : true, 1 /* sAttributes */,
8863 : false, 0,
8864 : false, 0,
8865 : false, 0,
8866 : 2,
8867 : 9,
8868 : sNativeProperties_sortedPropertyIndices,
8869 : {
8870 : { sMethods, &sNativeProperties_propertyInfos[0] },
8871 : { sAttributes, &sNativeProperties_propertyInfos[8] }
8872 : }
8873 : };
8874 : static_assert(2 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
8875 : "We have an iterator alias index that is oversized");
8876 : static_assert(9 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
8877 : "We have a property info count that is oversized");
8878 :
8879 : static bool
8880 0 : _constructor(JSContext* cx, unsigned argc, JS::Value* vp)
8881 : {
8882 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
8883 0 : JS::Rooted<JSObject*> obj(cx, &args.callee());
8884 0 : if (!args.isConstructing()) {
8885 : // XXXbz wish I could get the name from the callee instead of
8886 : // Adding more relocations
8887 0 : return ThrowConstructorWithoutNew(cx, "TestInterfaceSetlikeNode");
8888 : }
8889 :
8890 0 : GlobalObject global(cx, obj);
8891 0 : if (global.Failed()) {
8892 0 : return false;
8893 : }
8894 :
8895 0 : JS::Rooted<JSObject*> desiredProto(cx);
8896 0 : if (!GetDesiredProto(cx, args, &desiredProto)) {
8897 0 : return false;
8898 : }
8899 :
8900 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
8901 0 : Maybe<JSAutoCompartment> ac;
8902 0 : if (objIsXray) {
8903 0 : obj = js::CheckedUnwrap(obj);
8904 0 : if (!obj) {
8905 0 : return false;
8906 : }
8907 0 : ac.emplace(cx, obj);
8908 0 : if (!JS_WrapObject(cx, &desiredProto)) {
8909 0 : return false;
8910 : }
8911 : }
8912 0 : binding_detail::FastErrorResult rv;
8913 0 : auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceSetlikeNode>(mozilla::dom::TestInterfaceSetlikeNode::Constructor(global, rv)));
8914 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
8915 0 : return false;
8916 : }
8917 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
8918 : static_assert(!IsPointer<decltype(result)>::value,
8919 : "NewObject implies that we need to keep the object alive with a strong reference.");
8920 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) {
8921 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
8922 0 : return false;
8923 : }
8924 0 : return true;
8925 : }
8926 :
8927 : static const js::ClassOps sInterfaceObjectClassOps = {
8928 : nullptr, /* addProperty */
8929 : nullptr, /* delProperty */
8930 : nullptr, /* getProperty */
8931 : nullptr, /* setProperty */
8932 : nullptr, /* enumerate */
8933 : nullptr, /* newEnumerate */
8934 : nullptr, /* resolve */
8935 : nullptr, /* mayResolve */
8936 : nullptr, /* finalize */
8937 : _constructor, /* call */
8938 : nullptr, /* hasInstance */
8939 : _constructor, /* construct */
8940 : nullptr, /* trace */
8941 : };
8942 :
8943 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
8944 : {
8945 : "Function",
8946 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
8947 : &sInterfaceObjectClassOps,
8948 : JS_NULL_CLASS_SPEC,
8949 : JS_NULL_CLASS_EXT,
8950 : &sInterfaceObjectClassObjectOps
8951 : },
8952 : eInterface,
8953 : true,
8954 : prototypes::id::TestInterfaceSetlikeNode,
8955 : PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth,
8956 : sNativePropertyHooks,
8957 : "function TestInterfaceSetlikeNode() {\n [native code]\n}",
8958 : JS::GetRealmFunctionPrototype
8959 : };
8960 :
8961 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
8962 : {
8963 : "TestInterfaceSetlikeNodePrototype",
8964 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
8965 : JS_NULL_CLASS_OPS,
8966 : JS_NULL_CLASS_SPEC,
8967 : JS_NULL_CLASS_EXT,
8968 : JS_NULL_OBJECT_OPS
8969 : },
8970 : eInterfacePrototype,
8971 : false,
8972 : prototypes::id::TestInterfaceSetlikeNode,
8973 : PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth,
8974 : sNativePropertyHooks,
8975 : "[object TestInterfaceSetlikeNodePrototype]",
8976 : JS::GetRealmObjectPrototype
8977 : };
8978 :
8979 : bool
8980 0 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
8981 : {
8982 : static bool sPrefValue;
8983 : static bool sPrefCacheSetUp = false;
8984 0 : if (!sPrefCacheSetUp) {
8985 0 : sPrefCacheSetUp = true;
8986 0 : Preferences::AddBoolVarCache(&sPrefValue, "dom.expose_test_interfaces");
8987 : }
8988 :
8989 0 : return sPrefValue;
8990 : }
8991 :
8992 : JSObject*
8993 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
8994 : {
8995 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
8996 : }
8997 :
8998 : static const js::ClassOps sClassOps = {
8999 : _addProperty, /* addProperty */
9000 : nullptr, /* delProperty */
9001 : nullptr, /* getProperty */
9002 : nullptr, /* setProperty */
9003 : nullptr, /* enumerate */
9004 : nullptr, /* newEnumerate */
9005 : nullptr, /* resolve */
9006 : nullptr, /* mayResolve */
9007 : _finalize, /* finalize */
9008 : nullptr, /* call */
9009 : nullptr, /* hasInstance */
9010 : nullptr, /* construct */
9011 : nullptr, /* trace */
9012 : };
9013 :
9014 : static const js::ClassExtension sClassExtension = {
9015 : nullptr, /* weakmapKeyDelegateOp */
9016 : _objectMoved /* objectMovedOp */
9017 : };
9018 :
9019 : static const DOMJSClass sClass = {
9020 : { "TestInterfaceSetlikeNode",
9021 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
9022 : &sClassOps,
9023 : JS_NULL_CLASS_SPEC,
9024 : &sClassExtension,
9025 : JS_NULL_OBJECT_OPS
9026 : },
9027 : { prototypes::id::TestInterfaceSetlikeNode, 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 },
9028 : IsBaseOf<nsISupports, mozilla::dom::TestInterfaceSetlikeNode >::value,
9029 : sNativePropertyHooks,
9030 : FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceSetlikeNode>::Get,
9031 : GetProtoObjectHandle,
9032 : GetCCParticipant<mozilla::dom::TestInterfaceSetlikeNode>::Get()
9033 : };
9034 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
9035 : "Must have the right minimal number of reserved slots.");
9036 : static_assert(2 >= 2,
9037 : "Must have enough reserved slots.");
9038 :
9039 : const JSClass*
9040 0 : GetJSClass()
9041 : {
9042 0 : return sClass.ToJSClass();
9043 : }
9044 :
9045 : bool
9046 0 : Wrap(JSContext* aCx, mozilla::dom::TestInterfaceSetlikeNode* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
9047 : {
9048 : MOZ_ASSERT(static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(aObject) ==
9049 : reinterpret_cast<mozilla::dom::TestInterfaceSetlikeNode*>(aObject),
9050 : "Multiple inheritance for mozilla::dom::TestInterfaceSetlikeNode is broken.");
9051 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
9052 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
9053 0 : MOZ_ASSERT(!aCache->GetWrapper(),
9054 : "You should probably not be using Wrap() directly; use "
9055 : "GetOrCreateDOMReflector instead");
9056 :
9057 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
9058 : "nsISupports must be on our primary inheritance chain");
9059 :
9060 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
9061 0 : if (!global) {
9062 0 : return false;
9063 : }
9064 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
9065 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
9066 :
9067 : // That might have ended up wrapping us already, due to the wonders
9068 : // of XBL. Check for that, and bail out as needed.
9069 0 : aReflector.set(aCache->GetWrapper());
9070 0 : if (aReflector) {
9071 : #ifdef DEBUG
9072 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
9073 : #endif // DEBUG
9074 0 : return true;
9075 : }
9076 :
9077 0 : JSAutoCompartment ac(aCx, global);
9078 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
9079 0 : if (!canonicalProto) {
9080 0 : return false;
9081 : }
9082 0 : JS::Rooted<JSObject*> proto(aCx);
9083 0 : if (aGivenProto) {
9084 0 : proto = aGivenProto;
9085 : // Unfortunately, while aGivenProto was in the compartment of aCx
9086 : // coming in, we changed compartments to that of "parent" so may need
9087 : // to wrap the proto here.
9088 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
9089 0 : if (!JS_WrapObject(aCx, &proto)) {
9090 0 : return false;
9091 : }
9092 : }
9093 : } else {
9094 0 : proto = canonicalProto;
9095 : }
9096 :
9097 0 : BindingJSObjectCreator<mozilla::dom::TestInterfaceSetlikeNode> creator(aCx);
9098 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
9099 0 : if (!aReflector) {
9100 0 : return false;
9101 : }
9102 :
9103 0 : aCache->SetWrapper(aReflector);
9104 0 : creator.InitializationSucceeded();
9105 :
9106 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
9107 : aCache->GetWrapperPreserveColor() == aReflector);
9108 : // If proto != canonicalProto, we have to preserve our wrapper;
9109 : // otherwise we won't be able to properly recreate it later, since
9110 : // we won't know what proto to use. Note that we don't check
9111 : // aGivenProto here, since it's entirely possible (and even
9112 : // somewhat common) to have a non-null aGivenProto which is the
9113 : // same as canonicalProto.
9114 0 : if (proto != canonicalProto) {
9115 0 : PreserveWrapper(aObject);
9116 : }
9117 :
9118 0 : return true;
9119 : }
9120 :
9121 : // This may allocate too many slots, because we only really need
9122 : // slots for our non-interface-typed members that we cache. But
9123 : // allocating slots only for those would make the slot index
9124 : // computations much more complicated, so let's do this the simple
9125 : // way for now.
9126 : DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
9127 :
9128 : const NativePropertyHooks sNativePropertyHooks[] = { {
9129 : nullptr,
9130 : nullptr,
9131 : nullptr,
9132 : { sNativeProperties.Upcast(), nullptr },
9133 : prototypes::id::TestInterfaceSetlikeNode,
9134 : constructors::id::TestInterfaceSetlikeNode,
9135 : nullptr,
9136 : &sXrayExpandoObjectClass
9137 : } };
9138 :
9139 : void
9140 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
9141 : {
9142 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
9143 0 : if (!parentProto) {
9144 0 : return;
9145 : }
9146 :
9147 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
9148 0 : if (!constructorProto) {
9149 0 : return;
9150 : }
9151 :
9152 : static bool sIdsInited = false;
9153 0 : if (!sIdsInited && NS_IsMainThread()) {
9154 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
9155 0 : return;
9156 : }
9157 0 : sIdsInited = true;
9158 : }
9159 :
9160 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceSetlikeNode);
9161 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceSetlikeNode);
9162 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
9163 : &sPrototypeClass.mBase, protoCache,
9164 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
9165 : interfaceCache,
9166 : sNativeProperties.Upcast(),
9167 : nullptr,
9168 : "TestInterfaceSetlikeNode", aDefineOnGlobal,
9169 : nullptr,
9170 0 : false);
9171 :
9172 : // Set up aliases on the interface prototype object we just created.
9173 0 : JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
9174 0 : if (!proto) {
9175 0 : *protoCache = nullptr;
9176 0 : if (interfaceCache) {
9177 0 : *interfaceCache = nullptr;
9178 : }
9179 0 : return;
9180 : }
9181 :
9182 0 : JS::Rooted<JS::Value> aliasedVal(aCx);
9183 :
9184 0 : if (!JS_GetProperty(aCx, proto, "values", &aliasedVal)) {
9185 0 : *protoCache = nullptr;
9186 0 : if (interfaceCache) {
9187 0 : *interfaceCache = nullptr;
9188 : }
9189 0 : return;
9190 : }
9191 0 : JS::Rooted<jsid> iteratorId(aCx, SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::iterator)));
9192 0 : if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
9193 0 : *protoCache = nullptr;
9194 0 : if (interfaceCache) {
9195 0 : *interfaceCache = nullptr;
9196 : }
9197 0 : return;
9198 : }
9199 : }
9200 :
9201 : JS::Handle<JSObject*>
9202 0 : GetProtoObjectHandle(JSContext* aCx)
9203 : {
9204 : /* Get the interface prototype object for this class. This will create the
9205 : object as needed. */
9206 0 : bool aDefineOnGlobal = true;
9207 :
9208 : /* Make sure our global is sane. Hopefully we can remove this sometime */
9209 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
9210 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
9211 0 : return nullptr;
9212 : }
9213 :
9214 : /* Check to see whether the interface objects are already installed */
9215 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
9216 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::TestInterfaceSetlikeNode)) {
9217 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
9218 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
9219 : }
9220 :
9221 : /*
9222 : * The object might _still_ be null, but that's OK.
9223 : *
9224 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
9225 : * traced by TraceProtoAndIfaceCache() and its contents are never
9226 : * changed after they have been set.
9227 : *
9228 : * Calling address() avoids the read read barrier that does gray
9229 : * unmarking, but it's not possible for the object to be gray here.
9230 : */
9231 :
9232 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::TestInterfaceSetlikeNode);
9233 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
9234 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
9235 : }
9236 :
9237 : JS::Handle<JSObject*>
9238 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
9239 : {
9240 : /* Get the interface object for this class. This will create the object as
9241 : needed. */
9242 :
9243 : /* Make sure our global is sane. Hopefully we can remove this sometime */
9244 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
9245 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
9246 0 : return nullptr;
9247 : }
9248 :
9249 : /* Check to see whether the interface objects are already installed */
9250 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
9251 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::TestInterfaceSetlikeNode)) {
9252 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
9253 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
9254 : }
9255 :
9256 : /*
9257 : * The object might _still_ be null, but that's OK.
9258 : *
9259 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
9260 : * traced by TraceProtoAndIfaceCache() and its contents are never
9261 : * changed after they have been set.
9262 : *
9263 : * Calling address() avoids the read read barrier that does gray
9264 : * unmarking, but it's not possible for the object to be gray here.
9265 : */
9266 :
9267 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::TestInterfaceSetlikeNode);
9268 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
9269 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
9270 : }
9271 :
9272 : JSObject*
9273 0 : GetConstructorObject(JSContext* aCx)
9274 : {
9275 0 : return GetConstructorObjectHandle(aCx);
9276 : }
9277 :
9278 : } // namespace TestInterfaceSetlikeNodeBinding
9279 :
9280 :
9281 :
9282 : void
9283 0 : TestInterfaceJSMaplikeJSImpl::SetInternal(const nsAString& aKey, int32_t aValue, ErrorResult& aRv, JSCompartment* aCompartment)
9284 : {
9285 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.setInternal", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9286 0 : JSContext* cx = s.GetContext();
9287 0 : if (!cx) {
9288 0 : MOZ_ASSERT(aRv.Failed());
9289 0 : return;
9290 : }
9291 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9292 0 : JS::AutoValueVector argv(cx);
9293 0 : if (!argv.resize(2)) {
9294 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
9295 0 : return;
9296 : }
9297 0 : unsigned argc = 2;
9298 :
9299 : do {
9300 0 : argv[1].setInt32(int32_t(aValue));
9301 0 : break;
9302 : } while (0);
9303 :
9304 : do {
9305 0 : nsString mutableStr(aKey);
9306 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
9307 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9308 0 : return;
9309 : }
9310 0 : break;
9311 : } while (0);
9312 :
9313 0 : JS::Rooted<JS::Value> callable(cx);
9314 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9315 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9316 0 : !GetCallableProperty(cx, atomsCache->setInternal_id, &callable)) {
9317 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9318 0 : return;
9319 : }
9320 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9321 0 : if (!JS::Call(cx, thisValue, callable,
9322 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
9323 0 : aRv.NoteJSContextException(cx);
9324 0 : return;
9325 : }
9326 : }
9327 :
9328 : void
9329 0 : TestInterfaceJSMaplikeJSImpl::ClearInternal(ErrorResult& aRv, JSCompartment* aCompartment)
9330 : {
9331 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.clearInternal", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9332 0 : JSContext* cx = s.GetContext();
9333 0 : if (!cx) {
9334 0 : MOZ_ASSERT(aRv.Failed());
9335 0 : return;
9336 : }
9337 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9338 :
9339 0 : JS::Rooted<JS::Value> callable(cx);
9340 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9341 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9342 0 : !GetCallableProperty(cx, atomsCache->clearInternal_id, &callable)) {
9343 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9344 0 : return;
9345 : }
9346 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9347 0 : if (!JS::Call(cx, thisValue, callable,
9348 0 : JS::HandleValueArray::empty(), &rval)) {
9349 0 : aRv.NoteJSContextException(cx);
9350 0 : return;
9351 : }
9352 : }
9353 :
9354 : bool
9355 0 : TestInterfaceJSMaplikeJSImpl::DeleteInternal(const nsAString& aKey, ErrorResult& aRv, JSCompartment* aCompartment)
9356 : {
9357 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.deleteInternal", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9358 0 : JSContext* cx = s.GetContext();
9359 0 : if (!cx) {
9360 0 : MOZ_ASSERT(aRv.Failed());
9361 0 : return bool(0);
9362 : }
9363 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9364 0 : JS::AutoValueVector argv(cx);
9365 0 : if (!argv.resize(1)) {
9366 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
9367 0 : return bool(0);
9368 : }
9369 0 : unsigned argc = 1;
9370 :
9371 : do {
9372 0 : nsString mutableStr(aKey);
9373 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
9374 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9375 0 : return bool(0);
9376 : }
9377 0 : break;
9378 : } while (0);
9379 :
9380 0 : JS::Rooted<JS::Value> callable(cx);
9381 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9382 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9383 0 : !GetCallableProperty(cx, atomsCache->deleteInternal_id, &callable)) {
9384 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9385 0 : return bool(0);
9386 : }
9387 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9388 0 : if (!JS::Call(cx, thisValue, callable,
9389 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
9390 0 : aRv.NoteJSContextException(cx);
9391 0 : return bool(0);
9392 : }
9393 : bool rvalDecl;
9394 0 : if (!ValueToPrimitive<bool, eDefault>(cx, rval, &rvalDecl)) {
9395 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9396 0 : return bool(0);
9397 : }
9398 0 : return rvalDecl;
9399 : }
9400 :
9401 : void
9402 0 : TestInterfaceJSMaplikeJSImpl::Entries(JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
9403 : {
9404 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.entries", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9405 0 : JSContext* cx = s.GetContext();
9406 0 : if (!cx) {
9407 0 : MOZ_ASSERT(aRv.Failed());
9408 0 : return;
9409 : }
9410 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9411 :
9412 0 : JS::Rooted<JS::Value> callable(cx);
9413 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9414 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9415 0 : !GetCallableProperty(cx, atomsCache->entries_id, &callable)) {
9416 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9417 0 : return;
9418 : }
9419 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9420 0 : if (!JS::Call(cx, thisValue, callable,
9421 0 : JS::HandleValueArray::empty(), &rval)) {
9422 0 : aRv.NoteJSContextException(cx);
9423 0 : return;
9424 : }
9425 0 : JS::Rooted<JSObject*> rvalDecl(cx);
9426 0 : if (rval.isObject()) {
9427 : #ifdef __clang__
9428 : #pragma clang diagnostic push
9429 : #pragma clang diagnostic ignored "-Wunreachable-code"
9430 : #pragma clang diagnostic ignored "-Wunreachable-code-return"
9431 : #endif // __clang__
9432 0 : if ((false) && !CallerSubsumes(rval)) {
9433 0 : ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "return value of TestInterfaceJSMaplike.entries");
9434 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9435 0 : return;
9436 : }
9437 : #ifdef __clang__
9438 : #pragma clang diagnostic pop
9439 : #endif // __clang__
9440 0 : rvalDecl = &rval.toObject();
9441 : } else {
9442 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Return value of TestInterfaceJSMaplike.entries");
9443 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9444 0 : return;
9445 : }
9446 0 : aRetVal.set(rvalDecl);
9447 : }
9448 :
9449 : void
9450 0 : TestInterfaceJSMaplikeJSImpl::Keys(JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
9451 : {
9452 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.keys", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9453 0 : JSContext* cx = s.GetContext();
9454 0 : if (!cx) {
9455 0 : MOZ_ASSERT(aRv.Failed());
9456 0 : return;
9457 : }
9458 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9459 :
9460 0 : JS::Rooted<JS::Value> callable(cx);
9461 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9462 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9463 0 : !GetCallableProperty(cx, atomsCache->keys_id, &callable)) {
9464 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9465 0 : return;
9466 : }
9467 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9468 0 : if (!JS::Call(cx, thisValue, callable,
9469 0 : JS::HandleValueArray::empty(), &rval)) {
9470 0 : aRv.NoteJSContextException(cx);
9471 0 : return;
9472 : }
9473 0 : JS::Rooted<JSObject*> rvalDecl(cx);
9474 0 : if (rval.isObject()) {
9475 : #ifdef __clang__
9476 : #pragma clang diagnostic push
9477 : #pragma clang diagnostic ignored "-Wunreachable-code"
9478 : #pragma clang diagnostic ignored "-Wunreachable-code-return"
9479 : #endif // __clang__
9480 0 : if ((false) && !CallerSubsumes(rval)) {
9481 0 : ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "return value of TestInterfaceJSMaplike.keys");
9482 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9483 0 : return;
9484 : }
9485 : #ifdef __clang__
9486 : #pragma clang diagnostic pop
9487 : #endif // __clang__
9488 0 : rvalDecl = &rval.toObject();
9489 : } else {
9490 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Return value of TestInterfaceJSMaplike.keys");
9491 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9492 0 : return;
9493 : }
9494 0 : aRetVal.set(rvalDecl);
9495 : }
9496 :
9497 : void
9498 0 : TestInterfaceJSMaplikeJSImpl::Values(JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
9499 : {
9500 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.values", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9501 0 : JSContext* cx = s.GetContext();
9502 0 : if (!cx) {
9503 0 : MOZ_ASSERT(aRv.Failed());
9504 0 : return;
9505 : }
9506 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9507 :
9508 0 : JS::Rooted<JS::Value> callable(cx);
9509 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9510 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9511 0 : !GetCallableProperty(cx, atomsCache->values_id, &callable)) {
9512 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9513 0 : return;
9514 : }
9515 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9516 0 : if (!JS::Call(cx, thisValue, callable,
9517 0 : JS::HandleValueArray::empty(), &rval)) {
9518 0 : aRv.NoteJSContextException(cx);
9519 0 : return;
9520 : }
9521 0 : JS::Rooted<JSObject*> rvalDecl(cx);
9522 0 : if (rval.isObject()) {
9523 : #ifdef __clang__
9524 : #pragma clang diagnostic push
9525 : #pragma clang diagnostic ignored "-Wunreachable-code"
9526 : #pragma clang diagnostic ignored "-Wunreachable-code-return"
9527 : #endif // __clang__
9528 0 : if ((false) && !CallerSubsumes(rval)) {
9529 0 : ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "return value of TestInterfaceJSMaplike.values");
9530 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9531 0 : return;
9532 : }
9533 : #ifdef __clang__
9534 : #pragma clang diagnostic pop
9535 : #endif // __clang__
9536 0 : rvalDecl = &rval.toObject();
9537 : } else {
9538 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Return value of TestInterfaceJSMaplike.values");
9539 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9540 0 : return;
9541 : }
9542 0 : aRetVal.set(rvalDecl);
9543 : }
9544 :
9545 : void
9546 0 : TestInterfaceJSMaplikeJSImpl::ForEach(JS::Handle<JSObject*> callback, JS::Handle<JS::Value> thisArg, ErrorResult& aRv, JSCompartment* aCompartment)
9547 : {
9548 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.forEach", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9549 0 : JSContext* cx = s.GetContext();
9550 0 : if (!cx) {
9551 0 : MOZ_ASSERT(aRv.Failed());
9552 0 : return;
9553 : }
9554 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9555 0 : JS::AutoValueVector argv(cx);
9556 0 : if (!argv.resize(2)) {
9557 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
9558 0 : return;
9559 : }
9560 0 : unsigned argc = 2;
9561 :
9562 : do {
9563 0 : JS::ExposeValueToActiveJS(thisArg);
9564 0 : argv[1].set(thisArg);
9565 0 : if (!MaybeWrapValue(cx, argv[1])) {
9566 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9567 0 : return;
9568 : }
9569 0 : break;
9570 : } while (0);
9571 :
9572 : do {
9573 0 : JS::ExposeObjectToActiveJS(callback);
9574 0 : argv[0].setObject(*callback);
9575 0 : if (!MaybeWrapObjectValue(cx, argv[0])) {
9576 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9577 0 : return;
9578 : }
9579 0 : break;
9580 : } while (0);
9581 :
9582 0 : JS::Rooted<JS::Value> callable(cx);
9583 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9584 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9585 0 : !GetCallableProperty(cx, atomsCache->forEach_id, &callable)) {
9586 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9587 0 : return;
9588 : }
9589 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9590 0 : if (!JS::Call(cx, thisValue, callable,
9591 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
9592 0 : aRv.NoteJSContextException(cx);
9593 0 : return;
9594 : }
9595 : }
9596 :
9597 : bool
9598 0 : TestInterfaceJSMaplikeJSImpl::Has(const nsAString& key, ErrorResult& aRv, JSCompartment* aCompartment)
9599 : {
9600 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.has", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9601 0 : JSContext* cx = s.GetContext();
9602 0 : if (!cx) {
9603 0 : MOZ_ASSERT(aRv.Failed());
9604 0 : return bool(0);
9605 : }
9606 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9607 0 : JS::AutoValueVector argv(cx);
9608 0 : if (!argv.resize(1)) {
9609 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
9610 0 : return bool(0);
9611 : }
9612 0 : unsigned argc = 1;
9613 :
9614 : do {
9615 0 : nsString mutableStr(key);
9616 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
9617 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9618 0 : return bool(0);
9619 : }
9620 0 : break;
9621 : } while (0);
9622 :
9623 0 : JS::Rooted<JS::Value> callable(cx);
9624 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9625 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9626 0 : !GetCallableProperty(cx, atomsCache->has_id, &callable)) {
9627 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9628 0 : return bool(0);
9629 : }
9630 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9631 0 : if (!JS::Call(cx, thisValue, callable,
9632 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
9633 0 : aRv.NoteJSContextException(cx);
9634 0 : return bool(0);
9635 : }
9636 : bool rvalDecl;
9637 0 : if (!ValueToPrimitive<bool, eDefault>(cx, rval, &rvalDecl)) {
9638 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9639 0 : return bool(0);
9640 : }
9641 0 : return rvalDecl;
9642 : }
9643 :
9644 : void
9645 0 : TestInterfaceJSMaplikeJSImpl::__clear(ErrorResult& aRv, JSCompartment* aCompartment)
9646 : {
9647 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.__clear", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9648 0 : JSContext* cx = s.GetContext();
9649 0 : if (!cx) {
9650 0 : MOZ_ASSERT(aRv.Failed());
9651 0 : return;
9652 : }
9653 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9654 :
9655 0 : JS::Rooted<JS::Value> callable(cx);
9656 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9657 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9658 0 : !GetCallableProperty(cx, atomsCache->__clear_id, &callable)) {
9659 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9660 0 : return;
9661 : }
9662 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9663 0 : if (!JS::Call(cx, thisValue, callable,
9664 0 : JS::HandleValueArray::empty(), &rval)) {
9665 0 : aRv.NoteJSContextException(cx);
9666 0 : return;
9667 : }
9668 : }
9669 :
9670 : bool
9671 0 : TestInterfaceJSMaplikeJSImpl::__delete(const nsAString& key, ErrorResult& aRv, JSCompartment* aCompartment)
9672 : {
9673 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.__delete", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9674 0 : JSContext* cx = s.GetContext();
9675 0 : if (!cx) {
9676 0 : MOZ_ASSERT(aRv.Failed());
9677 0 : return bool(0);
9678 : }
9679 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9680 0 : JS::AutoValueVector argv(cx);
9681 0 : if (!argv.resize(1)) {
9682 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
9683 0 : return bool(0);
9684 : }
9685 0 : unsigned argc = 1;
9686 :
9687 : do {
9688 0 : nsString mutableStr(key);
9689 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
9690 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9691 0 : return bool(0);
9692 : }
9693 0 : break;
9694 : } while (0);
9695 :
9696 0 : JS::Rooted<JS::Value> callable(cx);
9697 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9698 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9699 0 : !GetCallableProperty(cx, atomsCache->__delete_id, &callable)) {
9700 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9701 0 : return bool(0);
9702 : }
9703 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9704 0 : if (!JS::Call(cx, thisValue, callable,
9705 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
9706 0 : aRv.NoteJSContextException(cx);
9707 0 : return bool(0);
9708 : }
9709 : bool rvalDecl;
9710 0 : if (!ValueToPrimitive<bool, eDefault>(cx, rval, &rvalDecl)) {
9711 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9712 0 : return bool(0);
9713 : }
9714 0 : return rvalDecl;
9715 : }
9716 :
9717 : void
9718 0 : TestInterfaceJSMaplikeJSImpl::Get(const nsAString& key, JS::MutableHandle<JS::Value> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
9719 : {
9720 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.get", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9721 0 : JSContext* cx = s.GetContext();
9722 0 : if (!cx) {
9723 0 : MOZ_ASSERT(aRv.Failed());
9724 0 : return;
9725 : }
9726 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9727 0 : JS::AutoValueVector argv(cx);
9728 0 : if (!argv.resize(1)) {
9729 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
9730 0 : return;
9731 : }
9732 0 : unsigned argc = 1;
9733 :
9734 : do {
9735 0 : nsString mutableStr(key);
9736 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
9737 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9738 0 : return;
9739 : }
9740 0 : break;
9741 : } while (0);
9742 :
9743 0 : JS::Rooted<JS::Value> callable(cx);
9744 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9745 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9746 0 : !GetCallableProperty(cx, atomsCache->get_id, &callable)) {
9747 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9748 0 : return;
9749 : }
9750 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9751 0 : if (!JS::Call(cx, thisValue, callable,
9752 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
9753 0 : aRv.NoteJSContextException(cx);
9754 0 : return;
9755 : }
9756 0 : JS::Rooted<JS::Value> rvalDecl(cx);
9757 : #ifdef __clang__
9758 : #pragma clang diagnostic push
9759 : #pragma clang diagnostic ignored "-Wunreachable-code"
9760 : #pragma clang diagnostic ignored "-Wunreachable-code-return"
9761 : #endif // __clang__
9762 0 : if ((false) && !CallerSubsumes(rval)) {
9763 0 : ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "return value of TestInterfaceJSMaplike.get");
9764 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9765 0 : return;
9766 : }
9767 : #ifdef __clang__
9768 : #pragma clang diagnostic pop
9769 : #endif // __clang__
9770 0 : rvalDecl = rval;
9771 0 : aRetVal.set(rvalDecl);
9772 : }
9773 :
9774 : void
9775 0 : TestInterfaceJSMaplikeJSImpl::__set(const nsAString& key, int32_t value, JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
9776 : {
9777 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.__set", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9778 0 : JSContext* cx = s.GetContext();
9779 0 : if (!cx) {
9780 0 : MOZ_ASSERT(aRv.Failed());
9781 0 : return;
9782 : }
9783 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9784 0 : JS::AutoValueVector argv(cx);
9785 0 : if (!argv.resize(2)) {
9786 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
9787 0 : return;
9788 : }
9789 0 : unsigned argc = 2;
9790 :
9791 : do {
9792 0 : argv[1].setInt32(int32_t(value));
9793 0 : break;
9794 : } while (0);
9795 :
9796 : do {
9797 0 : nsString mutableStr(key);
9798 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
9799 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9800 0 : return;
9801 : }
9802 0 : break;
9803 : } while (0);
9804 :
9805 0 : JS::Rooted<JS::Value> callable(cx);
9806 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9807 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9808 0 : !GetCallableProperty(cx, atomsCache->__set_id, &callable)) {
9809 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9810 0 : return;
9811 : }
9812 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9813 0 : if (!JS::Call(cx, thisValue, callable,
9814 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
9815 0 : aRv.NoteJSContextException(cx);
9816 0 : return;
9817 : }
9818 0 : JS::Rooted<JSObject*> rvalDecl(cx);
9819 0 : if (rval.isObject()) {
9820 : #ifdef __clang__
9821 : #pragma clang diagnostic push
9822 : #pragma clang diagnostic ignored "-Wunreachable-code"
9823 : #pragma clang diagnostic ignored "-Wunreachable-code-return"
9824 : #endif // __clang__
9825 0 : if ((false) && !CallerSubsumes(rval)) {
9826 0 : ThrowErrorMessage(cx, MSG_PERMISSION_DENIED_TO_PASS_ARG, "return value of TestInterfaceJSMaplike.__set");
9827 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9828 0 : return;
9829 : }
9830 : #ifdef __clang__
9831 : #pragma clang diagnostic pop
9832 : #endif // __clang__
9833 0 : rvalDecl = &rval.toObject();
9834 : } else {
9835 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Return value of TestInterfaceJSMaplike.__set");
9836 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9837 0 : return;
9838 : }
9839 0 : aRetVal.set(rvalDecl);
9840 : }
9841 :
9842 : void
9843 0 : TestInterfaceJSMaplikeJSImpl::__Init(ErrorResult& aRv, JSCompartment* aCompartment)
9844 : {
9845 0 : CallSetup s(this, aRv, "__init", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9846 0 : JSContext* cx = s.GetContext();
9847 0 : if (!cx) {
9848 0 : MOZ_ASSERT(aRv.Failed());
9849 0 : return;
9850 : }
9851 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9852 :
9853 0 : JS::Rooted<JS::Value> callable(cx);
9854 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9855 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9856 0 : !GetCallableProperty(cx, atomsCache->__init_id, &callable)) {
9857 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9858 0 : return;
9859 : }
9860 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
9861 0 : if (!JS::Call(cx, thisValue, callable,
9862 0 : JS::HandleValueArray::empty(), &rval)) {
9863 0 : aRv.NoteJSContextException(cx);
9864 0 : return;
9865 : }
9866 : }
9867 :
9868 : bool
9869 0 : TestInterfaceJSMaplikeJSImpl::InitIds(JSContext* cx, TestInterfaceJSMaplikeAtoms* atomsCache)
9870 : {
9871 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
9872 :
9873 : // Initialize these in reverse order so that any failure leaves the first one
9874 : // uninitialized.
9875 0 : if (!atomsCache->__init_id.init(cx, "__init") ||
9876 0 : !atomsCache->__set_id.init(cx, "__set") ||
9877 0 : !atomsCache->get_id.init(cx, "get") ||
9878 0 : !atomsCache->__delete_id.init(cx, "__delete") ||
9879 0 : !atomsCache->__clear_id.init(cx, "__clear") ||
9880 0 : !atomsCache->has_id.init(cx, "has") ||
9881 0 : !atomsCache->forEach_id.init(cx, "forEach") ||
9882 0 : !atomsCache->values_id.init(cx, "values") ||
9883 0 : !atomsCache->keys_id.init(cx, "keys") ||
9884 0 : !atomsCache->entries_id.init(cx, "entries") ||
9885 0 : !atomsCache->size_id.init(cx, "size") ||
9886 0 : !atomsCache->deleteInternal_id.init(cx, "deleteInternal") ||
9887 0 : !atomsCache->clearInternal_id.init(cx, "clearInternal") ||
9888 0 : !atomsCache->setInternal_id.init(cx, "setInternal")) {
9889 0 : return false;
9890 : }
9891 0 : return true;
9892 : }
9893 :
9894 :
9895 : uint32_t
9896 0 : TestInterfaceJSMaplikeJSImpl::GetSize(ErrorResult& aRv, JSCompartment* aCompartment)
9897 : {
9898 0 : CallSetup s(this, aRv, "TestInterfaceJSMaplike.size", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
9899 0 : JSContext* cx = s.GetContext();
9900 0 : if (!cx) {
9901 0 : MOZ_ASSERT(aRv.Failed());
9902 0 : return uint32_t(0);
9903 : }
9904 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
9905 :
9906 0 : JS::Rooted<JSObject *> callback(cx, mCallback);
9907 0 : TestInterfaceJSMaplikeAtoms* atomsCache = GetAtomCache<TestInterfaceJSMaplikeAtoms>(cx);
9908 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
9909 0 : !JS_GetPropertyById(cx, callback, atomsCache->size_id, &rval)) {
9910 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9911 0 : return uint32_t(0);
9912 : }
9913 : uint32_t rvalDecl;
9914 0 : if (!ValueToPrimitive<uint32_t, eDefault>(cx, rval, &rvalDecl)) {
9915 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
9916 0 : return uint32_t(0);
9917 : }
9918 0 : return rvalDecl;
9919 : }
9920 :
9921 :
9922 : NS_IMPL_CYCLE_COLLECTION_CLASS(TestInterfaceJSMaplike)
9923 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TestInterfaceJSMaplike)
9924 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mImpl)
9925 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
9926 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
9927 0 : tmp->ClearWeakReferences();
9928 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
9929 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TestInterfaceJSMaplike)
9930 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImpl)
9931 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
9932 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
9933 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(TestInterfaceJSMaplike)
9934 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceJSMaplike)
9935 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceJSMaplike)
9936 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceJSMaplike)
9937 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
9938 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
9939 0 : NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
9940 0 : NS_INTERFACE_MAP_END
9941 :
9942 0 : TestInterfaceJSMaplike::TestInterfaceJSMaplike(JS::Handle<JSObject*> aJSImplObject, nsIGlobalObject* aParent)
9943 0 : : mImpl(new TestInterfaceJSMaplikeJSImpl(nullptr, aJSImplObject, /* aIncumbentGlobal = */ nullptr)),
9944 0 : mParent(aParent)
9945 : {
9946 0 : }
9947 :
9948 :
9949 0 : TestInterfaceJSMaplike::~TestInterfaceJSMaplike()
9950 : {
9951 0 : }
9952 :
9953 : nsISupports*
9954 0 : TestInterfaceJSMaplike::GetParentObject() const
9955 : {
9956 0 : return mParent;
9957 : }
9958 :
9959 : JSObject*
9960 0 : TestInterfaceJSMaplike::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
9961 : {
9962 0 : JS::Rooted<JSObject*> obj(aCx, TestInterfaceJSMaplikeBinding::Wrap(aCx, this, aGivenProto));
9963 0 : if (!obj) {
9964 0 : return nullptr;
9965 : }
9966 :
9967 : // Now define it on our chrome object
9968 0 : JSAutoCompartment ac(aCx, mImpl->CallbackOrNull());
9969 0 : if (!JS_WrapObject(aCx, &obj)) {
9970 0 : return nullptr;
9971 : }
9972 0 : if (!JS_DefineProperty(aCx, mImpl->CallbackOrNull(), "__DOM_IMPL__", obj, 0)) {
9973 0 : return nullptr;
9974 : }
9975 0 : return obj;
9976 : }
9977 :
9978 : already_AddRefed<TestInterfaceJSMaplike>
9979 0 : TestInterfaceJSMaplike::Constructor(const GlobalObject& global, JSContext* cx, ErrorResult& aRv)
9980 : {
9981 0 : JS::Rooted<JSObject*> jsImplObj(cx);
9982 : nsCOMPtr<nsIGlobalObject> globalHolder =
9983 0 : ConstructJSImplementation("@mozilla.org/dom/test-interface-js-maplike;1", global, &jsImplObj, aRv);
9984 0 : if (aRv.Failed()) {
9985 0 : return nullptr;
9986 : }
9987 : // Build the C++ implementation.
9988 0 : RefPtr<TestInterfaceJSMaplike> impl = new TestInterfaceJSMaplike(jsImplObj, globalHolder);
9989 0 : return impl.forget();
9990 : }
9991 :
9992 : void
9993 0 : TestInterfaceJSMaplike::SetInternal(const nsAString& aKey, int32_t aValue, ErrorResult& aRv, JSCompartment* aCompartment)
9994 : {
9995 0 : return mImpl->SetInternal(aKey, aValue, aRv, aCompartment);
9996 : }
9997 :
9998 : void
9999 0 : TestInterfaceJSMaplike::ClearInternal(ErrorResult& aRv, JSCompartment* aCompartment)
10000 : {
10001 0 : return mImpl->ClearInternal(aRv, aCompartment);
10002 : }
10003 :
10004 : bool
10005 0 : TestInterfaceJSMaplike::DeleteInternal(const nsAString& aKey, ErrorResult& aRv, JSCompartment* aCompartment)
10006 : {
10007 0 : return mImpl->DeleteInternal(aKey, aRv, aCompartment);
10008 : }
10009 :
10010 : uint32_t
10011 0 : TestInterfaceJSMaplike::GetSize(ErrorResult& aRv, JSCompartment* aCompartment) const
10012 : {
10013 0 : return mImpl->GetSize(aRv, aCompartment);
10014 : }
10015 :
10016 : void
10017 0 : TestInterfaceJSMaplike::Entries(JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
10018 : {
10019 0 : return mImpl->Entries(aRetVal, aRv, aCompartment);
10020 : }
10021 :
10022 : void
10023 0 : TestInterfaceJSMaplike::Keys(JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
10024 : {
10025 0 : return mImpl->Keys(aRetVal, aRv, aCompartment);
10026 : }
10027 :
10028 : void
10029 0 : TestInterfaceJSMaplike::Values(JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
10030 : {
10031 0 : return mImpl->Values(aRetVal, aRv, aCompartment);
10032 : }
10033 :
10034 : void
10035 0 : TestInterfaceJSMaplike::ForEach(JS::Handle<JSObject*> callback, JS::Handle<JS::Value> thisArg, ErrorResult& aRv, JSCompartment* aCompartment)
10036 : {
10037 0 : return mImpl->ForEach(callback, thisArg, aRv, aCompartment);
10038 : }
10039 :
10040 : bool
10041 0 : TestInterfaceJSMaplike::Has(const nsAString& key, ErrorResult& aRv, JSCompartment* aCompartment)
10042 : {
10043 0 : return mImpl->Has(key, aRv, aCompartment);
10044 : }
10045 :
10046 : void
10047 0 : TestInterfaceJSMaplike::__clear(ErrorResult& aRv, JSCompartment* aCompartment)
10048 : {
10049 0 : return mImpl->__clear(aRv, aCompartment);
10050 : }
10051 :
10052 : bool
10053 0 : TestInterfaceJSMaplike::__delete(const nsAString& key, ErrorResult& aRv, JSCompartment* aCompartment)
10054 : {
10055 0 : return mImpl->__delete(key, aRv, aCompartment);
10056 : }
10057 :
10058 : void
10059 0 : TestInterfaceJSMaplike::Get(const nsAString& key, JS::MutableHandle<JS::Value> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
10060 : {
10061 0 : return mImpl->Get(key, aRetVal, aRv, aCompartment);
10062 : }
10063 :
10064 : void
10065 0 : TestInterfaceJSMaplike::__set(const nsAString& key, int32_t value, JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv, JSCompartment* aCompartment)
10066 : {
10067 0 : return mImpl->__set(key, value, aRetVal, aRv, aCompartment);
10068 : }
10069 :
10070 : bool
10071 0 : TestInterfaceJSMaplike::_Create(JSContext* cx, unsigned argc, JS::Value* vp)
10072 : {
10073 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
10074 0 : if (args.length() < 2) {
10075 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "TestInterfaceJSMaplike._create");
10076 : }
10077 0 : if (!args[0].isObject()) {
10078 0 : return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of TestInterfaceJSMaplike._create");
10079 : }
10080 0 : if (!args[1].isObject()) {
10081 0 : return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of TestInterfaceJSMaplike._create");
10082 : }
10083 :
10084 : // GlobalObject will go through wrappers as needed for us, and
10085 : // is simpler than the right UnwrapArg incantation.
10086 0 : GlobalObject global(cx, &args[0].toObject());
10087 0 : if (global.Failed()) {
10088 0 : return false;
10089 : }
10090 0 : nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(global.GetAsSupports());
10091 0 : MOZ_ASSERT(globalHolder);
10092 0 : JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
10093 0 : RefPtr<TestInterfaceJSMaplike> impl = new TestInterfaceJSMaplike(arg, globalHolder);
10094 0 : MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
10095 0 : return GetOrCreateDOMReflector(cx, impl, args.rval());
10096 : }
10097 :
10098 :
10099 : } // namespace dom
10100 : } // namespace mozilla
|