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