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