/* THIS FILE IS AUTOGENERATED FROM JSWindowActor.webidl BY Codegen.py - DO NOT EDIT */ #include #include "AtomList.h" #include "JSWindowActorBinding.h" #include "MainThreadUtils.h" #include "WrapperFactory.h" #include "js/Array.h" #include "js/CallAndConstruct.h" #include "js/Exception.h" #include "js/ForOfIterator.h" #include "js/MapAndSet.h" #include "js/Object.h" #include "js/PropertyAndElement.h" #include "js/PropertyDescriptor.h" #include "js/experimental/JitInfo.h" #include "mozilla/Atomics.h" #include "mozilla/OwningNonNull.h" #include "mozilla/ProfilerLabels.h" #include "mozilla/dom/BindingCallContext.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/BrowsingContext.h" #include "mozilla/dom/CanonicalBrowsingContext.h" #include "mozilla/dom/DOMJSClass.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/JSWindowActorChild.h" #include "mozilla/dom/JSWindowActorParent.h" #include "mozilla/dom/NonRefcountedDOMObject.h" #include "mozilla/dom/Nullable.h" #include "mozilla/dom/PrimitiveConversions.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/SimpleGlobalObject.h" #include "mozilla/dom/ToJSValue.h" #include "mozilla/dom/WindowContext.h" #include "mozilla/dom/WindowGlobalChild.h" #include "mozilla/dom/WindowGlobalParent.h" #include "mozilla/dom/WindowProxyHolder.h" #include "mozilla/dom/XrayExpandoClass.h" #include "nsContentUtils.h" #include "nsIDocShell.h" namespace mozilla::dom { namespace binding_detail {}; // Just to make sure it's known as a namespace using namespace mozilla::dom::binding_detail; WindowActorChildOptions::WindowActorChildOptions() : JSActorSidedOptions(FastDictionaryInitializer()) { // Safe to pass a null context if we pass a null value Init(nullptr, JS::NullHandleValue); } bool WindowActorChildOptions::InitIds(JSContext* cx, WindowActorChildOptionsAtoms* atomsCache) { MOZ_ASSERT(reinterpret_cast(atomsCache)->isVoid()); // Initialize these in reverse order so that any failure leaves the first one // uninitialized. if (!atomsCache->observers_id.init(cx, "observers") || !atomsCache->events_id.init(cx, "events")) { return false; } return true; } bool WindowActorChildOptions::Init(BindingCallContext& cx, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // Passing a null JSContext is OK only if we're initing from null, // Since in that case we will not have to do any property gets // Also evaluate isNullOrUndefined in order to avoid false-positive // checkers by static analysis tools MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined()); WindowActorChildOptionsAtoms* atomsCache = nullptr; if (cx) { atomsCache = GetAtomCache(cx); if (reinterpret_cast(atomsCache)->isVoid() && !InitIds(cx, atomsCache)) { return false; } } // Per spec, we init the parent's members first if (!JSActorSidedOptions::Init(cx, val)) { return false; } bool isNull = val.isNullOrUndefined(); // We only need these if !isNull, in which case we have |cx|. Maybe > object; Maybe > temp; if (!isNull) { MOZ_ASSERT(cx); object.emplace(cx, &val.toObject()); temp.emplace(cx); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->events_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { mEvents.Construct(); if (temp.ref().isObject()) { auto& recordEntries = (mEvents.Value()).Entries(); JS::Rooted recordObj(cx, &temp.ref().toObject()); JS::RootedVector ids(cx); if (!js::GetPropertyKeys(cx, recordObj, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, &ids)) { return false; } if (!recordEntries.SetCapacity(ids.length(), mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } JS::Rooted propNameValue(cx); JS::Rooted temp(cx); JS::Rooted curId(cx); JS::Rooted idVal(cx); // Use a hashset to keep track of ids seen, to avoid // introducing nasty O(N^2) behavior scanning for them all the // time. Ideally we'd use a data structure with O(1) lookup // _and_ ordering for the MozMap, but we don't have one lying // around. nsTHashtable idsSeen; for (size_t i = 0; i < ids.length(); ++i) { curId = ids[i]; JS::Rooted> desc(cx); if (!JS_GetOwnPropertyDescriptorById(cx, recordObj, curId, &desc)) { return false; } if (desc.isNothing() || !desc->enumerable()) { continue; } idVal = js::IdToValue(curId); nsString propName; // This will just throw if idVal is a Symbol, like the spec says // to do. if (!ConvertJSValueToString(cx, idVal, "key of 'events' member of WindowActorChildOptions", propName)) { return false; } if (!JS_GetPropertyById(cx, recordObj, curId, &temp)) { return false; } Record::EntryType* entry; if (!idsSeen.EnsureInserted(propName)) { // Find the existing entry. auto idx = recordEntries.IndexOf(propName); MOZ_ASSERT(idx != recordEntries.NoIndex, "Why is it not found?"); // Now blow it away to make it look like it was just added // to the array, because it's not obvious that it's // safe to write to its already-initialized mValue via our // normal codegen conversions. For example, the value // could be a union and this would change its type, but // codegen assumes we won't do that. entry = recordEntries.ReconstructElementAt(idx); } else { // Safe to do an infallible append here, because we did a // SetCapacity above to the right capacity. entry = recordEntries.AppendElement(); } entry->mKey = propName; WindowActorEventListenerOptions& slot = entry->mValue; if (!slot.Init(cx, temp, "Value in 'events' member of WindowActorChildOptions", passedToJSImpl)) { return false; } } } else { cx.ThrowErrorMessage("'events' member of WindowActorChildOptions"); return false; } mIsAnyMemberPresent = true; } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->observers_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { mObservers.Construct(); if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'observers' member of WindowActorChildOptions", "sequence"); return false; } Sequence &arr = (mObservers.Value()); if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } nsCString* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } nsCString& slot = *slotPtr; if (!ConvertJSValueToByteString(cx, temp, false, "element of 'observers' member of WindowActorChildOptions", slot)) { return false; } } } else { cx.ThrowErrorMessage("'observers' member of WindowActorChildOptions", "sequence"); return false; } mIsAnyMemberPresent = true; } return true; } bool WindowActorChildOptions::Init(JSContext* cx_, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // We don't want to use sourceDescription for our context here; // that's not really what it's formatted for. BindingCallContext cx(cx_, nullptr); return Init(cx, val, sourceDescription, passedToJSImpl); } void WindowActorChildOptions::TraceDictionary(JSTracer* trc) { JSActorSidedOptions::TraceDictionary(trc); } WindowActorEventListenerOptions::WindowActorEventListenerOptions() : AddEventListenerOptions(FastDictionaryInitializer()) { // Safe to pass a null context if we pass a null value Init(nullptr, JS::NullHandleValue); } bool WindowActorEventListenerOptions::InitIds(JSContext* cx, WindowActorEventListenerOptionsAtoms* atomsCache) { MOZ_ASSERT(reinterpret_cast(atomsCache)->isVoid()); // Initialize these in reverse order so that any failure leaves the first one // uninitialized. if (!atomsCache->createActor_id.init(cx, "createActor")) { return false; } return true; } bool WindowActorEventListenerOptions::Init(BindingCallContext& cx, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // Passing a null JSContext is OK only if we're initing from null, // Since in that case we will not have to do any property gets // Also evaluate isNullOrUndefined in order to avoid false-positive // checkers by static analysis tools MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined()); WindowActorEventListenerOptionsAtoms* atomsCache = nullptr; if (cx) { atomsCache = GetAtomCache(cx); if (reinterpret_cast(atomsCache)->isVoid() && !InitIds(cx, atomsCache)) { return false; } } // Per spec, we init the parent's members first if (!AddEventListenerOptions::Init(cx, val)) { return false; } bool isNull = val.isNullOrUndefined(); // We only need these if !isNull, in which case we have |cx|. Maybe > object; Maybe > temp; if (!isNull) { MOZ_ASSERT(cx); object.emplace(cx, &val.toObject()); temp.emplace(cx); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->createActor_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ValueToPrimitive(cx, temp.ref(), "'createActor' member of WindowActorEventListenerOptions", &mCreateActor)) { return false; } } else { mCreateActor = true; } mIsAnyMemberPresent = true; return true; } bool WindowActorEventListenerOptions::Init(JSContext* cx_, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // We don't want to use sourceDescription for our context here; // that's not really what it's formatted for. BindingCallContext cx(cx_, nullptr); return Init(cx, val, sourceDescription, passedToJSImpl); } void WindowActorEventListenerOptions::TraceDictionary(JSTracer* trc) { AddEventListenerOptions::TraceDictionary(trc); } WindowActorEventListenerOptions& WindowActorEventListenerOptions::operator=(const WindowActorEventListenerOptions& aOther) { AddEventListenerOptions::operator=(aOther); mCreateActor = aOther.mCreateActor; return *this; } WindowActorOptions::WindowActorOptions() : JSActorOptions(FastDictionaryInitializer()) { // Safe to pass a null context if we pass a null value Init(nullptr, JS::NullHandleValue); } bool WindowActorOptions::InitIds(JSContext* cx, WindowActorOptionsAtoms* atomsCache) { MOZ_ASSERT(reinterpret_cast(atomsCache)->isVoid()); // Initialize these in reverse order so that any failure leaves the first one // uninitialized. if (!atomsCache->parent_id.init(cx, "parent") || !atomsCache->messageManagerGroups_id.init(cx, "messageManagerGroups") || !atomsCache->matches_id.init(cx, "matches") || !atomsCache->includeChrome_id.init(cx, "includeChrome") || !atomsCache->child_id.init(cx, "child") || !atomsCache->allFrames_id.init(cx, "allFrames")) { return false; } return true; } bool WindowActorOptions::Init(BindingCallContext& cx, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // Passing a null JSContext is OK only if we're initing from null, // Since in that case we will not have to do any property gets // Also evaluate isNullOrUndefined in order to avoid false-positive // checkers by static analysis tools MOZ_ASSERT_IF(!cx, val.isNull() && val.isNullOrUndefined()); WindowActorOptionsAtoms* atomsCache = nullptr; if (cx) { atomsCache = GetAtomCache(cx); if (reinterpret_cast(atomsCache)->isVoid() && !InitIds(cx, atomsCache)) { return false; } } // Per spec, we init the parent's members first if (!JSActorOptions::Init(cx, val)) { return false; } bool isNull = val.isNullOrUndefined(); // We only need these if !isNull, in which case we have |cx|. Maybe > object; Maybe > temp; if (!isNull) { MOZ_ASSERT(cx); object.emplace(cx, &val.toObject()); temp.emplace(cx); } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->allFrames_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ValueToPrimitive(cx, temp.ref(), "'allFrames' member of WindowActorOptions", &mAllFrames)) { return false; } } else { mAllFrames = false; } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->child_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { mChild.Construct(); if (!(mChild.Value()).Init(cx, temp.ref(), "'child' member of WindowActorOptions", passedToJSImpl)) { return false; } mIsAnyMemberPresent = true; } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->includeChrome_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { if (!ValueToPrimitive(cx, temp.ref(), "'includeChrome' member of WindowActorOptions", &mIncludeChrome)) { return false; } } else { mIncludeChrome = false; } mIsAnyMemberPresent = true; if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->matches_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { mMatches.Construct(); if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'matches' member of WindowActorOptions", "sequence"); return false; } Sequence &arr = (mMatches.Value()); if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } nsString* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } nsString& slot = *slotPtr; if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) { return false; } } } else { cx.ThrowErrorMessage("'matches' member of WindowActorOptions", "sequence"); return false; } mIsAnyMemberPresent = true; } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->messageManagerGroups_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { mMessageManagerGroups.Construct(); if (temp.ref().isObject()) { JS::ForOfIterator iter(cx); if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) { return false; } if (!iter.valueIsIterable()) { cx.ThrowErrorMessage("'messageManagerGroups' member of WindowActorOptions", "sequence"); return false; } Sequence &arr = (mMessageManagerGroups.Value()); if (mozilla::Maybe sizeHint = iter.sizeHint()) { if (!arr.SetCapacity(*sizeHint, mozilla::fallible)) { JS_ReportOutOfMemory(cx); return false; } } JS::Rooted temp(cx); while (true) { bool done; if (!iter.next(&temp, &done)) { return false; } if (done) { break; } nsString* slotPtr = arr.AppendElement(mozilla::fallible); if (!slotPtr) { JS_ReportOutOfMemory(cx); return false; } nsString& slot = *slotPtr; if (!ConvertJSValueToString(cx, temp, eStringify, eStringify, slot)) { return false; } } } else { cx.ThrowErrorMessage("'messageManagerGroups' member of WindowActorOptions", "sequence"); return false; } mIsAnyMemberPresent = true; } if (!isNull) { if (!JS_GetPropertyById(cx, *object, atomsCache->parent_id, temp.ptr())) { return false; } } if (!isNull && !temp->isUndefined()) { mParent.Construct(); if (!(mParent.Value()).Init(cx, temp.ref(), "'parent' member of WindowActorOptions", passedToJSImpl)) { return false; } mIsAnyMemberPresent = true; } return true; } bool WindowActorOptions::Init(JSContext* cx_, JS::Handle val, const char* sourceDescription, bool passedToJSImpl) { // We don't want to use sourceDescription for our context here; // that's not really what it's formatted for. BindingCallContext cx(cx_, nullptr); return Init(cx, val, sourceDescription, passedToJSImpl); } void WindowActorOptions::TraceDictionary(JSTracer* trc) { JSActorOptions::TraceDictionary(trc); } namespace JSWindowActorChild_Binding { MOZ_CAN_RUN_SCRIPT static bool get_manager(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "manager", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); auto result(StrongOrRawPtr(MOZ_KnownLive(self)->GetManager())); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const JSJitInfo manager_getterinfo = { { get_manager }, { prototypes::id::JSWindowActorChild }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_windowContext(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "windowContext", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); auto result(StrongOrRawPtr(MOZ_KnownLive(self)->GetWindowContext())); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const JSJitInfo windowContext_getterinfo = { { get_windowContext }, { prototypes::id::JSWindowActorChild }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_document(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "document", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); FastErrorResult rv; auto result(StrongOrRawPtr(MOZ_KnownLive(self)->GetDocument(rv))); if (rv.MaybeSetPendingException(cx, "JSWindowActorChild.document getter")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const JSJitInfo document_getterinfo = { { get_document }, { prototypes::id::JSWindowActorChild }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_browsingContext(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "browsingContext", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); FastErrorResult rv; auto result(StrongOrRawPtr(MOZ_KnownLive(self)->GetBrowsingContext(rv))); if (rv.MaybeSetPendingException(cx, "JSWindowActorChild.browsingContext getter")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const JSJitInfo browsingContext_getterinfo = { { get_browsingContext }, { prototypes::id::JSWindowActorChild }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_docShell(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "docShell", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); FastErrorResult rv; auto result(StrongOrRawPtr(MOZ_KnownLive(self)->GetDocShell(rv))); if (rv.MaybeSetPendingException(cx, "JSWindowActorChild.docShell getter")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!WrapObject(cx, result, &NS_GET_IID(nsIDocShell), args.rval())) { return false; } return true; } static const JSJitInfo docShell_getterinfo = { { get_docShell }, { prototypes::id::JSWindowActorChild }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_contentWindow(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "contentWindow", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); FastErrorResult rv; Nullable result(MOZ_KnownLive(self)->GetContentWindow(rv)); if (rv.MaybeSetPendingException(cx, "JSWindowActorChild.contentWindow getter")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (result.IsNull()) { args.rval().setNull(); return true; } if (!WrapObject(cx, result.Value(), args.rval())) { return false; } return true; } static const JSJitInfo contentWindow_getterinfo = { { get_contentWindow }, { prototypes::id::JSWindowActorChild }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool sendAsyncMessage(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "sendAsyncMessage", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "JSWindowActorChild.sendAsyncMessage", 1)) { return false; } nsAutoString arg0; if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } JS::Rooted arg1(cx); if (args.hasDefined(1)) { arg1 = args[1]; } else { arg1 = JS::UndefinedValue(); } JS::Rooted arg2(cx); if (args.hasDefined(2)) { arg2 = args[2]; } else { arg2 = JS::UndefinedValue(); } FastErrorResult rv; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vSendAsyncMessage(cx, NonNullHelper(Constify(arg0)), arg1, arg2, rv))>, "Should be returning void here"); MOZ_KnownLive(self)->SendAsyncMessage(cx, NonNullHelper(Constify(arg0)), arg1, arg2, rv); if (rv.MaybeSetPendingException(cx, "JSWindowActorChild.sendAsyncMessage")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setUndefined(); return true; } static const JSJitInfo sendAsyncMessage_methodinfo = { { (JSJitGetterOp)sendAsyncMessage }, { prototypes::id::JSWindowActorChild }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool sendQuery(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "sendQuery", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "JSWindowActorChild.sendQuery", 1)) { return false; } nsAutoString arg0; if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } JS::Rooted arg1(cx); if (args.hasDefined(1)) { arg1 = args[1]; } else { arg1 = JS::UndefinedValue(); } FastErrorResult rv; auto result(StrongOrRawPtr(MOZ_KnownLive(self)->SendQuery(cx, NonNullHelper(Constify(arg0)), arg1, rv))); if (rv.MaybeSetPendingException(cx, "JSWindowActorChild.sendQuery")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); static_assert(!std::is_pointer_v, "NewObject implies that we need to keep the object alive with a strong reference."); if (!ToJSValue(cx, result, args.rval())) { return false; } return true; } MOZ_CAN_RUN_SCRIPT static bool sendQuery_promiseWrapper(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { bool ok = sendQuery(cx, obj, void_self, args); if (ok) { return true; } return ConvertExceptionToPromise(cx, args.rval()); } static const JSJitInfo sendQuery_methodinfo = { { (JSJitGetterOp)sendQuery_promiseWrapper }, { prototypes::id::JSWindowActorChild }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_name(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "name", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); nsAutoCString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetName(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetName(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!NonVoidUTF8StringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo name_getterinfo = { { get_name }, { prototypes::id::JSWindowActorChild }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; static void _finalize(JS::GCContext* gcx, JSObject* obj) { mozilla::dom::JSWindowActorChild* self = UnwrapPossiblyNotInitializedDOMObject(obj); if (self) { JS::SetNativeObjectReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue()); ClearWrapper(self, self, obj); if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) { JS::RemoveAssociatedMemory(obj, mallocBytes, JS::MemoryUse::DOMBinding); } AddForDeferredFinalization(self); } } MOZ_GLOBINIT static const JSFunctionSpec sMethods_specs[] = { JS_FNSPEC("sendAsyncMessage", (GenericMethod), reinterpret_cast(&sendAsyncMessage_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("sendQuery", (GenericMethod), reinterpret_cast(&sendQuery_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FS_END }; static const Prefable sMethods[] = { { nullptr, &sMethods_specs[0] }, { nullptr, nullptr } }; static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX, "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)"); static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX, "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)"); MOZ_GLOBINIT static const JSPropertySpec sAttributes_specs[] = { JSPropertySpec::nativeAccessors("manager", JSPROP_ENUMERATE, GenericGetter, &manager_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("windowContext", JSPROP_ENUMERATE, GenericGetter, &windowContext_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("document", JSPROP_ENUMERATE, GenericGetter, &document_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("browsingContext", JSPROP_ENUMERATE, GenericGetter, &browsingContext_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("docShell", JSPROP_ENUMERATE, GenericGetter, &docShell_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("contentWindow", JSPROP_ENUMERATE, GenericGetter, &contentWindow_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("name", JSPROP_ENUMERATE, GenericGetter, &name_getterinfo, nullptr, nullptr), JS_PS_END }; static const Prefable sAttributes[] = { { nullptr, &sAttributes_specs[0] }, { nullptr, nullptr } }; static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX, "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)"); static_assert(7 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX, "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)"); static uint16_t sNativeProperties_sortedPropertyIndices[9]; static PropertyInfo sNativeProperties_propertyInfos[9]; static const NativePropertiesN<2> sNativeProperties = { false, 0, false, 0, true, 0 /* sMethods */, true, 1 /* sAttributes */, false, 0, false, 0, false, 0, -1, 9, sNativeProperties_sortedPropertyIndices, { { sMethods, &sNativeProperties_propertyInfos[0] }, { sAttributes, &sNativeProperties_propertyInfos[2] } } }; static_assert(9 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)), "We have a property info count that is oversized"); bool sNativePropertiesInited = false; const NativePropertyHooks sNativePropertyHooks = { nullptr, { sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited }, prototypes::id::JSWindowActorChild, constructors::id::JSWindowActorChild, &DefaultXrayExpandoObjectClass }; static bool _constructor(JSContext* cx, unsigned argc, JS::Value* vp) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorChild", "constructor", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); if (!nsContentUtils::ThreadsafeIsSystemCaller(cx)) { return ThrowingConstructor(cx, argc, vp); } if (!args.isConstructing()) { return ThrowConstructorWithoutNew(cx, "JSWindowActorChild"); } JS::Rooted desiredProto(cx); if (!GetDesiredProto(cx, args, prototypes::id::JSWindowActorChild, CreateInterfaceObjects, &desiredProto)) { return false; } GlobalObject global(cx, obj); if (global.Failed()) { return false; } bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj); Maybe ar; if (objIsXray) { // Since our object is an Xray, we can just CheckedUnwrapStatic: // we know Xrays have no dynamic unwrap behavior. obj = js::CheckedUnwrapStatic(obj); if (!obj) { return false; } ar.emplace(cx, obj); if (!JS_WrapObject(cx, &desiredProto)) { return false; } } auto result(StrongOrRawPtr(mozilla::dom::JSWindowActorChild::Constructor(global))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); static_assert(!std::is_pointer_v, "NewObject implies that we need to keep the object alive with a strong reference."); if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const DOMInterfaceInfo sInterfaceObjectInfo = { { _constructor, &sNativePropertyHooks }, JS::GetRealmFunctionPrototypeHandle, PrototypeTraits::Depth, prototypes::id::JSWindowActorChild, true, 0, "JSWindowActorChild", }; static const DOMIfaceAndProtoJSClass sPrototypeClass = { { "JSWindowActorChildPrototype", JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE), JS_NULL_CLASS_OPS, JS_NULL_CLASS_SPEC, JS_NULL_CLASS_EXT, JS_NULL_OBJECT_OPS }, eInterfacePrototype, prototypes::id::JSWindowActorChild, PrototypeTraits::Depth, &sNativePropertyHooks, JS::GetRealmObjectPrototype }; bool ConstructorEnabled(JSContext* aCx, JS::Handle aObj) { return nsContentUtils::ThreadsafeIsSystemCaller(aCx); } static JS::Handle GetProtoObjectHandle(JSContext* aCx); static const JSClassOps sClassOps = { nullptr, /* addProperty */ nullptr, /* delProperty */ nullptr, /* enumerate */ nullptr, /* newEnumerate */ nullptr, /* resolve */ nullptr, /* mayResolve */ _finalize, /* finalize */ nullptr, /* call */ nullptr, /* construct */ nullptr, /* trace */ }; static const DOMJSClass sClass = { { "JSWindowActorChild", JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_PRESERVES_WRAPPER, &sClassOps, JS_NULL_CLASS_SPEC, &NativeTypeHelpers::sClassExtension, JS_NULL_OBJECT_OPS }, { prototypes::id::JSWindowActorChild, 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 }, std::is_base_of_v, &sNativePropertyHooks, GetProtoObjectHandle, GetCCParticipant::Get(), nullptr, NativeTypeHelpers::GetWrapperCache }; static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS, "Must have the right minimal number of reserved slots."); static_assert(1 >= 1, "Must have enough reserved slots."); bool Wrap(JSContext* aCx, mozilla::dom::JSWindowActorChild* aObject, nsWrapperCache* aCache, JS::Handle aGivenProto, JS::MutableHandle aReflector) { static_assert(!std::is_base_of_v, "Shouldn't have wrappercached things that are not refcounted."); static_assert(std::is_same_v); MOZ_ASSERT(ToSupportsIsCorrect(aObject)); MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx)); MOZ_ASSERT(!aCache->GetWrapper(), "You should probably not be using Wrap() directly; use " "GetOrCreateDOMReflector instead"); MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache), "nsISupports must be on our primary inheritance chain"); // If the wrapper cache contains a dead reflector then finalize that // now, ensuring that the finalizer for the old reflector always // runs before the new reflector is created and attached. This // avoids the awkward situation where there are multiple reflector // objects that contain pointers to the same native. if (JSObject* oldReflector = aCache->GetWrapperMaybeDead()) { _finalize(nullptr /* unused */, oldReflector); MOZ_ASSERT(!aCache->GetWrapperMaybeDead()); } JS::Rooted global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject())); if (!global) { return false; } MOZ_ASSERT(JS_IsGlobalObject(global)); JS::AssertObjectIsNotGray(global); // That might have ended up wrapping us already, due to the wonders // of XBL. Check for that, and bail out as needed. aReflector.set(aCache->GetWrapper()); if (aReflector) { #ifdef DEBUG AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto); #endif // DEBUG return true; } JSAutoRealm ar(aCx, global); JS::Handle canonicalProto = GetProtoObjectHandle(aCx); if (!canonicalProto) { return false; } JS::Rooted proto(aCx); if (aGivenProto) { proto = aGivenProto; // Unfortunately, while aGivenProto was in the compartment of aCx // coming in, we changed compartments to that of "parent" so may need // to wrap the proto here. if (js::GetContextCompartment(aCx) != JS::GetCompartment(proto)) { if (!JS_WrapObject(aCx, &proto)) { return false; } } } else { proto = canonicalProto; } BindingJSObjectCreator creator(aCx); creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector); if (!aReflector) { return false; } aCache->SetWrapper(aReflector); creator.InitializationSucceeded(); MOZ_ASSERT(aCache->GetWrapperPreserveColor() && aCache->GetWrapperPreserveColor() == aReflector); // If proto != canonicalProto, we have to preserve our wrapper; // otherwise we won't be able to properly recreate it later, since // we won't know what proto to use. Note that we don't check // aGivenProto here, since it's entirely possible (and even // somewhat common) to have a non-null aGivenProto which is the // same as canonicalProto. if (proto != canonicalProto) { PreserveWrapper(aObject); } return true; } void CreateInterfaceObjects(JSContext* aCx, JS::Handle aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, DefineInterfaceProperty aDefineOnGlobal) { JS::Heap* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::JSWindowActorChild); JS::Heap* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::JSWindowActorChild); JS::Handle parentProto(JS::GetRealmObjectPrototypeHandle(aCx)); if (!parentProto) { return; } JS::Handle constructorProto(JS::GetRealmFunctionPrototypeHandle(aCx)); if (!constructorProto) { return; } dom::CreateInterfaceObjects(aCx, aGlobal, parentProto, &sPrototypeClass, protoCache, constructorProto, &sInterfaceObjectInfo, 0, true, Span{}, interfaceCache, sNativeProperties.Upcast(), nullptr, "JSWindowActorChild", ShouldExpose(aCx, aGlobal, aDefineOnGlobal), nullptr, false, nullptr); } static JS::Handle GetProtoObjectHandle(JSContext* aCx) { /* Get the interface prototype object for this class. This will create the object as needed. */ return GetPerInterfaceObjectHandle(aCx, prototypes::id::JSWindowActorChild, &CreateInterfaceObjects, DefineInterfaceProperty::CheckExposure); } JS::Handle GetConstructorObjectHandle(JSContext* aCx) { /* Get the interface object for this class. This will create the object as needed. */ return GetPerInterfaceObjectHandle(aCx, constructors::id::JSWindowActorChild, &CreateInterfaceObjects, DefineInterfaceProperty::CheckExposure); } } // namespace JSWindowActorChild_Binding namespace JSWindowActorParent_Binding { MOZ_CAN_RUN_SCRIPT static bool get_manager(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorParent", "manager", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); auto result(StrongOrRawPtr(MOZ_KnownLive(self)->GetManager())); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const JSJitInfo manager_getterinfo = { { get_manager }, { prototypes::id::JSWindowActorParent }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_windowContext(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorParent", "windowContext", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); auto result(StrongOrRawPtr(MOZ_KnownLive(self)->GetWindowContext())); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const JSJitInfo windowContext_getterinfo = { { get_windowContext }, { prototypes::id::JSWindowActorParent }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_browsingContext(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorParent", "browsingContext", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); FastErrorResult rv; auto result(StrongOrRawPtr(MOZ_KnownLive(self)->GetBrowsingContext(rv))); if (rv.MaybeSetPendingException(cx, "JSWindowActorParent.browsingContext getter")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!result) { args.rval().setNull(); return true; } if (!GetOrCreateDOMReflector(cx, result, args.rval())) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const JSJitInfo browsingContext_getterinfo = { { get_browsingContext }, { prototypes::id::JSWindowActorParent }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNKNOWN, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool sendAsyncMessage(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorParent", "sendAsyncMessage", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "JSWindowActorParent.sendAsyncMessage", 1)) { return false; } nsAutoString arg0; if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } JS::Rooted arg1(cx); if (args.hasDefined(1)) { arg1 = args[1]; } else { arg1 = JS::UndefinedValue(); } JS::Rooted arg2(cx); if (args.hasDefined(2)) { arg2 = args[2]; } else { arg2 = JS::UndefinedValue(); } FastErrorResult rv; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vSendAsyncMessage(cx, NonNullHelper(Constify(arg0)), arg1, arg2, rv))>, "Should be returning void here"); MOZ_KnownLive(self)->SendAsyncMessage(cx, NonNullHelper(Constify(arg0)), arg1, arg2, rv); if (rv.MaybeSetPendingException(cx, "JSWindowActorParent.sendAsyncMessage")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); args.rval().setUndefined(); return true; } static const JSJitInfo sendAsyncMessage_methodinfo = { { (JSJitGetterOp)sendAsyncMessage }, { prototypes::id::JSWindowActorParent }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool sendQuery(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorParent", "sendQuery", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); if (!args.requireAtLeast(cx, "JSWindowActorParent.sendQuery", 1)) { return false; } nsAutoString arg0; if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) { return false; } JS::Rooted arg1(cx); if (args.hasDefined(1)) { arg1 = args[1]; } else { arg1 = JS::UndefinedValue(); } FastErrorResult rv; auto result(StrongOrRawPtr(MOZ_KnownLive(self)->SendQuery(cx, NonNullHelper(Constify(arg0)), arg1, rv))); if (rv.MaybeSetPendingException(cx, "JSWindowActorParent.sendQuery")) [[unlikely]] { return false; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); static_assert(!std::is_pointer_v, "NewObject implies that we need to keep the object alive with a strong reference."); if (!ToJSValue(cx, result, args.rval())) { return false; } return true; } MOZ_CAN_RUN_SCRIPT static bool sendQuery_promiseWrapper(JSContext* cx, JS::Handle obj, void* void_self, const JSJitMethodCallArgs& args) { bool ok = sendQuery(cx, obj, void_self, args); if (ok) { return true; } return ConvertExceptionToPromise(cx, args.rval()); } static const JSJitInfo sendQuery_methodinfo = { { (JSJitGetterOp)sendQuery_promiseWrapper }, { prototypes::id::JSWindowActorParent }, { PrototypeTraits::Depth }, JSJitInfo::Method, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_OBJECT, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; MOZ_CAN_RUN_SCRIPT static bool get_name(JSContext* cx, JS::Handle obj, void* void_self, JSJitGetterCallArgs args) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorParent", "name", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) | uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); auto* self = static_cast(void_self); nsAutoCString result; // NOTE: This assert does NOT call the function. static_assert(std::is_void_vGetName(result))>, "Should be returning void here"); MOZ_KnownLive(self)->GetName(result); MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!NonVoidUTF8StringToJsval(cx, result, args.rval())) { return false; } return true; } static const JSJitInfo name_getterinfo = { { get_name }, { prototypes::id::JSWindowActorParent }, { PrototypeTraits::Depth }, JSJitInfo::Getter, JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */ JSVAL_TYPE_STRING, /* returnType. Not relevant for setters. */ false, /* isInfallible. False in setters. */ false, /* isMovable. Not relevant for setters. */ false, /* isEliminatable. Not relevant for setters. */ false, /* isAlwaysInSlot. Only relevant for getters. */ false, /* isLazilyCachedInSlot. Only relevant for getters. */ false, /* isTypedMethod. Only relevant for methods. */ 0 /* Reserved slot index, if we're stored in a slot, else 0. */ }; static void _finalize(JS::GCContext* gcx, JSObject* obj) { mozilla::dom::JSWindowActorParent* self = UnwrapPossiblyNotInitializedDOMObject(obj); if (self) { JS::SetNativeObjectReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue()); ClearWrapper(self, self, obj); if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) { JS::RemoveAssociatedMemory(obj, mallocBytes, JS::MemoryUse::DOMBinding); } AddForDeferredFinalization(self); } } MOZ_GLOBINIT static const JSFunctionSpec sMethods_specs[] = { JS_FNSPEC("sendAsyncMessage", (GenericMethod), reinterpret_cast(&sendAsyncMessage_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FNSPEC("sendQuery", (GenericMethod), reinterpret_cast(&sendQuery_methodinfo), 1, JSPROP_ENUMERATE, nullptr), JS_FS_END }; static const Prefable sMethods[] = { { nullptr, &sMethods_specs[0] }, { nullptr, nullptr } }; static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX, "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)"); static_assert(2 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX, "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)"); MOZ_GLOBINIT static const JSPropertySpec sAttributes_specs[] = { JSPropertySpec::nativeAccessors("manager", JSPROP_ENUMERATE, GenericGetter, &manager_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("windowContext", JSPROP_ENUMERATE, GenericGetter, &windowContext_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("browsingContext", JSPROP_ENUMERATE, GenericGetter, &browsingContext_getterinfo, nullptr, nullptr), JSPropertySpec::nativeAccessors("name", JSPROP_ENUMERATE, GenericGetter, &name_getterinfo, nullptr, nullptr), JS_PS_END }; static const Prefable sAttributes[] = { { nullptr, &sAttributes_specs[0] }, { nullptr, nullptr } }; static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX, "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)"); static_assert(4 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX, "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)"); static uint16_t sNativeProperties_sortedPropertyIndices[6]; static PropertyInfo sNativeProperties_propertyInfos[6]; static const NativePropertiesN<2> sNativeProperties = { false, 0, false, 0, true, 0 /* sMethods */, true, 1 /* sAttributes */, false, 0, false, 0, false, 0, -1, 6, sNativeProperties_sortedPropertyIndices, { { sMethods, &sNativeProperties_propertyInfos[0] }, { sAttributes, &sNativeProperties_propertyInfos[2] } } }; static_assert(6 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)), "We have a property info count that is oversized"); bool sNativePropertiesInited = false; const NativePropertyHooks sNativePropertyHooks = { nullptr, { sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited }, prototypes::id::JSWindowActorParent, constructors::id::JSWindowActorParent, &DefaultXrayExpandoObjectClass }; static bool _constructor(JSContext* cx, unsigned argc, JS::Value* vp) { AUTO_PROFILER_LABEL_DYNAMIC_FAST( "JSWindowActorParent", "constructor", DOM, cx, uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS)); JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JS::Rooted obj(cx, &args.callee()); if (!nsContentUtils::ThreadsafeIsSystemCaller(cx)) { return ThrowingConstructor(cx, argc, vp); } if (!args.isConstructing()) { return ThrowConstructorWithoutNew(cx, "JSWindowActorParent"); } JS::Rooted desiredProto(cx); if (!GetDesiredProto(cx, args, prototypes::id::JSWindowActorParent, CreateInterfaceObjects, &desiredProto)) { return false; } GlobalObject global(cx, obj); if (global.Failed()) { return false; } bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj); Maybe ar; if (objIsXray) { // Since our object is an Xray, we can just CheckedUnwrapStatic: // we know Xrays have no dynamic unwrap behavior. obj = js::CheckedUnwrapStatic(obj); if (!obj) { return false; } ar.emplace(cx, obj); if (!JS_WrapObject(cx, &desiredProto)) { return false; } } auto result(StrongOrRawPtr(mozilla::dom::JSWindowActorParent::Constructor(global))); MOZ_ASSERT(!JS_IsExceptionPending(cx)); static_assert(!std::is_pointer_v, "NewObject implies that we need to keep the object alive with a strong reference."); if (!GetOrCreateDOMReflector(cx, result, args.rval(), desiredProto)) { MOZ_ASSERT(JS_IsExceptionPending(cx)); return false; } return true; } static const DOMInterfaceInfo sInterfaceObjectInfo = { { _constructor, &sNativePropertyHooks }, JS::GetRealmFunctionPrototypeHandle, PrototypeTraits::Depth, prototypes::id::JSWindowActorParent, true, 0, "JSWindowActorParent", }; static const DOMIfaceAndProtoJSClass sPrototypeClass = { { "JSWindowActorParentPrototype", JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE), JS_NULL_CLASS_OPS, JS_NULL_CLASS_SPEC, JS_NULL_CLASS_EXT, JS_NULL_OBJECT_OPS }, eInterfacePrototype, prototypes::id::JSWindowActorParent, PrototypeTraits::Depth, &sNativePropertyHooks, JS::GetRealmObjectPrototype }; bool ConstructorEnabled(JSContext* aCx, JS::Handle aObj) { return nsContentUtils::ThreadsafeIsSystemCaller(aCx); } static JS::Handle GetProtoObjectHandle(JSContext* aCx); static const JSClassOps sClassOps = { nullptr, /* addProperty */ nullptr, /* delProperty */ nullptr, /* enumerate */ nullptr, /* newEnumerate */ nullptr, /* resolve */ nullptr, /* mayResolve */ _finalize, /* finalize */ nullptr, /* call */ nullptr, /* construct */ nullptr, /* trace */ }; static const DOMJSClass sClass = { { "JSWindowActorParent", JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_PRESERVES_WRAPPER, &sClassOps, JS_NULL_CLASS_SPEC, &NativeTypeHelpers::sClassExtension, JS_NULL_OBJECT_OPS }, { prototypes::id::JSWindowActorParent, 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 }, std::is_base_of_v, &sNativePropertyHooks, GetProtoObjectHandle, GetCCParticipant::Get(), nullptr, NativeTypeHelpers::GetWrapperCache }; static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS, "Must have the right minimal number of reserved slots."); static_assert(1 >= 1, "Must have enough reserved slots."); bool Wrap(JSContext* aCx, mozilla::dom::JSWindowActorParent* aObject, nsWrapperCache* aCache, JS::Handle aGivenProto, JS::MutableHandle aReflector) { static_assert(!std::is_base_of_v, "Shouldn't have wrappercached things that are not refcounted."); static_assert(std::is_same_v); MOZ_ASSERT(ToSupportsIsCorrect(aObject)); MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx)); MOZ_ASSERT(!aCache->GetWrapper(), "You should probably not be using Wrap() directly; use " "GetOrCreateDOMReflector instead"); MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache), "nsISupports must be on our primary inheritance chain"); // If the wrapper cache contains a dead reflector then finalize that // now, ensuring that the finalizer for the old reflector always // runs before the new reflector is created and attached. This // avoids the awkward situation where there are multiple reflector // objects that contain pointers to the same native. if (JSObject* oldReflector = aCache->GetWrapperMaybeDead()) { _finalize(nullptr /* unused */, oldReflector); MOZ_ASSERT(!aCache->GetWrapperMaybeDead()); } JS::Rooted global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject())); if (!global) { return false; } MOZ_ASSERT(JS_IsGlobalObject(global)); JS::AssertObjectIsNotGray(global); // That might have ended up wrapping us already, due to the wonders // of XBL. Check for that, and bail out as needed. aReflector.set(aCache->GetWrapper()); if (aReflector) { #ifdef DEBUG AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto); #endif // DEBUG return true; } JSAutoRealm ar(aCx, global); JS::Handle canonicalProto = GetProtoObjectHandle(aCx); if (!canonicalProto) { return false; } JS::Rooted proto(aCx); if (aGivenProto) { proto = aGivenProto; // Unfortunately, while aGivenProto was in the compartment of aCx // coming in, we changed compartments to that of "parent" so may need // to wrap the proto here. if (js::GetContextCompartment(aCx) != JS::GetCompartment(proto)) { if (!JS_WrapObject(aCx, &proto)) { return false; } } } else { proto = canonicalProto; } BindingJSObjectCreator creator(aCx); creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector); if (!aReflector) { return false; } aCache->SetWrapper(aReflector); creator.InitializationSucceeded(); MOZ_ASSERT(aCache->GetWrapperPreserveColor() && aCache->GetWrapperPreserveColor() == aReflector); // If proto != canonicalProto, we have to preserve our wrapper; // otherwise we won't be able to properly recreate it later, since // we won't know what proto to use. Note that we don't check // aGivenProto here, since it's entirely possible (and even // somewhat common) to have a non-null aGivenProto which is the // same as canonicalProto. if (proto != canonicalProto) { PreserveWrapper(aObject); } return true; } void CreateInterfaceObjects(JSContext* aCx, JS::Handle aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, DefineInterfaceProperty aDefineOnGlobal) { JS::Heap* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::JSWindowActorParent); JS::Heap* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::JSWindowActorParent); JS::Handle parentProto(JS::GetRealmObjectPrototypeHandle(aCx)); if (!parentProto) { return; } JS::Handle constructorProto(JS::GetRealmFunctionPrototypeHandle(aCx)); if (!constructorProto) { return; } dom::CreateInterfaceObjects(aCx, aGlobal, parentProto, &sPrototypeClass, protoCache, constructorProto, &sInterfaceObjectInfo, 0, true, Span{}, interfaceCache, sNativeProperties.Upcast(), nullptr, "JSWindowActorParent", ShouldExpose(aCx, aGlobal, aDefineOnGlobal), nullptr, false, nullptr); } static JS::Handle GetProtoObjectHandle(JSContext* aCx) { /* Get the interface prototype object for this class. This will create the object as needed. */ return GetPerInterfaceObjectHandle(aCx, prototypes::id::JSWindowActorParent, &CreateInterfaceObjects, DefineInterfaceProperty::CheckExposure); } JS::Handle GetConstructorObjectHandle(JSContext* aCx) { /* Get the interface object for this class. This will create the object as needed. */ return GetPerInterfaceObjectHandle(aCx, constructors::id::JSWindowActorParent, &CreateInterfaceObjects, DefineInterfaceProperty::CheckExposure); } } // namespace JSWindowActorParent_Binding } // namespace mozilla::dom