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