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