Line data Source code
1 : /* THIS FILE IS AUTOGENERATED FROM HeapSnapshot.webidl BY Codegen.py - DO NOT EDIT */
2 :
3 : #include "HeapSnapshotBinding.h"
4 : #include "WrapperFactory.h"
5 : #include "mozilla/OwningNonNull.h"
6 : #include "mozilla/devtools/DominatorTree.h"
7 : #include "mozilla/devtools/HeapSnapshot.h"
8 : #include "mozilla/dom/BindingUtils.h"
9 : #include "mozilla/dom/DOMJSClass.h"
10 : #include "mozilla/dom/NonRefcountedDOMObject.h"
11 : #include "mozilla/dom/Nullable.h"
12 : #include "mozilla/dom/PrimitiveConversions.h"
13 : #include "mozilla/dom/XrayExpandoClass.h"
14 : #include "nsContentUtils.h"
15 :
16 : namespace mozilla {
17 : namespace dom {
18 :
19 : namespace HeapSnapshotBinding {
20 :
21 : static bool
22 0 : get_creationTime(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::devtools::HeapSnapshot* self, JSJitGetterCallArgs args)
23 : {
24 0 : Nullable<uint64_t> result(self->GetCreationTime());
25 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
26 0 : if (result.IsNull()) {
27 0 : args.rval().setNull();
28 0 : return true;
29 : }
30 0 : args.rval().set(JS_NumberValue(double(result.Value())));
31 0 : return true;
32 : }
33 :
34 : static const JSJitInfo creationTime_getterinfo = {
35 : { (JSJitGetterOp)get_creationTime },
36 : { prototypes::id::HeapSnapshot },
37 : { PrototypeTraits<prototypes::id::HeapSnapshot>::Depth },
38 : JSJitInfo::Getter,
39 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
40 : JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */
41 : true, /* isInfallible. False in setters. */
42 : false, /* isMovable. Not relevant for setters. */
43 : false, /* isEliminatable. Not relevant for setters. */
44 : false, /* isAlwaysInSlot. Only relevant for getters. */
45 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
46 : false, /* isTypedMethod. Only relevant for methods. */
47 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
48 : };
49 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
50 : static_assert(0 < 1, "There is no slot for us");
51 :
52 : static bool
53 0 : takeCensus(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::devtools::HeapSnapshot* self, const JSJitMethodCallArgs& args)
54 : {
55 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
56 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "HeapSnapshot.takeCensus");
57 : }
58 0 : JS::Rooted<JSObject*> arg0(cx);
59 0 : if (args[0].isObject()) {
60 0 : arg0 = &args[0].toObject();
61 0 : } else if (args[0].isNullOrUndefined()) {
62 0 : arg0 = nullptr;
63 : } else {
64 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of HeapSnapshot.takeCensus");
65 0 : return false;
66 : }
67 0 : binding_detail::FastErrorResult rv;
68 0 : JS::Rooted<JS::Value> result(cx);
69 0 : self->TakeCensus(cx, arg0, &result, rv);
70 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
71 0 : return false;
72 : }
73 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
74 0 : JS::ExposeValueToActiveJS(result);
75 0 : args.rval().set(result);
76 0 : if (!MaybeWrapValue(cx, args.rval())) {
77 0 : return false;
78 : }
79 0 : return true;
80 : }
81 :
82 : static const JSJitInfo takeCensus_methodinfo = {
83 : { (JSJitGetterOp)takeCensus },
84 : { prototypes::id::HeapSnapshot },
85 : { PrototypeTraits<prototypes::id::HeapSnapshot>::Depth },
86 : JSJitInfo::Method,
87 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
88 : JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */
89 : false, /* isInfallible. False in setters. */
90 : false, /* isMovable. Not relevant for setters. */
91 : false, /* isEliminatable. Not relevant for setters. */
92 : false, /* isAlwaysInSlot. Only relevant for getters. */
93 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
94 : false, /* isTypedMethod. Only relevant for methods. */
95 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
96 : };
97 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
98 : static_assert(0 < 1, "There is no slot for us");
99 :
100 : static bool
101 0 : describeNode(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::devtools::HeapSnapshot* self, const JSJitMethodCallArgs& args)
102 : {
103 0 : if (MOZ_UNLIKELY(args.length() < 2)) {
104 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "HeapSnapshot.describeNode");
105 : }
106 0 : JS::Rooted<JSObject*> arg0(cx);
107 0 : if (args[0].isObject()) {
108 0 : arg0 = &args[0].toObject();
109 : } else {
110 0 : ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of HeapSnapshot.describeNode");
111 0 : return false;
112 : }
113 : uint64_t arg1;
114 0 : if (!ValueToPrimitive<uint64_t, eDefault>(cx, args[1], &arg1)) {
115 0 : return false;
116 : }
117 0 : binding_detail::FastErrorResult rv;
118 0 : JS::Rooted<JS::Value> result(cx);
119 0 : self->DescribeNode(cx, arg0, arg1, &result, rv);
120 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
121 0 : return false;
122 : }
123 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
124 0 : JS::ExposeValueToActiveJS(result);
125 0 : args.rval().set(result);
126 0 : if (!MaybeWrapValue(cx, args.rval())) {
127 0 : return false;
128 : }
129 0 : return true;
130 : }
131 :
132 : static const JSJitInfo describeNode_methodinfo = {
133 : { (JSJitGetterOp)describeNode },
134 : { prototypes::id::HeapSnapshot },
135 : { PrototypeTraits<prototypes::id::HeapSnapshot>::Depth },
136 : JSJitInfo::Method,
137 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
138 : JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */
139 : false, /* isInfallible. False in setters. */
140 : false, /* isMovable. Not relevant for setters. */
141 : false, /* isEliminatable. Not relevant for setters. */
142 : false, /* isAlwaysInSlot. Only relevant for getters. */
143 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
144 : false, /* isTypedMethod. Only relevant for methods. */
145 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
146 : };
147 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
148 : static_assert(0 < 1, "There is no slot for us");
149 :
150 : static bool
151 0 : computeDominatorTree(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::devtools::HeapSnapshot* self, const JSJitMethodCallArgs& args)
152 : {
153 0 : binding_detail::FastErrorResult rv;
154 0 : auto result(StrongOrRawPtr<mozilla::devtools::DominatorTree>(self->ComputeDominatorTree(rv)));
155 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
156 0 : return false;
157 : }
158 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
159 0 : if (!GetOrCreateDOMReflector(cx, result, args.rval())) {
160 0 : MOZ_ASSERT(true || JS_IsExceptionPending(cx));
161 0 : return false;
162 : }
163 0 : return true;
164 : }
165 :
166 : static const JSJitInfo computeDominatorTree_methodinfo = {
167 : { (JSJitGetterOp)computeDominatorTree },
168 : { prototypes::id::HeapSnapshot },
169 : { PrototypeTraits<prototypes::id::HeapSnapshot>::Depth },
170 : JSJitInfo::Method,
171 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
172 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
173 : false, /* isInfallible. False in setters. */
174 : false, /* isMovable. Not relevant for setters. */
175 : false, /* isEliminatable. Not relevant for setters. */
176 : false, /* isAlwaysInSlot. Only relevant for getters. */
177 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
178 : false, /* isTypedMethod. Only relevant for methods. */
179 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
180 : };
181 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
182 : static_assert(0 < 1, "There is no slot for us");
183 :
184 : static bool
185 0 : computeShortestPaths(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::devtools::HeapSnapshot* self, const JSJitMethodCallArgs& args)
186 : {
187 0 : if (MOZ_UNLIKELY(args.length() < 3)) {
188 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "HeapSnapshot.computeShortestPaths");
189 : }
190 : uint64_t arg0;
191 0 : if (!ValueToPrimitive<uint64_t, eDefault>(cx, args[0], &arg0)) {
192 0 : return false;
193 : }
194 0 : binding_detail::AutoSequence<uint64_t> arg1;
195 0 : if (args[1].isObject()) {
196 0 : JS::ForOfIterator iter(cx);
197 0 : if (!iter.init(args[1], JS::ForOfIterator::AllowNonIterable)) {
198 0 : return false;
199 : }
200 0 : if (!iter.valueIsIterable()) {
201 0 : ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 2 of HeapSnapshot.computeShortestPaths");
202 0 : return false;
203 : }
204 0 : binding_detail::AutoSequence<uint64_t> &arr = arg1;
205 0 : JS::Rooted<JS::Value> temp(cx);
206 : while (true) {
207 : bool done;
208 0 : if (!iter.next(&temp, &done)) {
209 0 : return false;
210 : }
211 0 : if (done) {
212 0 : break;
213 : }
214 0 : uint64_t* slotPtr = arr.AppendElement(mozilla::fallible);
215 0 : if (!slotPtr) {
216 0 : JS_ReportOutOfMemory(cx);
217 0 : return false;
218 : }
219 0 : uint64_t& slot = *slotPtr;
220 0 : if (!ValueToPrimitive<uint64_t, eDefault>(cx, temp, &slot)) {
221 0 : return false;
222 : }
223 0 : }
224 : } else {
225 0 : ThrowErrorMessage(cx, MSG_NOT_SEQUENCE, "Argument 2 of HeapSnapshot.computeShortestPaths");
226 0 : return false;
227 : }
228 : uint64_t arg2;
229 0 : if (!ValueToPrimitive<uint64_t, eDefault>(cx, args[2], &arg2)) {
230 0 : return false;
231 : }
232 0 : binding_detail::FastErrorResult rv;
233 0 : JS::Rooted<JSObject*> result(cx);
234 0 : self->ComputeShortestPaths(cx, arg0, Constify(arg1), arg2, &result, rv);
235 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
236 0 : return false;
237 : }
238 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
239 0 : JS::ExposeObjectToActiveJS(result);
240 0 : args.rval().setObject(*result);
241 0 : if (!MaybeWrapObjectValue(cx, args.rval())) {
242 0 : return false;
243 : }
244 0 : return true;
245 : }
246 :
247 : static const JSJitInfo computeShortestPaths_methodinfo = {
248 : { (JSJitGetterOp)computeShortestPaths },
249 : { prototypes::id::HeapSnapshot },
250 : { PrototypeTraits<prototypes::id::HeapSnapshot>::Depth },
251 : JSJitInfo::Method,
252 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
253 : JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */
254 : false, /* isInfallible. False in setters. */
255 : false, /* isMovable. Not relevant for setters. */
256 : false, /* isEliminatable. Not relevant for setters. */
257 : false, /* isAlwaysInSlot. Only relevant for getters. */
258 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
259 : false, /* isTypedMethod. Only relevant for methods. */
260 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
261 : };
262 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
263 : static_assert(0 < 1, "There is no slot for us");
264 :
265 : static bool
266 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
267 : {
268 0 : mozilla::devtools::HeapSnapshot* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::devtools::HeapSnapshot>(obj);
269 : // We don't want to preserve if we don't have a wrapper, and we
270 : // obviously can't preserve if we're not initialized.
271 0 : if (self && self->GetWrapperPreserveColor()) {
272 0 : PreserveWrapper(self);
273 : }
274 0 : return true;
275 : }
276 :
277 : static void
278 0 : _finalize(js::FreeOp* fop, JSObject* obj)
279 : {
280 0 : mozilla::devtools::HeapSnapshot* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::devtools::HeapSnapshot>(obj);
281 0 : if (self) {
282 0 : ClearWrapper(self, self, obj);
283 0 : AddForDeferredFinalization<mozilla::devtools::HeapSnapshot>(self);
284 : }
285 0 : }
286 :
287 : static void
288 0 : _objectMoved(JSObject* obj, const JSObject* old)
289 : {
290 0 : mozilla::devtools::HeapSnapshot* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::devtools::HeapSnapshot>(obj);
291 0 : if (self) {
292 0 : UpdateWrapper(self, self, obj, old);
293 : }
294 0 : }
295 :
296 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
297 : #if defined(__clang__)
298 : #pragma clang diagnostic push
299 : #pragma clang diagnostic ignored "-Wmissing-braces"
300 : #endif
301 : static const JSFunctionSpec sMethods_specs[] = {
302 : JS_FNSPEC("takeCensus", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&takeCensus_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
303 : JS_FNSPEC("describeNode", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&describeNode_methodinfo), 2, JSPROP_ENUMERATE, nullptr),
304 : JS_FNSPEC("computeDominatorTree", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&computeDominatorTree_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
305 : JS_FNSPEC("computeShortestPaths", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&computeShortestPaths_methodinfo), 3, JSPROP_ENUMERATE, nullptr),
306 : JS_FS_END
307 : };
308 : #if defined(__clang__)
309 : #pragma clang diagnostic pop
310 : #endif
311 :
312 :
313 : // Can't be const because the pref-enabled boolean needs to be writable
314 : static Prefable<const JSFunctionSpec> sMethods[] = {
315 : { nullptr, &sMethods_specs[0] },
316 : { nullptr, nullptr }
317 : };
318 :
319 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
320 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
321 : static_assert(4 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
322 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
323 :
324 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
325 : #if defined(__clang__)
326 : #pragma clang diagnostic push
327 : #pragma clang diagnostic ignored "-Wmissing-braces"
328 : #endif
329 : static const JSPropertySpec sAttributes_specs[] = {
330 : { "creationTime", JSPROP_SHARED | JSPROP_ENUMERATE, GenericBindingGetter, &creationTime_getterinfo, nullptr, nullptr },
331 : { nullptr, 0, nullptr, nullptr, nullptr, nullptr }
332 : };
333 : #if defined(__clang__)
334 : #pragma clang diagnostic pop
335 : #endif
336 :
337 :
338 : // Can't be const because the pref-enabled boolean needs to be writable
339 : static Prefable<const JSPropertySpec> sAttributes[] = {
340 : { nullptr, &sAttributes_specs[0] },
341 : { nullptr, nullptr }
342 : };
343 :
344 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
345 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
346 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
347 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
348 :
349 :
350 : static uint16_t sNativeProperties_sortedPropertyIndices[5];
351 : static PropertyInfo sNativeProperties_propertyInfos[5];
352 :
353 : static const NativePropertiesN<2> sNativeProperties = {
354 : false, 0,
355 : false, 0,
356 : true, 0 /* sMethods */,
357 : true, 1 /* sAttributes */,
358 : false, 0,
359 : false, 0,
360 : false, 0,
361 : -1,
362 : 5,
363 : sNativeProperties_sortedPropertyIndices,
364 : {
365 : { sMethods, &sNativeProperties_propertyInfos[0] },
366 : { sAttributes, &sNativeProperties_propertyInfos[4] }
367 : }
368 : };
369 : static_assert(5 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
370 : "We have a property info count that is oversized");
371 :
372 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
373 : {
374 : "Function",
375 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
376 : &sBoringInterfaceObjectClassClassOps,
377 : JS_NULL_CLASS_SPEC,
378 : JS_NULL_CLASS_EXT,
379 : &sInterfaceObjectClassObjectOps
380 : },
381 : eInterface,
382 : true,
383 : prototypes::id::HeapSnapshot,
384 : PrototypeTraits<prototypes::id::HeapSnapshot>::Depth,
385 : sNativePropertyHooks,
386 : "function HeapSnapshot() {\n [native code]\n}",
387 : JS::GetRealmFunctionPrototype
388 : };
389 :
390 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
391 : {
392 : "HeapSnapshotPrototype",
393 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
394 : JS_NULL_CLASS_OPS,
395 : JS_NULL_CLASS_SPEC,
396 : JS_NULL_CLASS_EXT,
397 : JS_NULL_OBJECT_OPS
398 : },
399 : eInterfacePrototype,
400 : false,
401 : prototypes::id::HeapSnapshot,
402 : PrototypeTraits<prototypes::id::HeapSnapshot>::Depth,
403 : sNativePropertyHooks,
404 : "[object HeapSnapshotPrototype]",
405 : JS::GetRealmObjectPrototype
406 : };
407 :
408 : bool
409 2 : ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
410 : {
411 2 : return nsContentUtils::ThreadsafeIsSystemCaller(aCx);
412 : }
413 :
414 : JSObject*
415 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
416 : {
417 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
418 : }
419 :
420 : static const js::ClassOps sClassOps = {
421 : _addProperty, /* addProperty */
422 : nullptr, /* delProperty */
423 : nullptr, /* getProperty */
424 : nullptr, /* setProperty */
425 : nullptr, /* enumerate */
426 : nullptr, /* newEnumerate */
427 : nullptr, /* resolve */
428 : nullptr, /* mayResolve */
429 : _finalize, /* finalize */
430 : nullptr, /* call */
431 : nullptr, /* hasInstance */
432 : nullptr, /* construct */
433 : nullptr, /* trace */
434 : };
435 :
436 : static const js::ClassExtension sClassExtension = {
437 : nullptr, /* weakmapKeyDelegateOp */
438 : _objectMoved /* objectMovedOp */
439 : };
440 :
441 : static const DOMJSClass sClass = {
442 : { "HeapSnapshot",
443 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
444 : &sClassOps,
445 : JS_NULL_CLASS_SPEC,
446 : &sClassExtension,
447 : JS_NULL_OBJECT_OPS
448 : },
449 : { prototypes::id::HeapSnapshot, 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 },
450 : IsBaseOf<nsISupports, mozilla::devtools::HeapSnapshot >::value,
451 : sNativePropertyHooks,
452 : FindAssociatedGlobalForNative<mozilla::devtools::HeapSnapshot>::Get,
453 : GetProtoObjectHandle,
454 : GetCCParticipant<mozilla::devtools::HeapSnapshot>::Get()
455 : };
456 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
457 : "Must have the right minimal number of reserved slots.");
458 : static_assert(1 >= 1,
459 : "Must have enough reserved slots.");
460 :
461 : const JSClass*
462 0 : GetJSClass()
463 : {
464 0 : return sClass.ToJSClass();
465 : }
466 :
467 : bool
468 0 : Wrap(JSContext* aCx, mozilla::devtools::HeapSnapshot* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
469 : {
470 : MOZ_ASSERT(static_cast<mozilla::devtools::HeapSnapshot*>(aObject) ==
471 : reinterpret_cast<mozilla::devtools::HeapSnapshot*>(aObject),
472 : "Multiple inheritance for mozilla::devtools::HeapSnapshot is broken.");
473 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
474 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
475 0 : MOZ_ASSERT(!aCache->GetWrapper(),
476 : "You should probably not be using Wrap() directly; use "
477 : "GetOrCreateDOMReflector instead");
478 :
479 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
480 : "nsISupports must be on our primary inheritance chain");
481 :
482 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
483 0 : if (!global) {
484 0 : return false;
485 : }
486 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
487 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
488 :
489 : // That might have ended up wrapping us already, due to the wonders
490 : // of XBL. Check for that, and bail out as needed.
491 0 : aReflector.set(aCache->GetWrapper());
492 0 : if (aReflector) {
493 : #ifdef DEBUG
494 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
495 : #endif // DEBUG
496 0 : return true;
497 : }
498 :
499 0 : JSAutoCompartment ac(aCx, global);
500 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
501 0 : if (!canonicalProto) {
502 0 : return false;
503 : }
504 0 : JS::Rooted<JSObject*> proto(aCx);
505 0 : if (aGivenProto) {
506 0 : proto = aGivenProto;
507 : // Unfortunately, while aGivenProto was in the compartment of aCx
508 : // coming in, we changed compartments to that of "parent" so may need
509 : // to wrap the proto here.
510 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
511 0 : if (!JS_WrapObject(aCx, &proto)) {
512 0 : return false;
513 : }
514 : }
515 : } else {
516 0 : proto = canonicalProto;
517 : }
518 :
519 0 : BindingJSObjectCreator<mozilla::devtools::HeapSnapshot> creator(aCx);
520 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
521 0 : if (!aReflector) {
522 0 : return false;
523 : }
524 :
525 0 : aCache->SetWrapper(aReflector);
526 0 : creator.InitializationSucceeded();
527 :
528 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
529 : aCache->GetWrapperPreserveColor() == aReflector);
530 : // If proto != canonicalProto, we have to preserve our wrapper;
531 : // otherwise we won't be able to properly recreate it later, since
532 : // we won't know what proto to use. Note that we don't check
533 : // aGivenProto here, since it's entirely possible (and even
534 : // somewhat common) to have a non-null aGivenProto which is the
535 : // same as canonicalProto.
536 0 : if (proto != canonicalProto) {
537 0 : PreserveWrapper(aObject);
538 : }
539 :
540 0 : return true;
541 : }
542 :
543 : const NativePropertyHooks sNativePropertyHooks[] = { {
544 : nullptr,
545 : nullptr,
546 : nullptr,
547 : { sNativeProperties.Upcast(), nullptr },
548 : prototypes::id::HeapSnapshot,
549 : constructors::id::HeapSnapshot,
550 : nullptr,
551 : &DefaultXrayExpandoObjectClass
552 : } };
553 :
554 : void
555 2 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
556 : {
557 4 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
558 2 : if (!parentProto) {
559 0 : return;
560 : }
561 :
562 4 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
563 2 : if (!constructorProto) {
564 0 : return;
565 : }
566 :
567 : static bool sIdsInited = false;
568 2 : if (!sIdsInited && NS_IsMainThread()) {
569 1 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
570 0 : return;
571 : }
572 1 : sIdsInited = true;
573 : }
574 :
575 2 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::HeapSnapshot);
576 2 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::HeapSnapshot);
577 4 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
578 : &sPrototypeClass.mBase, protoCache,
579 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
580 : interfaceCache,
581 : sNativeProperties.Upcast(),
582 : nullptr,
583 : "HeapSnapshot", aDefineOnGlobal,
584 : nullptr,
585 2 : false);
586 : }
587 :
588 : JS::Handle<JSObject*>
589 0 : GetProtoObjectHandle(JSContext* aCx)
590 : {
591 : /* Get the interface prototype object for this class. This will create the
592 : object as needed. */
593 0 : bool aDefineOnGlobal = true;
594 :
595 : /* Make sure our global is sane. Hopefully we can remove this sometime */
596 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
597 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
598 0 : return nullptr;
599 : }
600 :
601 : /* Check to see whether the interface objects are already installed */
602 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
603 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::HeapSnapshot)) {
604 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
605 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
606 : }
607 :
608 : /*
609 : * The object might _still_ be null, but that's OK.
610 : *
611 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
612 : * traced by TraceProtoAndIfaceCache() and its contents are never
613 : * changed after they have been set.
614 : *
615 : * Calling address() avoids the read read barrier that does gray
616 : * unmarking, but it's not possible for the object to be gray here.
617 : */
618 :
619 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::HeapSnapshot);
620 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
621 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
622 : }
623 :
624 : JS::Handle<JSObject*>
625 2 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
626 : {
627 : /* Get the interface object for this class. This will create the object as
628 : needed. */
629 :
630 : /* Make sure our global is sane. Hopefully we can remove this sometime */
631 2 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
632 2 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
633 0 : return nullptr;
634 : }
635 :
636 : /* Check to see whether the interface objects are already installed */
637 2 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
638 2 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::HeapSnapshot)) {
639 4 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
640 2 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
641 : }
642 :
643 : /*
644 : * The object might _still_ be null, but that's OK.
645 : *
646 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
647 : * traced by TraceProtoAndIfaceCache() and its contents are never
648 : * changed after they have been set.
649 : *
650 : * Calling address() avoids the read read barrier that does gray
651 : * unmarking, but it's not possible for the object to be gray here.
652 : */
653 :
654 2 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::HeapSnapshot);
655 2 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
656 2 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
657 : }
658 :
659 : JSObject*
660 2 : GetConstructorObject(JSContext* aCx)
661 : {
662 2 : return GetConstructorObjectHandle(aCx);
663 : }
664 :
665 : } // namespace HeapSnapshotBinding
666 :
667 :
668 :
669 : } // namespace dom
670 : } // namespace mozilla
|