Copy as Markdown

Other Tools

/* THIS FILE IS AUTOGENERATED FROM TestInterfaceJSMaplikeSetlikeIterable.webidl BY Codegen.py - DO NOT EDIT */
#include <type_traits>
#include "AtomList.h"
#include "MainThreadUtils.h"
#include "TestInterfaceJSMaplikeSetlikeIterableBinding.h"
#include "WrapperFactory.h"
#include "XrayWrapper.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/Symbol.h"
#include "js/experimental/JitInfo.h"
#include "mozilla/Atomics.h"
#include "mozilla/OwningNonNull.h"
#include "mozilla/ProfilerLabels.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/dom/BindingCallContext.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DOMJSClass.h"
#include "mozilla/dom/DOMJSProxyHandler.h"
#include "mozilla/dom/IterableIterator.h"
#include "mozilla/dom/NonRefcountedDOMObject.h"
#include "mozilla/dom/Nullable.h"
#include "mozilla/dom/PrimitiveConversions.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ProxyHandlerUtils.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/SimpleGlobalObject.h"
#include "mozilla/dom/TestInterfaceAsyncIterableDouble.h"
#include "mozilla/dom/TestInterfaceAsyncIterableDoubleUnion.h"
#include "mozilla/dom/TestInterfaceAsyncIterableSingle.h"
#include "mozilla/dom/TestInterfaceAsyncIterableSingleWithArgs.h"
#include "mozilla/dom/TestInterfaceIterableDouble.h"
#include "mozilla/dom/TestInterfaceIterableDoubleUnion.h"
#include "mozilla/dom/TestInterfaceIterableSingle.h"
#include "mozilla/dom/TestInterfaceMaplike.h"
#include "mozilla/dom/TestInterfaceMaplikeJSObject.h"
#include "mozilla/dom/TestInterfaceMaplikeObject.h"
#include "mozilla/dom/TestInterfaceSetlike.h"
#include "mozilla/dom/TestInterfaceSetlikeNode.h"
#include "mozilla/dom/ToJSValue.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/dom/XrayExpandoClass.h"
#include "nsIContent.h"
namespace mozilla::dom {
namespace binding_detail {}; // Just to make sure it's known as a namespace
using namespace mozilla::dom::binding_detail;
TestInterfaceAsyncIterableSingleOptions::TestInterfaceAsyncIterableSingleOptions()
{
// Safe to pass a null context if we pass a null value
Init(nullptr, JS::NullHandleValue);
}
bool
TestInterfaceAsyncIterableSingleOptions::InitIds(JSContext* cx, TestInterfaceAsyncIterableSingleOptionsAtoms* atomsCache)
{
MOZ_ASSERT(reinterpret_cast<jsid*>(atomsCache)->isVoid());
// Initialize these in reverse order so that any failure leaves the first one
// uninitialized.
if (!atomsCache->failToInit_id.init(cx, "failToInit")) {
return false;
}
return true;
}
bool
TestInterfaceAsyncIterableSingleOptions::Init(BindingCallContext& cx, JS::Handle<JS::Value> 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());
TestInterfaceAsyncIterableSingleOptionsAtoms* atomsCache = nullptr;
if (cx) {
atomsCache = GetAtomCache<TestInterfaceAsyncIterableSingleOptionsAtoms>(cx);
if (reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) {
return false;
}
}
if (!IsConvertibleToDictionary(val)) {
return cx.ThrowErrorMessage<MSG_CONVERSION_ERROR>(sourceDescription, "dictionary");
}
bool isNull = val.isNullOrUndefined();
// We only need these if !isNull, in which case we have |cx|.
Maybe<JS::Rooted<JSObject *> > object;
Maybe<JS::Rooted<JS::Value> > temp;
if (!isNull) {
MOZ_ASSERT(cx);
object.emplace(cx, &val.toObject());
temp.emplace(cx);
}
if (!isNull) {
if (!JS_GetPropertyById(cx, *object, atomsCache->failToInit_id, temp.ptr())) {
return false;
}
}
if (!isNull && !temp->isUndefined()) {
if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), "'failToInit' member of TestInterfaceAsyncIterableSingleOptions", &mFailToInit)) {
return false;
}
} else {
mFailToInit = false;
}
mIsAnyMemberPresent = true;
return true;
}
bool
TestInterfaceAsyncIterableSingleOptions::Init(JSContext* cx_, JS::Handle<JS::Value> 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
TestInterfaceAsyncIterableSingleOptions::TraceDictionary(JSTracer* trc)
{
}
TestInterfaceAsyncIterableSingleOptions&
TestInterfaceAsyncIterableSingleOptions::operator=(const TestInterfaceAsyncIterableSingleOptions& aOther)
{
DictionaryBase::operator=(aOther);
mFailToInit = aOther.mFailToInit;
return *this;
}
bool
TestInterfaceAsyncIterableSingleOptions::operator==(const TestInterfaceAsyncIterableSingleOptions& aOther) const
{
if (mFailToInit != aOther.mFailToInit) {
return false;
}
return true;
}
TestInterfaceAsyncIteratorOptions::TestInterfaceAsyncIteratorOptions()
{
// Safe to pass a null context if we pass a null value
Init(nullptr, JS::NullHandleValue);
}
bool
TestInterfaceAsyncIteratorOptions::InitIds(JSContext* cx, TestInterfaceAsyncIteratorOptionsAtoms* atomsCache)
{
MOZ_ASSERT(reinterpret_cast<jsid*>(atomsCache)->isVoid());
// Initialize these in reverse order so that any failure leaves the first one
// uninitialized.
if (!atomsCache->throwFromReturn_id.init(cx, "throwFromReturn") ||
!atomsCache->throwFromNext_id.init(cx, "throwFromNext") ||
!atomsCache->multiplier_id.init(cx, "multiplier") ||
!atomsCache->failNextAfter_id.init(cx, "failNextAfter") ||
!atomsCache->blockingPromises_id.init(cx, "blockingPromises")) {
return false;
}
return true;
}
bool
TestInterfaceAsyncIteratorOptions::Init(BindingCallContext& cx, JS::Handle<JS::Value> 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());
TestInterfaceAsyncIteratorOptionsAtoms* atomsCache = nullptr;
if (cx) {
atomsCache = GetAtomCache<TestInterfaceAsyncIteratorOptionsAtoms>(cx);
if (reinterpret_cast<jsid*>(atomsCache)->isVoid() &&
!InitIds(cx, atomsCache)) {
return false;
}
}
if (!IsConvertibleToDictionary(val)) {
return cx.ThrowErrorMessage<MSG_CONVERSION_ERROR>(sourceDescription, "dictionary");
}
bool isNull = val.isNullOrUndefined();
// We only need these if !isNull, in which case we have |cx|.
Maybe<JS::Rooted<JSObject *> > object;
Maybe<JS::Rooted<JS::Value> > temp;
if (!isNull) {
MOZ_ASSERT(cx);
object.emplace(cx, &val.toObject());
temp.emplace(cx);
}
if (!isNull) {
if (!JS_GetPropertyById(cx, *object, atomsCache->blockingPromises_id, temp.ptr())) {
return false;
}
}
if (!isNull && !temp->isUndefined()) {
if (temp.ref().isObject()) {
JS::ForOfIterator iter(cx);
if (!iter.init(temp.ref(), JS::ForOfIterator::AllowNonIterable)) {
return false;
}
if (!iter.valueIsIterable()) {
cx.ThrowErrorMessage<MSG_CONVERSION_ERROR>("'blockingPromises' member of TestInterfaceAsyncIteratorOptions", "sequence");
return false;
}
Sequence<OwningNonNull<Promise>> &arr = mBlockingPromises;
JS::Rooted<JS::Value> temp(cx);
while (true) {
bool done;
if (!iter.next(&temp, &done)) {
return false;
}
if (done) {
break;
}
OwningNonNull<Promise>* slotPtr = arr.AppendElement(mozilla::fallible);
if (!slotPtr) {
JS_ReportOutOfMemory(cx);
return false;
}
OwningNonNull<Promise>& slot = *slotPtr;
{ // Scope for our GlobalObject, FastErrorResult, JSAutoRealm,
// etc.
JS::Rooted<JSObject*> globalObj(cx);
globalObj = JS::CurrentGlobalOrNull(cx);
JSAutoRealm ar(cx, globalObj);
GlobalObject promiseGlobal(cx, globalObj);
if (promiseGlobal.Failed()) {
return false;
}
JS::Rooted<JS::Value> valueToResolve(cx, temp);
if (!JS_WrapValue(cx, &valueToResolve)) {
return false;
}
binding_detail::FastErrorResult promiseRv;
nsCOMPtr<nsIGlobalObject> global =
do_QueryInterface(promiseGlobal.GetAsSupports());
if (!global) {
promiseRv.Throw(NS_ERROR_UNEXPECTED);
MOZ_ALWAYS_TRUE(promiseRv.MaybeSetPendingException(cx));
return false;
}
slot = Promise::Resolve(global, cx, valueToResolve,
promiseRv);
if (promiseRv.MaybeSetPendingException(cx)) {
return false;
}
}
}
} else {
cx.ThrowErrorMessage<MSG_CONVERSION_ERROR>("'blockingPromises' member of TestInterfaceAsyncIteratorOptions", "sequence");
return false;
}
} else {
/* mBlockingPromises array is already empty; nothing to do */
}
mIsAnyMemberPresent = true;
if (!isNull) {
if (!JS_GetPropertyById(cx, *object, atomsCache->failNextAfter_id, temp.ptr())) {
return false;
}
}
if (!isNull && !temp->isUndefined()) {
if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), "'failNextAfter' member of TestInterfaceAsyncIteratorOptions", &mFailNextAfter)) {
return false;
}
} else {
mFailNextAfter = 4294967295U;
}
mIsAnyMemberPresent = true;
if (!isNull) {
if (!JS_GetPropertyById(cx, *object, atomsCache->multiplier_id, temp.ptr())) {
return false;
}
}
if (!isNull && !temp->isUndefined()) {
if (!ValueToPrimitive<uint32_t, eDefault>(cx, temp.ref(), "'multiplier' member of TestInterfaceAsyncIteratorOptions", &mMultiplier)) {
return false;
}
} else {
mMultiplier = 1U;
}
mIsAnyMemberPresent = true;
if (!isNull) {
if (!JS_GetPropertyById(cx, *object, atomsCache->throwFromNext_id, temp.ptr())) {
return false;
}
}
if (!isNull && !temp->isUndefined()) {
if (!ValueToPrimitive<bool, eDefault>(cx, temp.ref(), "'throwFromNext' member of TestInterfaceAsyncIteratorOptions", &mThrowFromNext)) {
return false;
}
} else {
mThrowFromNext = false;
}
mIsAnyMemberPresent = true;
if (!isNull) {
if (!JS_GetPropertyById(cx, *object, atomsCache->throwFromReturn_id, temp.ptr())) {
return false;
}
}
if (!isNull && !temp->isUndefined()) {
mThrowFromReturn.Construct();
if (temp.ref().isObject()) {
if (JS::IsCallable(&temp.ref().toObject())) {
{ // scope for tempRoot and tempGlobalRoot if needed
JS::Rooted<JSObject*> tempRoot(cx, &temp.ref().toObject());
JS::Rooted<JSObject*> tempGlobalRoot(cx, JS::CurrentGlobalOrNull(cx));
(mThrowFromReturn.Value()) = new TestThrowingCallback(cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal());
}
} else {
cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("'throwFromReturn' member of TestInterfaceAsyncIteratorOptions");
return false;
}
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("'throwFromReturn' member of TestInterfaceAsyncIteratorOptions");
return false;
}
mIsAnyMemberPresent = true;
}
return true;
}
bool
TestInterfaceAsyncIteratorOptions::Init(JSContext* cx_, JS::Handle<JS::Value> 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
TestInterfaceAsyncIteratorOptions::TraceDictionary(JSTracer* trc)
{
}
MOZ_CAN_RUN_SCRIPT void
TestThrowingCallback::Call(BindingCallContext& cx, JS::Handle<JS::Value> aThisVal, ErrorResult& aRv)
{
JS::Rooted<JS::Value> rval(cx);
JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));
if (!JS::Call(cx, aThisVal, callable,
JS::HandleValueArray::empty(), &rval)) {
aRv.NoteJSContextException(cx);
return;
}
}
namespace TestInterfaceAsyncIterableDoubleAsyncIterator_Binding {
static bool
Wrap(JSContext* aCx, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>* aObject, JS::MutableHandle<JSObject*> aReflector);
} // namespace TestInterfaceAsyncIterableDoubleAsyncIterator_Binding
namespace TestInterfaceAsyncIterableDouble_Binding {
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDouble", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableDouble*>(void_self);
typedef mozilla::dom::binding_detail::WrappableAsyncIterableIterator<mozilla::dom::TestInterfaceAsyncIterableDouble, false, &TestInterfaceAsyncIterableDoubleAsyncIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Values));
{
ErrorResult initError;
self->InitAsyncIteratorData(result->Data(), itrType::IteratorType::Values, initError);
if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for TestInterfaceAsyncIterableDouble failed")) {
return false;
}
}
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceAsyncIterableDouble },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDouble>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
entries(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDouble", "entries", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableDouble*>(void_self);
typedef mozilla::dom::binding_detail::WrappableAsyncIterableIterator<mozilla::dom::TestInterfaceAsyncIterableDouble, false, &TestInterfaceAsyncIterableDoubleAsyncIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Entries));
{
ErrorResult initError;
self->InitAsyncIteratorData(result->Data(), itrType::IteratorType::Entries, initError);
if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for TestInterfaceAsyncIterableDouble failed")) {
return false;
}
}
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo entries_methodinfo = {
{
{ (JSJitGetterOp)entries },
{ prototypes::id::TestInterfaceAsyncIterableDouble },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDouble>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
entries_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
keys(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDouble", "keys", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableDouble*>(void_self);
typedef mozilla::dom::binding_detail::WrappableAsyncIterableIterator<mozilla::dom::TestInterfaceAsyncIterableDouble, false, &TestInterfaceAsyncIterableDoubleAsyncIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Keys));
{
ErrorResult initError;
self->InitAsyncIteratorData(result->Data(), itrType::IteratorType::Keys, initError);
if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for TestInterfaceAsyncIterableDouble failed")) {
return false;
}
}
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo keys_methodinfo = {
{
{ (JSJitGetterOp)keys },
{ prototypes::id::TestInterfaceAsyncIterableDouble },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDouble>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
keys_methodinfo_argTypes
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceAsyncIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableDouble>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceAsyncIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableDouble>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceAsyncIterableDouble>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceAsyncIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableDouble>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceAsyncIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableDouble>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(3 <= 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[3];
static PropertyInfo sNativeProperties_propertyInfos[3];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
3,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(3 < 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::TestInterfaceAsyncIterableDouble,
constructors::id::TestInterfaceAsyncIterableDouble,
&DefaultXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDouble", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceAsyncIterableDouble");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceAsyncIterableDouble,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceAsyncIterableDouble>(mozilla::dom::TestInterfaceAsyncIterableDouble::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceAsyncIterableDouble constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceAsyncIterableDouble,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDouble>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceAsyncIterableDoublePrototype",
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::TestInterfaceAsyncIterableDouble,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDouble>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceAsyncIterableDouble",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceAsyncIterableDouble, 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<nsISupports, mozilla::dom::TestInterfaceAsyncIterableDouble>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceAsyncIterableDouble>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceAsyncIterableDouble>::Get(),
nullptr,
_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::TestInterfaceAsyncIterableDouble* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceAsyncIterableDouble>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceAsyncIterableDouble*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceAsyncIterableDouble> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceAsyncIterableDouble);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceAsyncIterableDouble);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceAsyncIterableDouble", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> asyncIteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::asyncIterator));
if (!JS_DefinePropertyById(aCx, proto, asyncIteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceAsyncIterableDouble_Binding
namespace TestInterfaceAsyncIterableDoubleAsyncIterator_Binding {
MOZ_CAN_RUN_SCRIPT static bool
next(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDoubleAsyncIterator", "next", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>*>(void_self);
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->Next(cx, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceAsyncIterableDoubleAsyncIterator.next"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
next_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = next(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo next_methodinfo = {
{ (JSJitGetterOp)next_promiseWrapper },
{ prototypes::id::TestInterfaceAsyncIterableDoubleAsyncIterator },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDoubleAsyncIterator>::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. */
};
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>>(self);
}
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("next", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&next_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(1 <= 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[1];
static PropertyInfo sNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 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::TestInterfaceAsyncIterableDoubleAsyncIterator,
constructors::id::_ID_Count,
&DefaultXrayExpandoObjectClass
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceAsyncIterableDouble AsyncIteratorPrototype",
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::TestInterfaceAsyncIterableDoubleAsyncIterator,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDoubleAsyncIterator>::Depth,
&sNativePropertyHooks,
JS::GetRealmAsyncIteratorPrototype
};
inline static JS::Handle<JSObject*> 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 js::ClassExtension sClassExtension = {
nullptr /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceAsyncIterableDouble AsyncIterator",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceAsyncIterableDoubleAsyncIterator, 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<nsISupports, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>>::Get(),
nullptr,
nullptr
};
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.");
static bool
Wrap(JSContext* aCx, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>* aObject, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>*>);
MOZ_ASSERT(ToSupportsIsCorrect(aObject));
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
if (!proto) {
return false;
}
BindingJSObjectCreator<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDouble, false>> creator(aCx);
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
creator.InitializationSucceeded();
return true;
}
static void
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceAsyncIterableDoubleAsyncIterator);
JS::Heap<JSObject*>* interfaceCache = nullptr;
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmAsyncIteratorPrototype(aCx));
if (!parentProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
nullptr, nullptr, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceAsyncIterableDouble AsyncIterator", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
inline static JS::Handle<JSObject*> GetProtoObjectHandle(JSContext* aCx)
{
/* Get the interface prototype object for this class. This will create the
object as needed. */
return GetPerInterfaceObjectHandle(aCx, prototypes::id::TestInterfaceAsyncIterableDoubleAsyncIterator,
&CreateInterfaceObjects,
/* aDefineOnGlobal = */ true);
}
} // namespace TestInterfaceAsyncIterableDoubleAsyncIterator_Binding
namespace TestInterfaceAsyncIterableDoubleUnionAsyncIterator_Binding {
static bool
Wrap(JSContext* aCx, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>* aObject, JS::MutableHandle<JSObject*> aReflector);
} // namespace TestInterfaceAsyncIterableDoubleUnionAsyncIterator_Binding
namespace TestInterfaceAsyncIterableDoubleUnion_Binding {
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDoubleUnion", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion*>(void_self);
typedef mozilla::dom::binding_detail::WrappableAsyncIterableIterator<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false, &TestInterfaceAsyncIterableDoubleUnionAsyncIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Values));
{
ErrorResult initError;
self->InitAsyncIteratorData(result->Data(), itrType::IteratorType::Values, initError);
if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for TestInterfaceAsyncIterableDoubleUnion failed")) {
return false;
}
}
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceAsyncIterableDoubleUnion },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDoubleUnion>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
entries(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDoubleUnion", "entries", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion*>(void_self);
typedef mozilla::dom::binding_detail::WrappableAsyncIterableIterator<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false, &TestInterfaceAsyncIterableDoubleUnionAsyncIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Entries));
{
ErrorResult initError;
self->InitAsyncIteratorData(result->Data(), itrType::IteratorType::Entries, initError);
if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for TestInterfaceAsyncIterableDoubleUnion failed")) {
return false;
}
}
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo entries_methodinfo = {
{
{ (JSJitGetterOp)entries },
{ prototypes::id::TestInterfaceAsyncIterableDoubleUnion },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDoubleUnion>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
entries_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
keys(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDoubleUnion", "keys", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion*>(void_self);
typedef mozilla::dom::binding_detail::WrappableAsyncIterableIterator<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false, &TestInterfaceAsyncIterableDoubleUnionAsyncIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Keys));
{
ErrorResult initError;
self->InitAsyncIteratorData(result->Data(), itrType::IteratorType::Keys, initError);
if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for TestInterfaceAsyncIterableDoubleUnion failed")) {
return false;
}
}
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo keys_methodinfo = {
{
{ (JSJitGetterOp)keys },
{ prototypes::id::TestInterfaceAsyncIterableDoubleUnion },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDoubleUnion>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
keys_methodinfo_argTypes
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceAsyncIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceAsyncIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceAsyncIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceAsyncIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(3 <= 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[3];
static PropertyInfo sNativeProperties_propertyInfos[3];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
3,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(3 < 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::TestInterfaceAsyncIterableDoubleUnion,
constructors::id::TestInterfaceAsyncIterableDoubleUnion,
&DefaultXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDoubleUnion", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceAsyncIterableDoubleUnion");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceAsyncIterableDoubleUnion,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>(mozilla::dom::TestInterfaceAsyncIterableDoubleUnion::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceAsyncIterableDoubleUnion constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceAsyncIterableDoubleUnion,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDoubleUnion>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceAsyncIterableDoubleUnionPrototype",
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::TestInterfaceAsyncIterableDoubleUnion,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDoubleUnion>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceAsyncIterableDoubleUnion",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceAsyncIterableDoubleUnion, 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<nsISupports, mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>::Get(),
nullptr,
_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::TestInterfaceAsyncIterableDoubleUnion* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceAsyncIterableDoubleUnion>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceAsyncIterableDoubleUnion*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceAsyncIterableDoubleUnion);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceAsyncIterableDoubleUnion);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceAsyncIterableDoubleUnion", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> asyncIteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::asyncIterator));
if (!JS_DefinePropertyById(aCx, proto, asyncIteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceAsyncIterableDoubleUnion_Binding
namespace TestInterfaceAsyncIterableDoubleUnionAsyncIterator_Binding {
MOZ_CAN_RUN_SCRIPT static bool
next(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableDoubleUnionAsyncIterator", "next", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>*>(void_self);
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->Next(cx, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceAsyncIterableDoubleUnionAsyncIterator.next"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
next_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = next(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo next_methodinfo = {
{ (JSJitGetterOp)next_promiseWrapper },
{ prototypes::id::TestInterfaceAsyncIterableDoubleUnionAsyncIterator },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDoubleUnionAsyncIterator>::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. */
};
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>>(self);
}
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("next", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&next_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(1 <= 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[1];
static PropertyInfo sNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 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::TestInterfaceAsyncIterableDoubleUnionAsyncIterator,
constructors::id::_ID_Count,
&DefaultXrayExpandoObjectClass
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceAsyncIterableDoubleUnion AsyncIteratorPrototype",
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::TestInterfaceAsyncIterableDoubleUnionAsyncIterator,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableDoubleUnionAsyncIterator>::Depth,
&sNativePropertyHooks,
JS::GetRealmAsyncIteratorPrototype
};
inline static JS::Handle<JSObject*> 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 js::ClassExtension sClassExtension = {
nullptr /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceAsyncIterableDoubleUnion AsyncIterator",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceAsyncIterableDoubleUnionAsyncIterator, 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<nsISupports, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>>::Get(),
nullptr,
nullptr
};
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.");
static bool
Wrap(JSContext* aCx, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>* aObject, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>*>);
MOZ_ASSERT(ToSupportsIsCorrect(aObject));
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
if (!proto) {
return false;
}
BindingJSObjectCreator<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableDoubleUnion, false>> creator(aCx);
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
creator.InitializationSucceeded();
return true;
}
static void
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceAsyncIterableDoubleUnionAsyncIterator);
JS::Heap<JSObject*>* interfaceCache = nullptr;
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmAsyncIteratorPrototype(aCx));
if (!parentProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
nullptr, nullptr, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceAsyncIterableDoubleUnion AsyncIterator", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
inline static JS::Handle<JSObject*> GetProtoObjectHandle(JSContext* aCx)
{
/* Get the interface prototype object for this class. This will create the
object as needed. */
return GetPerInterfaceObjectHandle(aCx, prototypes::id::TestInterfaceAsyncIterableDoubleUnionAsyncIterator,
&CreateInterfaceObjects,
/* aDefineOnGlobal = */ true);
}
} // namespace TestInterfaceAsyncIterableDoubleUnionAsyncIterator_Binding
namespace TestInterfaceAsyncIterableSingleAsyncIterator_Binding {
static bool
Wrap(JSContext* aCx, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>* aObject, JS::MutableHandle<JSObject*> aReflector);
} // namespace TestInterfaceAsyncIterableSingleAsyncIterator_Binding
namespace TestInterfaceAsyncIterableSingle_Binding {
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableSingle", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableSingle*>(void_self);
typedef mozilla::dom::binding_detail::WrappableAsyncIterableIterator<mozilla::dom::TestInterfaceAsyncIterableSingle, false, &TestInterfaceAsyncIterableSingleAsyncIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Values));
{
ErrorResult initError;
self->InitAsyncIteratorData(result->Data(), itrType::IteratorType::Values, initError);
if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for TestInterfaceAsyncIterableSingle failed")) {
return false;
}
}
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceAsyncIterableSingle },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingle>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceAsyncIterableSingle* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableSingle>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceAsyncIterableSingle* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableSingle>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceAsyncIterableSingle>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceAsyncIterableSingle* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableSingle>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceAsyncIterableSingle* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableSingle>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(1 <= 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[1];
static PropertyInfo sNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 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::TestInterfaceAsyncIterableSingle,
constructors::id::TestInterfaceAsyncIterableSingle,
&DefaultXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx_, unsigned argc, JS::Value* vp)
{
BindingCallContext cx(cx_, "TestInterfaceAsyncIterableSingle constructor");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableSingle", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceAsyncIterableSingle");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceAsyncIterableSingle,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
binding_detail::FastTestInterfaceAsyncIterableSingleOptions arg0;
if (!arg0.Init(cx, (args.hasDefined(0)) ? args[0] : JS::NullHandleValue, "Argument 1", false)) {
return false;
}
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceAsyncIterableSingle>(mozilla::dom::TestInterfaceAsyncIterableSingle::Constructor(global, Constify(arg0), rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceAsyncIterableSingle constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceAsyncIterableSingle,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingle>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceAsyncIterableSinglePrototype",
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::TestInterfaceAsyncIterableSingle,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingle>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceAsyncIterableSingle",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceAsyncIterableSingle, 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<nsISupports, mozilla::dom::TestInterfaceAsyncIterableSingle>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceAsyncIterableSingle>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceAsyncIterableSingle>::Get(),
nullptr,
_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::TestInterfaceAsyncIterableSingle* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceAsyncIterableSingle>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceAsyncIterableSingle*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceAsyncIterableSingle> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceAsyncIterableSingle);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceAsyncIterableSingle);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceAsyncIterableSingle", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "values", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> asyncIteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::asyncIterator));
if (!JS_DefinePropertyById(aCx, proto, asyncIteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceAsyncIterableSingle_Binding
namespace TestInterfaceAsyncIterableSingleAsyncIterator_Binding {
MOZ_CAN_RUN_SCRIPT static bool
next(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableSingleAsyncIterator", "next", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>*>(void_self);
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->Next(cx, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceAsyncIterableSingleAsyncIterator.next"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
next_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = next(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo next_methodinfo = {
{ (JSJitGetterOp)next_promiseWrapper },
{ prototypes::id::TestInterfaceAsyncIterableSingleAsyncIterator },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleAsyncIterator>::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. */
};
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>>(self);
}
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("next", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&next_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(1 <= 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[1];
static PropertyInfo sNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 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::TestInterfaceAsyncIterableSingleAsyncIterator,
constructors::id::_ID_Count,
&DefaultXrayExpandoObjectClass
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceAsyncIterableSingle AsyncIteratorPrototype",
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::TestInterfaceAsyncIterableSingleAsyncIterator,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleAsyncIterator>::Depth,
&sNativePropertyHooks,
JS::GetRealmAsyncIteratorPrototype
};
inline static JS::Handle<JSObject*> 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 js::ClassExtension sClassExtension = {
nullptr /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceAsyncIterableSingle AsyncIterator",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceAsyncIterableSingleAsyncIterator, 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<nsISupports, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>>::Get(),
nullptr,
nullptr
};
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.");
static bool
Wrap(JSContext* aCx, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>* aObject, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>*>);
MOZ_ASSERT(ToSupportsIsCorrect(aObject));
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
if (!proto) {
return false;
}
BindingJSObjectCreator<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingle, false>> creator(aCx);
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
creator.InitializationSucceeded();
return true;
}
static void
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceAsyncIterableSingleAsyncIterator);
JS::Heap<JSObject*>* interfaceCache = nullptr;
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmAsyncIteratorPrototype(aCx));
if (!parentProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
nullptr, nullptr, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceAsyncIterableSingle AsyncIterator", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
inline static JS::Handle<JSObject*> GetProtoObjectHandle(JSContext* aCx)
{
/* Get the interface prototype object for this class. This will create the
object as needed. */
return GetPerInterfaceObjectHandle(aCx, prototypes::id::TestInterfaceAsyncIterableSingleAsyncIterator,
&CreateInterfaceObjects,
/* aDefineOnGlobal = */ true);
}
} // namespace TestInterfaceAsyncIterableSingleAsyncIterator_Binding
namespace TestInterfaceAsyncIterableSingleWithArgsAsyncIterator_Binding {
static bool
Wrap(JSContext* aCx, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>* aObject, JS::MutableHandle<JSObject*> aReflector);
} // namespace TestInterfaceAsyncIterableSingleWithArgsAsyncIterator_Binding
namespace TestInterfaceAsyncIterableSingleWithArgs_Binding {
MOZ_CAN_RUN_SCRIPT static bool
get_returnCallCount(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableSingleWithArgs", "returnCallCount", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs*>(void_self);
int32_t result(MOZ_KnownLive(self)->ReturnCallCount());
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setInt32(int32_t(result));
return true;
}
static const JSJitInfo returnCallCount_getterinfo = {
{ get_returnCallCount },
{ prototypes::id::TestInterfaceAsyncIterableSingleWithArgs },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleWithArgs>::Depth },
JSJitInfo::Getter,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_INT32, /* returnType. Not relevant for setters. */
true, /* 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_returnLastCalledWith(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableSingleWithArgs", "returnLastCalledWith", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs*>(void_self);
JS::Rooted<JS::Value> result(cx);
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->GetReturnLastCalledWith(cx, &result))>, "Should be returning void here");
MOZ_KnownLive(self)->GetReturnLastCalledWith(cx, &result);
MOZ_ASSERT(!JS_IsExceptionPending(cx));
JS::ExposeValueToActiveJS(result);
args.rval().set(result);
if (!MaybeWrapValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo returnLastCalledWith_getterinfo = {
{ get_returnLastCalledWith },
{ prototypes::id::TestInterfaceAsyncIterableSingleWithArgs },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleWithArgs>::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
values(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceAsyncIterableSingleWithArgs.values");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableSingleWithArgs", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs*>(void_self);
binding_detail::FastTestInterfaceAsyncIteratorOptions arg0;
if (!arg0.Init(cx, (args.hasDefined(0)) ? args.get(0) : JS::NullHandleValue, "Argument 1", false)) {
return false;
}
typedef mozilla::dom::binding_detail::WrappableAsyncIterableIterator<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true, &TestInterfaceAsyncIterableSingleWithArgsAsyncIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Values));
{
ErrorResult initError;
self->InitAsyncIteratorData(result->Data(), itrType::IteratorType::Values, arg0, initError);
if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for TestInterfaceAsyncIterableSingleWithArgs failed")) {
return false;
}
}
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::Object, JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceAsyncIterableSingleWithArgs },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleWithArgs>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("returnCallCount", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &returnCallCount_getterinfo, nullptr, nullptr),
JSPropertySpec::nativeAccessors("returnLastCalledWith", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &returnLastCalledWith_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(2 <= 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[3];
static PropertyInfo sNativeProperties_propertyInfos[3];
static const NativePropertiesN<2> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
true, 1 /* sAttributes */,
false, 0,
false, 0,
false, 0,
-1,
3,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] },
{ sAttributes, &sNativeProperties_propertyInfos[1] }
}
};
static_assert(3 < 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::TestInterfaceAsyncIterableSingleWithArgs,
constructors::id::TestInterfaceAsyncIterableSingleWithArgs,
&DefaultXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableSingleWithArgs", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceAsyncIterableSingleWithArgs");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceAsyncIterableSingleWithArgs,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>(mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceAsyncIterableSingleWithArgs constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceAsyncIterableSingleWithArgs,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleWithArgs>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceAsyncIterableSingleWithArgsPrototype",
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::TestInterfaceAsyncIterableSingleWithArgs,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleWithArgs>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceAsyncIterableSingleWithArgs",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceAsyncIterableSingleWithArgs, 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<nsISupports, mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>::Get(),
nullptr,
_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::TestInterfaceAsyncIterableSingleWithArgs* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceAsyncIterableSingleWithArgs);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceAsyncIterableSingleWithArgs);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceAsyncIterableSingleWithArgs", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "values", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> asyncIteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::asyncIterator));
if (!JS_DefinePropertyById(aCx, proto, asyncIteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceAsyncIterableSingleWithArgs_Binding
namespace TestInterfaceAsyncIterableSingleWithArgsAsyncIterator_Binding {
MOZ_CAN_RUN_SCRIPT static bool
next(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableSingleWithArgsAsyncIterator", "next", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>*>(void_self);
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->Next(cx, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceAsyncIterableSingleWithArgsAsyncIterator.next"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
next_promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = next(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo next_methodinfo = {
{ (JSJitGetterOp)next_promiseWrapper },
{ prototypes::id::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator>::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
_return_(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceAsyncIterableSingleWithArgsAsyncIterator", "return", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>*>(void_self);
JS::Rooted<JS::Value> arg0(cx);
if (args.hasDefined(0)) {
arg0 = args[0];
} else {
arg0 = JS::UndefinedValue();
}
FastErrorResult rv;
auto result(StrongOrRawPtr<Promise>(MOZ_KnownLive(self)->Return(cx, arg0, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceAsyncIterableSingleWithArgsAsyncIterator.return"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (!ToJSValue(cx, result, args.rval())) {
return false;
}
return true;
}
MOZ_CAN_RUN_SCRIPT static bool
_return__promiseWrapper(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
bool ok = _return_(cx, obj, void_self, args);
if (ok) {
return true;
}
return ConvertExceptionToPromise(cx, args.rval());
}
static const JSJitInfo return_methodinfo = {
{ (JSJitGetterOp)_return__promiseWrapper },
{ prototypes::id::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator },
{ PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator>::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. */
};
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>>(self);
}
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("next", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&next_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("return", (GenericMethod<NormalThisPolicy, ConvertExceptionsToPromises>), reinterpret_cast<const JSJitInfo*>(&return_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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)");
static uint16_t sNativeProperties_sortedPropertyIndices[2];
static PropertyInfo sNativeProperties_propertyInfos[2];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
2,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(2 < 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::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator,
constructors::id::_ID_Count,
&DefaultXrayExpandoObjectClass
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceAsyncIterableSingleWithArgs AsyncIteratorPrototype",
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::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator,
PrototypeTraits<prototypes::id::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator>::Depth,
&sNativePropertyHooks,
JS::GetRealmAsyncIteratorPrototype
};
inline static JS::Handle<JSObject*> 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 js::ClassExtension sClassExtension = {
nullptr /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceAsyncIterableSingleWithArgs AsyncIterator",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator, 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<nsISupports, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>>::Get(),
nullptr,
nullptr
};
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.");
static bool
Wrap(JSContext* aCx, mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>* aObject, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>*>);
MOZ_ASSERT(ToSupportsIsCorrect(aObject));
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
if (!proto) {
return false;
}
BindingJSObjectCreator<mozilla::dom::binding_detail::AsyncIterableIteratorNative<mozilla::dom::TestInterfaceAsyncIterableSingleWithArgs, true>> creator(aCx);
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
creator.InitializationSucceeded();
return true;
}
static void
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator);
JS::Heap<JSObject*>* interfaceCache = nullptr;
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmAsyncIteratorPrototype(aCx));
if (!parentProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
nullptr, nullptr, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceAsyncIterableSingleWithArgs AsyncIterator", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
inline static JS::Handle<JSObject*> GetProtoObjectHandle(JSContext* aCx)
{
/* Get the interface prototype object for this class. This will create the
object as needed. */
return GetPerInterfaceObjectHandle(aCx, prototypes::id::TestInterfaceAsyncIterableSingleWithArgsAsyncIterator,
&CreateInterfaceObjects,
/* aDefineOnGlobal = */ true);
}
} // namespace TestInterfaceAsyncIterableSingleWithArgsAsyncIterator_Binding
namespace TestInterfaceIterableDoubleIterator_Binding {
static bool
Wrap(JSContext* aCx, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>* aObject, JS::MutableHandle<JSObject*> aReflector);
} // namespace TestInterfaceIterableDoubleIterator_Binding
namespace TestInterfaceIterableDouble_Binding {
MOZ_CAN_RUN_SCRIPT static bool
entries(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDouble", "entries", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceIterableDouble*>(void_self);
typedef mozilla::dom::binding_detail::WrappableIterableIterator<mozilla::dom::TestInterfaceIterableDouble, &TestInterfaceIterableDoubleIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Entries));
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo entries_methodinfo = {
{
{ (JSJitGetterOp)entries },
{ prototypes::id::TestInterfaceIterableDouble },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
entries_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
keys(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDouble", "keys", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceIterableDouble*>(void_self);
typedef mozilla::dom::binding_detail::WrappableIterableIterator<mozilla::dom::TestInterfaceIterableDouble, &TestInterfaceIterableDoubleIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Keys));
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo keys_methodinfo = {
{
{ (JSJitGetterOp)keys },
{ prototypes::id::TestInterfaceIterableDouble },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
keys_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDouble", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceIterableDouble*>(void_self);
typedef mozilla::dom::binding_detail::WrappableIterableIterator<mozilla::dom::TestInterfaceIterableDouble, &TestInterfaceIterableDoubleIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Values));
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceIterableDouble },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
forEach(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceIterableDouble.forEach");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDouble", "forEach", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceIterableDouble*>(void_self);
JS::Rooted<JSObject*> arg0(cx);
if (args.get(0).isObject()) {
arg0 = &args.get(0).toObject();
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JS::Value> arg1(cx);
if (args.hasDefined(1)) {
arg1 = args.get(1);
} else {
arg1 = JS::UndefinedValue();
}
if (!JS::IsCallable(arg0)) {
cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("Argument 1");
return false;
}
JS::RootedValueArray<3> callArgs(cx);
callArgs[2].setObject(*obj);
JS::Rooted<JS::Value> ignoredReturnVal(cx);
auto GetKeyAtIndex = &mozilla::dom::TestInterfaceIterableDouble::GetKeyAtIndex;
auto GetValueAtIndex = &mozilla::dom::TestInterfaceIterableDouble::GetValueAtIndex;
for (size_t i = 0; i < self->GetIterableLength(); ++i) {
if (!CallIterableGetter(cx, GetValueAtIndex, self, i,
callArgs[0])) {
return false;
}
if (!CallIterableGetter(cx, GetKeyAtIndex, self, i,
callArgs[1])) {
return false;
}
if (!JS::Call(cx, arg1, arg0, JS::HandleValueArray(callArgs),
&ignoredReturnVal)) {
return false;
}
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo forEach_methodinfo = {
{ (JSJitGetterOp)forEach },
{ prototypes::id::TestInterfaceIterableDouble },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::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. */
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDouble>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDouble>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceIterableDouble>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDouble>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceIterableDouble* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDouble>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("forEach", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(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[4];
static PropertyInfo sNativeProperties_propertyInfos[4];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
0,
4,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(4 < 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::TestInterfaceIterableDouble,
constructors::id::TestInterfaceIterableDouble,
&DefaultXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDouble", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceIterableDouble");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceIterableDouble,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceIterableDouble>(mozilla::dom::TestInterfaceIterableDouble::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceIterableDouble constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceIterableDouble,
PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceIterableDoublePrototype",
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::TestInterfaceIterableDouble,
PrototypeTraits<prototypes::id::TestInterfaceIterableDouble>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceIterableDouble",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceIterableDouble, 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<nsISupports, mozilla::dom::TestInterfaceIterableDouble>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceIterableDouble>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceIterableDouble>::Get(),
nullptr,
_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::TestInterfaceIterableDouble* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceIterableDouble>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceIterableDouble*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceIterableDouble> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableDouble);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceIterableDouble);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceIterableDouble", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> iteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::iterator));
if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceIterableDouble_Binding
namespace TestInterfaceIterableDoubleIterator_Binding {
MOZ_CAN_RUN_SCRIPT static bool
next(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDoubleIterator", "next", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>*>(void_self);
FastErrorResult rv;
JS::Rooted<JSObject*> result(cx);
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->Next(cx, &result, rv))>, "Should be returning void here");
MOZ_KnownLive(self)->Next(cx, &result, rv);
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceIterableDoubleIterator.next"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo next_methodinfo = {
{ (JSJitGetterOp)next },
{ prototypes::id::TestInterfaceIterableDoubleIterator },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleIterator>::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. */
};
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>>(self);
}
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("next", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&next_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(1 <= 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[1];
static PropertyInfo sNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 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::TestInterfaceIterableDoubleIterator,
constructors::id::_ID_Count,
&DefaultXrayExpandoObjectClass
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceIterableDouble IteratorPrototype",
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::TestInterfaceIterableDoubleIterator,
PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleIterator>::Depth,
&sNativePropertyHooks,
JS::GetRealmIteratorPrototype
};
inline static JS::Handle<JSObject*> 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 js::ClassExtension sClassExtension = {
nullptr /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceIterableDouble Iterator",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceIterableDoubleIterator, 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<nsISupports, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>>::Get(),
nullptr,
nullptr
};
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.");
static bool
Wrap(JSContext* aCx, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>* aObject, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>*>);
MOZ_ASSERT(ToSupportsIsCorrect(aObject));
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
if (!proto) {
return false;
}
BindingJSObjectCreator<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDouble>> creator(aCx);
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
creator.InitializationSucceeded();
return true;
}
static void
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableDoubleIterator);
JS::Heap<JSObject*>* interfaceCache = nullptr;
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmIteratorPrototype(aCx));
if (!parentProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
nullptr, nullptr, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceIterableDouble Iterator", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
inline static JS::Handle<JSObject*> GetProtoObjectHandle(JSContext* aCx)
{
/* Get the interface prototype object for this class. This will create the
object as needed. */
return GetPerInterfaceObjectHandle(aCx, prototypes::id::TestInterfaceIterableDoubleIterator,
&CreateInterfaceObjects,
/* aDefineOnGlobal = */ true);
}
} // namespace TestInterfaceIterableDoubleIterator_Binding
namespace TestInterfaceIterableDoubleUnionIterator_Binding {
static bool
Wrap(JSContext* aCx, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>* aObject, JS::MutableHandle<JSObject*> aReflector);
} // namespace TestInterfaceIterableDoubleUnionIterator_Binding
namespace TestInterfaceIterableDoubleUnion_Binding {
MOZ_CAN_RUN_SCRIPT static bool
entries(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDoubleUnion", "entries", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceIterableDoubleUnion*>(void_self);
typedef mozilla::dom::binding_detail::WrappableIterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion, &TestInterfaceIterableDoubleUnionIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Entries));
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo entries_methodinfo = {
{
{ (JSJitGetterOp)entries },
{ prototypes::id::TestInterfaceIterableDoubleUnion },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
entries_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
keys(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDoubleUnion", "keys", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceIterableDoubleUnion*>(void_self);
typedef mozilla::dom::binding_detail::WrappableIterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion, &TestInterfaceIterableDoubleUnionIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Keys));
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo keys_methodinfo = {
{
{ (JSJitGetterOp)keys },
{ prototypes::id::TestInterfaceIterableDoubleUnion },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
keys_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDoubleUnion", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceIterableDoubleUnion*>(void_self);
typedef mozilla::dom::binding_detail::WrappableIterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion, &TestInterfaceIterableDoubleUnionIterator_Binding::Wrap> itrType;
RefPtr<itrType> result(new itrType(self,
itrType::IteratorType::Values));
static_assert(!std::is_pointer_v<decltype(result)>,
"NewObject implies that we need to keep the object alive with a strong reference.");
if (!WrapNewBindingNonWrapperCachedObject(cx, obj, result, args.rval())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceIterableDoubleUnion },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
forEach(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceIterableDoubleUnion.forEach");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDoubleUnion", "forEach", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceIterableDoubleUnion*>(void_self);
JS::Rooted<JSObject*> arg0(cx);
if (args.get(0).isObject()) {
arg0 = &args.get(0).toObject();
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JS::Value> arg1(cx);
if (args.hasDefined(1)) {
arg1 = args.get(1);
} else {
arg1 = JS::UndefinedValue();
}
if (!JS::IsCallable(arg0)) {
cx.ThrowErrorMessage<MSG_NOT_CALLABLE>("Argument 1");
return false;
}
JS::RootedValueArray<3> callArgs(cx);
callArgs[2].setObject(*obj);
JS::Rooted<JS::Value> ignoredReturnVal(cx);
auto GetKeyAtIndex = &mozilla::dom::TestInterfaceIterableDoubleUnion::GetKeyAtIndex;
auto GetValueAtIndex = &mozilla::dom::TestInterfaceIterableDoubleUnion::GetValueAtIndex;
for (size_t i = 0; i < self->GetIterableLength(); ++i) {
if (!CallIterableGetter(cx, GetValueAtIndex, self, i,
callArgs[0])) {
return false;
}
if (!CallIterableGetter(cx, GetKeyAtIndex, self, i,
callArgs[1])) {
return false;
}
if (!JS::Call(cx, arg1, arg0, JS::HandleValueArray(callArgs),
&ignoredReturnVal)) {
return false;
}
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo forEach_methodinfo = {
{ (JSJitGetterOp)forEach },
{ prototypes::id::TestInterfaceIterableDoubleUnion },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::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. */
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDoubleUnion>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDoubleUnion>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceIterableDoubleUnion>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDoubleUnion>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceIterableDoubleUnion* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableDoubleUnion>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("forEach", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(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[4];
static PropertyInfo sNativeProperties_propertyInfos[4];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
0,
4,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(4 < 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::TestInterfaceIterableDoubleUnion,
constructors::id::TestInterfaceIterableDoubleUnion,
&DefaultXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDoubleUnion", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceIterableDoubleUnion");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceIterableDoubleUnion,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceIterableDoubleUnion>(mozilla::dom::TestInterfaceIterableDoubleUnion::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceIterableDoubleUnion constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceIterableDoubleUnion,
PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceIterableDoubleUnionPrototype",
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::TestInterfaceIterableDoubleUnion,
PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnion>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceIterableDoubleUnion",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceIterableDoubleUnion, 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<nsISupports, mozilla::dom::TestInterfaceIterableDoubleUnion>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceIterableDoubleUnion>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceIterableDoubleUnion>::Get(),
nullptr,
_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::TestInterfaceIterableDoubleUnion* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceIterableDoubleUnion>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceIterableDoubleUnion*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceIterableDoubleUnion> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableDoubleUnion);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceIterableDoubleUnion);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceIterableDoubleUnion", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> iteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::iterator));
if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceIterableDoubleUnion_Binding
namespace TestInterfaceIterableDoubleUnionIterator_Binding {
MOZ_CAN_RUN_SCRIPT static bool
next(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableDoubleUnionIterator", "next", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>*>(void_self);
FastErrorResult rv;
JS::Rooted<JSObject*> result(cx);
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->Next(cx, &result, rv))>, "Should be returning void here");
MOZ_KnownLive(self)->Next(cx, &result, rv);
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceIterableDoubleUnionIterator.next"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo next_methodinfo = {
{ (JSJitGetterOp)next },
{ prototypes::id::TestInterfaceIterableDoubleUnionIterator },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnionIterator>::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. */
};
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>>(self);
}
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("next", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&next_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(1 <= 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[1];
static PropertyInfo sNativeProperties_propertyInfos[1];
static const NativePropertiesN<1> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
false, 0,
false, 0,
false, 0,
false, 0,
-1,
1,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] }
}
};
static_assert(1 < 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::TestInterfaceIterableDoubleUnionIterator,
constructors::id::_ID_Count,
&DefaultXrayExpandoObjectClass
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceIterableDoubleUnion IteratorPrototype",
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::TestInterfaceIterableDoubleUnionIterator,
PrototypeTraits<prototypes::id::TestInterfaceIterableDoubleUnionIterator>::Depth,
&sNativePropertyHooks,
JS::GetRealmIteratorPrototype
};
inline static JS::Handle<JSObject*> 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 js::ClassExtension sClassExtension = {
nullptr /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceIterableDoubleUnion Iterator",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceIterableDoubleUnionIterator, 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<nsISupports, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>>::Get(),
nullptr,
nullptr
};
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.");
static bool
Wrap(JSContext* aCx, mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>* aObject, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>*>);
MOZ_ASSERT(ToSupportsIsCorrect(aObject));
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
JS::Handle<JSObject*> proto = GetProtoObjectHandle(aCx);
if (!proto) {
return false;
}
BindingJSObjectCreator<mozilla::dom::IterableIterator<mozilla::dom::TestInterfaceIterableDoubleUnion>> creator(aCx);
creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
if (!aReflector) {
return false;
}
creator.InitializationSucceeded();
return true;
}
static void
CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableDoubleUnionIterator);
JS::Heap<JSObject*>* interfaceCache = nullptr;
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmIteratorPrototype(aCx));
if (!parentProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
nullptr, nullptr, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceIterableDoubleUnion Iterator", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
inline static JS::Handle<JSObject*> GetProtoObjectHandle(JSContext* aCx)
{
/* Get the interface prototype object for this class. This will create the
object as needed. */
return GetPerInterfaceObjectHandle(aCx, prototypes::id::TestInterfaceIterableDoubleUnionIterator,
&CreateInterfaceObjects,
/* aDefineOnGlobal = */ true);
}
} // namespace TestInterfaceIterableDoubleUnionIterator_Binding
namespace TestInterfaceIterableSingle_Binding {
MOZ_CAN_RUN_SCRIPT static bool
get_length(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableSingle", "length", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceIterableSingle*>(void_self);
uint32_t result(MOZ_KnownLive(self)->Length());
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setNumber(result);
return true;
}
static const JSJitInfo length_getterinfo = {
{ get_length },
{ prototypes::id::TestInterfaceIterableSingle },
{ PrototypeTraits<prototypes::id::TestInterfaceIterableSingle>::Depth },
JSJitInfo::Getter,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
true, /* 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 const JSFunctionSpec sMethods_specs[] = {
JS_SYM_FNSPEC(iterator, nullptr, nullptr, 0, 0, "$ArrayValues"),
JS_FNSPEC("keys", nullptr, nullptr, 0, JSPROP_ENUMERATE, "ArrayKeys"),
JS_FNSPEC("values", nullptr, nullptr, 0, JSPROP_ENUMERATE, "$ArrayValues"),
JS_FNSPEC("entries", nullptr, nullptr, 0, JSPROP_ENUMERATE, "ArrayEntries"),
JS_FNSPEC("forEach", nullptr, nullptr, 1, JSPROP_ENUMERATE, "ArrayForEach"),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(5 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("length", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &length_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(1 <= 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[5] }
}
};
static_assert(6 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
static_assert(std::is_base_of_v<nsISupports, mozilla::dom::TestInterfaceIterableSingle>,
"We don't support non-nsISupports native classes for "
"proxy-based bindings yet");
class DOMProxyHandler : public mozilla::dom::DOMProxyHandler
{
public:
explicit constexpr DOMProxyHandler()
{
}
bool
getOwnPropDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool ignoreNamedProps, JS::MutableHandle<Maybe<JS::PropertyDescriptor>> desc) const override;
bool
defineProperty(JSContext* cx_, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& opresult, bool* done) const override;
using mozilla::dom::DOMProxyHandler::defineProperty;
bool
ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy, unsigned flags, JS::MutableHandleVector<jsid> props) const override;
bool
hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) const override;
bool
get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JS::Value> receiver, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
const char*
className(JSContext* cx, JS::Handle<JSObject*> proxy) const override;
bool
finalizeInBackground(const JS::Value& priv) const override;
void
finalize(JS::GCContext* gcx, JSObject* proxy) const override;
static const DOMProxyHandler*
getInstance();
bool
delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::ObjectOpResult& opresult) const override;
bool
getElements(JSContext* cx, JS::Handle<JSObject*> proxy, uint32_t begin, uint32_t end, js::ElementAdder* adder) const override;
size_t
objectMoved(JSObject* obj, JSObject* old) const override;
};
MOZ_ALWAYS_INLINE bool
IsProxy(JSObject* obj)
{
return js::IsProxy(obj) && js::GetProxyHandler(obj) == DOMProxyHandler::getInstance();
}
MOZ_ALWAYS_INLINE mozilla::dom::TestInterfaceIterableSingle*
UnwrapProxy(JSObject* obj)
{
MOZ_ASSERT(js::IsProxy(obj));
if (js::GetProxyHandler(obj) != DOMProxyHandler::getInstance()) {
MOZ_ASSERT(xpc::WrapperFactory::IsXrayWrapper(obj));
obj = js::UncheckedUnwrap(obj);
}
MOZ_ASSERT(IsProxy(obj));
return static_cast<mozilla::dom::TestInterfaceIterableSingle*>(js::GetProxyReservedSlot(obj, DOM_OBJECT_SLOT).toPrivate());
}
const NativeNamedOrIndexedPropertyHooks sNativeNamedOrIndexedPropertyHooks = {
binding_detail::ResolveOwnProperty,
binding_detail::EnumerateOwnProperties,
nullptr
};
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
&sNativeNamedOrIndexedPropertyHooks,
{ sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited },
prototypes::id::TestInterfaceIterableSingle,
constructors::id::TestInterfaceIterableSingle,
&DefaultXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceIterableSingle", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceIterableSingle");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceIterableSingle,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceIterableSingle>(mozilla::dom::TestInterfaceIterableSingle::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceIterableSingle constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceIterableSingle,
PrototypeTraits<prototypes::id::TestInterfaceIterableSingle>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceIterableSinglePrototype",
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::TestInterfaceIterableSingle,
PrototypeTraits<prototypes::id::TestInterfaceIterableSingle>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
bool
DOMProxyHandler::getOwnPropDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool ignoreNamedProps, JS::MutableHandle<Maybe<JS::PropertyDescriptor>> desc) const
{
bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
uint32_t index = GetArrayIndexFromId(id);
if (IsArrayIndex(index)) {
JS::Rooted<JS::Value> value(cx);
mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
bool found = false;
int32_t result(MOZ_KnownLive(self)->IndexedGetter(index, found));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (found) {
value.setInt32(int32_t(result));
desc.set(mozilla::Some(JS::PropertyDescriptor::Data(value, { JS::PropertyAttribute::Configurable, JS::PropertyAttribute::Enumerable })));
return true;
}
}
JS::Rooted<JSObject*> expando(cx);
if (!isXray &&(expando = GetExpandoObject(proxy))) {
if (!JS_GetOwnPropertyDescriptorById(cx, expando, id, desc)) {
return false;
}
if (desc.isSome()) {
return true;
}
}
desc.reset();
return true;
}
bool
DOMProxyHandler::defineProperty(JSContext* cx_, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::Handle<JS::PropertyDescriptor> desc, JS::ObjectOpResult& opresult, bool* done) const
{
if (IsArrayIndex(GetArrayIndexFromId(id))) {
*done = true;
return opresult.failNoIndexedSetter();
}
return mozilla::dom::DOMProxyHandler::defineProperty(cx_, proxy, id, desc, opresult, done);
}
bool
DOMProxyHandler::ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy, unsigned flags, JS::MutableHandleVector<jsid> props) const
{
bool isXray = xpc::WrapperFactory::IsXrayWrapper(proxy);
uint32_t length = UnwrapProxy(proxy)->Length();
MOZ_ASSERT(int32_t(length) >= 0);
for (int32_t i = 0; i < int32_t(length); ++i) {
if (!props.append(JS::PropertyKey::Int(i))) {
return false;
}
}
JS::Rooted<JSObject*> expando(cx);
if (!isXray &&(expando = DOMProxyHandler::GetExpandoObject(proxy)) &&
!js::GetPropertyKeys(cx, expando, flags, props)) {
return false;
}
return true;
}
bool
DOMProxyHandler::hasOwn(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) const
{
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
"Should not have a XrayWrapper here");
uint32_t index = GetArrayIndexFromId(id);
if (IsArrayIndex(index)) {
bool found = false;
mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
int32_t result(MOZ_KnownLive(self)->IndexedGetter(index, found));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
(void)result;
*bp = found;
return true;
}
JS::Rooted<JSObject*> expando(cx, GetExpandoObject(proxy));
if (expando) {
bool b = true;
bool ok = JS_HasPropertyById(cx, expando, id, &b);
*bp = !!b;
if (!ok || *bp) {
return ok;
}
}
*bp = false;
return true;
}
bool
DOMProxyHandler::get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JS::Value> receiver, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const
{
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
"Should not have a XrayWrapper here");
uint32_t index = GetArrayIndexFromId(id);
if (IsArrayIndex(index)) {
mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
bool found = false;
int32_t result(MOZ_KnownLive(self)->IndexedGetter(index, found));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (found) {
vp.setInt32(int32_t(result));
return true;
}
// Even if we don't have this index, we don't forward the
// get on to our expando object.
} else {
bool expandoHasProp = false;
{ // Scope for expando
JS::Rooted<JSObject*> expando(cx, DOMProxyHandler::GetExpandoObject(proxy));
if (expando) {
if (!JS_HasPropertyById(cx, expando, id, &expandoHasProp)) {
return false;
}
if (expandoHasProp) {
// Forward the get to the expando object, but our receiver is whatever our
// receiver is.
if (!JS_ForwardGetPropertyTo(cx, expando, id, receiver, vp)) {
return false;
}
}
}
}
if (expandoHasProp) {
return true;
}
}
bool foundOnPrototype;
if (!GetPropertyOnPrototype(cx, proxy, receiver, id, &foundOnPrototype, vp)) {
return false;
}
if (foundOnPrototype) {
return true;
}
MOZ_ASSERT(vp.isUndefined());
return true;
}
const char*
DOMProxyHandler::className(JSContext* cx, JS::Handle<JSObject*> proxy) const
{
return "TestInterfaceIterableSingle";
}
bool
DOMProxyHandler::finalizeInBackground(const JS::Value& priv) const
{
return false;
}
void
DOMProxyHandler::finalize(JS::GCContext* gcx, JSObject* proxy) const
{
mozilla::dom::TestInterfaceIterableSingle* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableSingle>(proxy);
if (self) {
JS::SetReservedSlot(proxy, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, proxy);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(proxy, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceIterableSingle>(self);
}
}
const DOMProxyHandler*
DOMProxyHandler::getInstance()
{
static const DOMProxyHandler instance;
return &instance;
}
bool
DOMProxyHandler::delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, JS::ObjectOpResult& opresult) const
{
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
"Should not have a XrayWrapper here");
uint32_t index = GetArrayIndexFromId(id);
if (IsArrayIndex(index)) {
bool deleteSucceeded;
bool found = false;
mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
int32_t result(MOZ_KnownLive(self)->IndexedGetter(index, found));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
(void)result;
deleteSucceeded = !found;
return deleteSucceeded ? opresult.succeed() : opresult.failCantDelete();
}
return dom::DOMProxyHandler::delete_(cx, proxy, id, opresult);
}
bool
DOMProxyHandler::getElements(JSContext* cx, JS::Handle<JSObject*> proxy, uint32_t begin, uint32_t end, js::ElementAdder* adder) const
{
JS::Rooted<JS::Value> temp(cx);
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
"Should not have a XrayWrapper here");
mozilla::dom::TestInterfaceIterableSingle* self = UnwrapProxy(proxy);
uint32_t length = self->Length();
// Compute the end of the indices we'll get ourselves
uint32_t ourEnd = std::max(begin, std::min(end, length));
for (uint32_t index = begin; index < ourEnd; ++index) {
bool found = false;
int32_t result(MOZ_KnownLive(self)->IndexedGetter(index, found));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
MOZ_ASSERT(found);
temp.setInt32(int32_t(result));
if (!adder->append(cx, temp)) return false;
continue;
}
if (end > ourEnd) {
JS::Rooted<JSObject*> proto(cx);
if (!js::GetObjectProto(cx, proxy, &proto)) {
return false;
}
return js::GetElementsWithAdder(cx, proto, proxy, ourEnd, end, adder);
}
return true;
}
size_t
DOMProxyHandler::objectMoved(JSObject* obj, JSObject* old) const
{
mozilla::dom::TestInterfaceIterableSingle* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceIterableSingle>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const DOMJSClass sClass = {
PROXY_CLASS_DEF("TestInterfaceIterableSingle",
JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1)),
{ prototypes::id::TestInterfaceIterableSingle, 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<nsISupports, mozilla::dom::TestInterfaceIterableSingle>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceIterableSingle>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceIterableSingle>::Get(),
nullptr,
nullptr
};
bool
Wrap(JSContext* aCx, mozilla::dom::TestInterfaceIterableSingle* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceIterableSingle>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceIterableSingle*>);
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()) {
DOMProxyHandler::getInstance()->finalize(nullptr /* unused */, oldReflector);
MOZ_ASSERT(!aCache->GetWrapperMaybeDead());
}
JS::Rooted<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceIterableSingle> creator(aCx);
creator.CreateProxyObject(aCx, &sClass.mBase, DOMProxyHandler::getInstance(),
proto, /* aLazyProto = */ false,
aObject, JS::UndefinedHandleValue, 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceIterableSingle);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceIterableSingle);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceIterableSingle", aDefineOnGlobal,
nullptr,
false,
nullptr);
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceIterableSingle_Binding
namespace TestInterfaceMaplike_Binding {
namespace MaplikeHelpers {
void
Clear(mozilla::dom::TestInterfaceMaplike* self, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
if (!JS::MapClear(cx, backingObj)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
bool
Delete(mozilla::dom::TestInterfaceMaplike* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
bool retVal;
if (!JS::MapDelete(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
bool
Has(mozilla::dom::TestInterfaceMaplike* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
bool retVal;
if (!JS::MapHas(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
void
Set(mozilla::dom::TestInterfaceMaplike* self, const nsAString& aKey, int32_t aValue, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(2)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
do {
argv[1].setInt32(int32_t(aValue));
break;
} while (false);
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
if (!JS::MapSet(cx, backingObj, argv[0], argv[1])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
int32_t
Get(mozilla::dom::TestInterfaceMaplike* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int32_t(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int32_t(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int32_t(0);
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int32_t(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int32_t(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
JS::Rooted<JS::Value> result(cx);
if (!JS::MapGet(cx, backingObj, argv[0], &result)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return int32_t(0);
}
if (result.isUndefined()) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return int32_t(0);
}
int32_t rvalDecl;
if (!ValueToPrimitive<int32_t, eDefault>(cx, result, "Return value of Get", &rvalDecl)) {
aRv.NoteJSContextException(cx);
return int32_t(0);
}
return rvalDecl;
}
} // namespace MaplikeHelpers
MOZ_CAN_RUN_SCRIPT static bool
setInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "setInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplike.setInternal", 2)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
int32_t arg1;
if (!ValueToPrimitive<int32_t, eDefault>(cx, args[1], "Argument 2", &arg1)) {
return false;
}
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->SetInternal(NonNullHelper(Constify(arg0)), arg1))>, "Should be returning void here");
MOZ_KnownLive(self)->SetInternal(NonNullHelper(Constify(arg0)), arg1);
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setUndefined();
return true;
}
static const JSJitInfo setInternal_methodinfo = {
{ (JSJitGetterOp)setInternal },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::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
clearInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "clearInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->ClearInternal())>, "Should be returning void here");
MOZ_KnownLive(self)->ClearInternal();
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setUndefined();
return true;
}
static const JSJitInfo clearInternal_methodinfo = {
{ (JSJitGetterOp)clearInternal },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
true, /* 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
deleteInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "deleteInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplike.deleteInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
bool result(MOZ_KnownLive(self)->DeleteInternal(NonNullHelper(Constify(arg0))));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo deleteInternal_methodinfo = {
{ (JSJitGetterOp)deleteInternal },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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
hasInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "hasInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplike.hasInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
bool result(MOZ_KnownLive(self)->HasInternal(NonNullHelper(Constify(arg0))));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo hasInternal_methodinfo = {
{ (JSJitGetterOp)hasInternal },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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
getInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "getInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplike.getInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
FastErrorResult rv;
int32_t result(MOZ_KnownLive(self)->GetInternal(NonNullHelper(Constify(arg0)), rv));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceMaplike.getInternal"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setInt32(int32_t(result));
return true;
}
static const JSJitInfo getInternal_methodinfo = {
{ (JSJitGetterOp)getInternal },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_INT32, /* 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_size(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "size", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
uint32_t result = JS::MapSize(cx, backingObj);
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setNumber(result);
return true;
}
static const JSJitInfo size_getterinfo = {
{ get_size },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
JSJitInfo::Getter,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
true, /* 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
entries(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "entries", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::MapEntries(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo entries_methodinfo = {
{
{ (JSJitGetterOp)entries },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
entries_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
keys(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "keys", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::MapKeys(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo keys_methodinfo = {
{
{ (JSJitGetterOp)keys },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
keys_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::MapValues(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
forEach(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceMaplike.forEach");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "forEach", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
JS::Rooted<JSObject*> arg0(cx);
if (args.get(0).isObject()) {
arg0 = &args.get(0).toObject();
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JS::Value> arg1(cx);
if (args.hasDefined(1)) {
arg1 = args.get(1);
} else {
arg1 = JS::UndefinedValue();
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
// Create a wrapper function.
JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
if (!func) {
return false;
}
JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
JS::ObjectValue(*arg0));
js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
JS::ObjectValue(*obj));
if (!JS::MapForEach(cx, backingObj, funcVal, arg1)) {
return false;
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo forEach_methodinfo = {
{ (JSJitGetterOp)forEach },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::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
has(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "has", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
bool result;
if (!JS::MapHas(cx, backingObj, arg0Val, &result)) {
return false;
}
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo has_methodinfo = {
{
{ (JSJitGetterOp)has },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
has_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
clear(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "clear", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
if (!JS::MapClear(cx, backingObj)) {
return false;
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo clear_methodinfo = {
{ (JSJitGetterOp)clear },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::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
_delete_(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "delete", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
bool result;
if (!JS::MapDelete(cx, backingObj, arg0Val, &result)) {
return false;
}
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo delete_methodinfo = {
{ (JSJitGetterOp)_delete_ },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "get", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
JS::Rooted<JS::Value> result(cx);
if (!JS::MapGet(cx, backingObj, arg0Val, &result)) {
return false;
}
JS::ExposeValueToActiveJS(result);
args.rval().set(result);
if (!MaybeWrapValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType get_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo get_methodinfo = {
{
{ (JSJitGetterOp)get },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasDOMSets, /* 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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
get_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
set(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "set", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplike*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
int32_t arg1;
if (!ValueToPrimitive<int32_t, eDefault>(cx, args.get(1), "Argument 2", &arg1)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplike>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
JS::Rooted<JS::Value> arg1Val(cx);
if (!ToJSValue(cx, arg1, &arg1Val)) {
return false;
}
JS::Rooted<JSObject*> result(cx);
if (!JS::MapSet(cx, backingObj, arg0Val, arg1Val)) {
return false;
}
result = obj;
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo set_methodinfo = {
{ (JSJitGetterOp)set },
{ prototypes::id::TestInterfaceMaplike },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplike>::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. */
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplike>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplike>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceMaplike>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplike>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceMaplike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplike>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("setInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&setInternal_methodinfo), 2, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("clearInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&clearInternal_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("deleteInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&deleteInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("hasInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&hasInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("getInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&getInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("forEach", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("has", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("clear", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&clear_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("delete", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&delete_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("get", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&get_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("set", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&set_methodinfo), 2, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(14 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("size", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &size_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(1 <= 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[15];
static PropertyInfo sNativeProperties_propertyInfos[15];
static const NativePropertiesN<2> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
true, 1 /* sAttributes */,
false, 0,
false, 0,
false, 0,
5,
15,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] },
{ sAttributes, &sNativeProperties_propertyInfos[14] }
}
};
static_assert(5 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
"We have an iterator alias index that is oversized");
static_assert(15 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
// This may allocate too many slots, because we only really need
// slots for our non-interface-typed members that we cache. But
// allocating slots only for those would make the slot index
// computations much more complicated, so let's do this the simple
// way for now.
DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
nullptr,
{ sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited },
prototypes::id::TestInterfaceMaplike,
constructors::id::TestInterfaceMaplike,
&sXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplike", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceMaplike");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceMaplike,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceMaplike>(mozilla::dom::TestInterfaceMaplike::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceMaplike constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceMaplike,
PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceMaplikePrototype",
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::TestInterfaceMaplike,
PrototypeTraits<prototypes::id::TestInterfaceMaplike>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceMaplike",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceMaplike, 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<nsISupports, mozilla::dom::TestInterfaceMaplike>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceMaplike>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceMaplike>::Get(),
nullptr,
_getWrapperCache
};
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
"Must have the right minimal number of reserved slots.");
static_assert(2 >= 2,
"Must have enough reserved slots.");
bool
Wrap(JSContext* aCx, mozilla::dom::TestInterfaceMaplike* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceMaplike>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceMaplike*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceMaplike> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceMaplike);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceMaplike);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceMaplike", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> iteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::iterator));
if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceMaplike_Binding
namespace TestInterfaceMaplikeJSObject_Binding {
namespace MaplikeHelpers {
void
Clear(mozilla::dom::TestInterfaceMaplikeJSObject* self, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
if (!JS::MapClear(cx, backingObj)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
bool
Delete(mozilla::dom::TestInterfaceMaplikeJSObject* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
bool retVal;
if (!JS::MapDelete(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
bool
Has(mozilla::dom::TestInterfaceMaplikeJSObject* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
bool retVal;
if (!JS::MapHas(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
void
Set(mozilla::dom::TestInterfaceMaplikeJSObject* self, const nsAString& aKey, JS::Handle<JSObject*> aValue, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(2)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
do {
JS::ExposeObjectToActiveJS(aValue);
argv[1].setObject(*aValue);
if (!MaybeWrapObjectValue(cx, argv[1])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
if (!JS::MapSet(cx, backingObj, argv[0], argv[1])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
void
Get(mozilla::dom::TestInterfaceMaplikeJSObject* self, JSContext* cx, const nsAString& aKey, JS::MutableHandle<JSObject*> aRetVal, ErrorResult& aRv)
{
MOZ_ASSERT(self);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JS::Rooted<JS::Value> result(cx);
{
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
if (!JS::MapGet(cx, backingObj, argv[0], &result)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (result.isUndefined()) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return;
}
}
if (!JS_WrapValue(cx, &result)) {
aRv.NoteJSContextException(cx);
return;
}
JS::Rooted<JSObject*> rvalDecl(cx);
rvalDecl = &result.toObject();
aRetVal.set(rvalDecl);
}
} // namespace MaplikeHelpers
MOZ_CAN_RUN_SCRIPT static bool
setInternal(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceMaplikeJSObject.setInternal");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "setInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplikeJSObject.setInternal", 2)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> arg1(cx);
if (args[1].isObject()) {
arg1 = &args[1].toObject();
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 2");
return false;
}
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->SetInternal(cx, NonNullHelper(Constify(arg0)), arg1))>, "Should be returning void here");
MOZ_KnownLive(self)->SetInternal(cx, NonNullHelper(Constify(arg0)), arg1);
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setUndefined();
return true;
}
static const JSJitInfo setInternal_methodinfo = {
{ (JSJitGetterOp)setInternal },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::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
clearInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "clearInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->ClearInternal())>, "Should be returning void here");
MOZ_KnownLive(self)->ClearInternal();
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setUndefined();
return true;
}
static const JSJitInfo clearInternal_methodinfo = {
{ (JSJitGetterOp)clearInternal },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
true, /* 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
deleteInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "deleteInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplikeJSObject.deleteInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
bool result(MOZ_KnownLive(self)->DeleteInternal(NonNullHelper(Constify(arg0))));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo deleteInternal_methodinfo = {
{ (JSJitGetterOp)deleteInternal },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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
hasInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "hasInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplikeJSObject.hasInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
bool result(MOZ_KnownLive(self)->HasInternal(NonNullHelper(Constify(arg0))));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo hasInternal_methodinfo = {
{ (JSJitGetterOp)hasInternal },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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
getInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "getInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplikeJSObject.getInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
FastErrorResult rv;
JS::Rooted<JSObject*> result(cx);
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->GetInternal(cx, NonNullHelper(Constify(arg0)), &result, rv))>, "Should be returning void here");
MOZ_KnownLive(self)->GetInternal(cx, NonNullHelper(Constify(arg0)), &result, rv);
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceMaplikeJSObject.getInternal"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
if (result) {
JS::ExposeObjectToActiveJS(result);
}
args.rval().setObjectOrNull(result);
if (!MaybeWrapObjectOrNullValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo getInternal_methodinfo = {
{ (JSJitGetterOp)getInternal },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::Depth },
JSJitInfo::Method,
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_size(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "size", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
uint32_t result = JS::MapSize(cx, backingObj);
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setNumber(result);
return true;
}
static const JSJitInfo size_getterinfo = {
{ get_size },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::Depth },
JSJitInfo::Getter,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
true, /* 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
entries(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "entries", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::MapEntries(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo entries_methodinfo = {
{
{ (JSJitGetterOp)entries },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
entries_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
keys(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "keys", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::MapKeys(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo keys_methodinfo = {
{
{ (JSJitGetterOp)keys },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
keys_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::MapValues(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
forEach(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceMaplikeJSObject.forEach");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "forEach", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
JS::Rooted<JSObject*> arg0(cx);
if (args.get(0).isObject()) {
arg0 = &args.get(0).toObject();
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JS::Value> arg1(cx);
if (args.hasDefined(1)) {
arg1 = args.get(1);
} else {
arg1 = JS::UndefinedValue();
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
// Create a wrapper function.
JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
if (!func) {
return false;
}
JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
JS::ObjectValue(*arg0));
js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
JS::ObjectValue(*obj));
if (!JS::MapForEach(cx, backingObj, funcVal, arg1)) {
return false;
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo forEach_methodinfo = {
{ (JSJitGetterOp)forEach },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::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
has(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "has", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
bool result;
if (!JS::MapHas(cx, backingObj, arg0Val, &result)) {
return false;
}
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo has_methodinfo = {
{
{ (JSJitGetterOp)has },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
has_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
get(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "get", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeJSObject*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
JS::Rooted<JS::Value> result(cx);
if (!JS::MapGet(cx, backingObj, arg0Val, &result)) {
return false;
}
JS::ExposeValueToActiveJS(result);
args.rval().set(result);
if (!MaybeWrapValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType get_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo get_methodinfo = {
{
{ (JSJitGetterOp)get },
{ prototypes::id::TestInterfaceMaplikeJSObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasDOMSets, /* 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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
get_methodinfo_argTypes
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceMaplikeJSObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeJSObject>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceMaplikeJSObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeJSObject>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceMaplikeJSObject>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceMaplikeJSObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeJSObject>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceMaplikeJSObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeJSObject>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("setInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&setInternal_methodinfo), 2, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("clearInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&clearInternal_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("deleteInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&deleteInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("hasInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&hasInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("getInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&getInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("forEach", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("has", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("get", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&get_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(11 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("size", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &size_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(1 <= 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[12];
static PropertyInfo sNativeProperties_propertyInfos[12];
static const NativePropertiesN<2> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
true, 1 /* sAttributes */,
false, 0,
false, 0,
false, 0,
5,
12,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] },
{ sAttributes, &sNativeProperties_propertyInfos[11] }
}
};
static_assert(5 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
"We have an iterator alias index that is oversized");
static_assert(12 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
// This may allocate too many slots, because we only really need
// slots for our non-interface-typed members that we cache. But
// allocating slots only for those would make the slot index
// computations much more complicated, so let's do this the simple
// way for now.
DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
nullptr,
{ sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited },
prototypes::id::TestInterfaceMaplikeJSObject,
constructors::id::TestInterfaceMaplikeJSObject,
&sXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeJSObject", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceMaplikeJSObject");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceMaplikeJSObject,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceMaplikeJSObject>(mozilla::dom::TestInterfaceMaplikeJSObject::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceMaplikeJSObject constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceMaplikeJSObject,
PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceMaplikeJSObjectPrototype",
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::TestInterfaceMaplikeJSObject,
PrototypeTraits<prototypes::id::TestInterfaceMaplikeJSObject>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceMaplikeJSObject",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceMaplikeJSObject, 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<nsISupports, mozilla::dom::TestInterfaceMaplikeJSObject>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceMaplikeJSObject>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceMaplikeJSObject>::Get(),
nullptr,
_getWrapperCache
};
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
"Must have the right minimal number of reserved slots.");
static_assert(2 >= 2,
"Must have enough reserved slots.");
bool
Wrap(JSContext* aCx, mozilla::dom::TestInterfaceMaplikeJSObject* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceMaplikeJSObject>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceMaplikeJSObject*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceMaplikeJSObject> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceMaplikeJSObject);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceMaplikeJSObject);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceMaplikeJSObject", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> iteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::iterator));
if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceMaplikeJSObject_Binding
namespace TestInterfaceMaplikeObject_Binding {
namespace MaplikeHelpers {
void
Clear(mozilla::dom::TestInterfaceMaplikeObject* self, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
if (!JS::MapClear(cx, backingObj)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
bool
Delete(mozilla::dom::TestInterfaceMaplikeObject* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
bool retVal;
if (!JS::MapDelete(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
bool
Has(mozilla::dom::TestInterfaceMaplikeObject* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
bool retVal;
if (!JS::MapHas(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
void
Set(mozilla::dom::TestInterfaceMaplikeObject* self, const nsAString& aKey, TestInterfaceMaplike& aValue, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(2)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
do {
if (!GetOrCreateDOMReflector(cx, aValue, argv[1])) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
if (!JS::MapSet(cx, backingObj, argv[0], argv[1])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
already_AddRefed<TestInterfaceMaplike>
Get(mozilla::dom::TestInterfaceMaplikeObject* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
JS::Rooted<JS::Value> result(cx);
if (!JS::MapGet(cx, backingObj, argv[0], &result)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
if (result.isUndefined()) {
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
return nullptr;
}
RefPtr<mozilla::dom::TestInterfaceMaplike> rvalDecl;
static_assert(IsRefcounted<mozilla::dom::TestInterfaceMaplike>::value, "We can only store refcounted classes.");
{
// Our JSContext should be in the right global to do unwrapping in.
nsresult rv = UnwrapObject<prototypes::id::TestInterfaceMaplike, mozilla::dom::TestInterfaceMaplike>(result, rvalDecl, cx);
if (NS_FAILED(rv)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
return rvalDecl.forget();
}
} // namespace MaplikeHelpers
MOZ_CAN_RUN_SCRIPT static bool
setInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "setInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplikeObject.setInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->SetInternal(NonNullHelper(Constify(arg0))))>, "Should be returning void here");
MOZ_KnownLive(self)->SetInternal(NonNullHelper(Constify(arg0)));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setUndefined();
return true;
}
static const JSJitInfo setInternal_methodinfo = {
{ (JSJitGetterOp)setInternal },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::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
clearInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "clearInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
// NOTE: This assert does NOT call the function.
static_assert(std::is_void_v<decltype(MOZ_KnownLive(self)->ClearInternal())>, "Should be returning void here");
MOZ_KnownLive(self)->ClearInternal();
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setUndefined();
return true;
}
static const JSJitInfo clearInternal_methodinfo = {
{ (JSJitGetterOp)clearInternal },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
true, /* 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
deleteInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "deleteInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplikeObject.deleteInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
bool result(MOZ_KnownLive(self)->DeleteInternal(NonNullHelper(Constify(arg0))));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo deleteInternal_methodinfo = {
{ (JSJitGetterOp)deleteInternal },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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
hasInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "hasInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplikeObject.hasInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
bool result(MOZ_KnownLive(self)->HasInternal(NonNullHelper(Constify(arg0))));
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo hasInternal_methodinfo = {
{ (JSJitGetterOp)hasInternal },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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
getInternal(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "getInternal", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
if (!args.requireAtLeast(cx, "TestInterfaceMaplikeObject.getInternal", 1)) {
return false;
}
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
return false;
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceMaplike>(MOZ_KnownLive(self)->GetInternal(NonNullHelper(Constify(arg0)), rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceMaplikeObject.getInternal"))) {
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 getInternal_methodinfo = {
{ (JSJitGetterOp)getInternal },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
JSJitInfo::Method,
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_size(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "size", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
uint32_t result = JS::MapSize(cx, backingObj);
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setNumber(result);
return true;
}
static const JSJitInfo size_getterinfo = {
{ get_size },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
JSJitInfo::Getter,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
true, /* 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
entries(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "entries", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::MapEntries(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo entries_methodinfo = {
{
{ (JSJitGetterOp)entries },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
entries_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
keys(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "keys", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::MapKeys(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo keys_methodinfo = {
{
{ (JSJitGetterOp)keys },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
keys_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::MapValues(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
forEach(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceMaplikeObject.forEach");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "forEach", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
JS::Rooted<JSObject*> arg0(cx);
if (args.get(0).isObject()) {
arg0 = &args.get(0).toObject();
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JS::Value> arg1(cx);
if (args.hasDefined(1)) {
arg1 = args.get(1);
} else {
arg1 = JS::UndefinedValue();
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
// Create a wrapper function.
JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
if (!func) {
return false;
}
JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
JS::ObjectValue(*arg0));
js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
JS::ObjectValue(*obj));
if (!JS::MapForEach(cx, backingObj, funcVal, arg1)) {
return false;
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo forEach_methodinfo = {
{ (JSJitGetterOp)forEach },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::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
has(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "has", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
bool result;
if (!JS::MapHas(cx, backingObj, arg0Val, &result)) {
return false;
}
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo has_methodinfo = {
{
{ (JSJitGetterOp)has },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
has_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
get(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "get", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceMaplikeObject*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetMaplikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
JS::Rooted<JS::Value> result(cx);
if (!JS::MapGet(cx, backingObj, arg0Val, &result)) {
return false;
}
JS::ExposeValueToActiveJS(result);
args.rval().set(result);
if (!MaybeWrapValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType get_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo get_methodinfo = {
{
{ (JSJitGetterOp)get },
{ prototypes::id::TestInterfaceMaplikeObject },
{ PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasDOMSets, /* 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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
get_methodinfo_argTypes
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceMaplikeObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeObject>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceMaplikeObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeObject>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceMaplikeObject>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceMaplikeObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeObject>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceMaplikeObject* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceMaplikeObject>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("setInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&setInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("clearInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&clearInternal_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("deleteInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&deleteInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("hasInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&hasInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("getInternal", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&getInternal_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("forEach", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("has", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("get", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&get_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(11 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("size", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &size_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(1 <= 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[12];
static PropertyInfo sNativeProperties_propertyInfos[12];
static const NativePropertiesN<2> sNativeProperties = {
false, 0,
false, 0,
true, 0 /* sMethods */,
true, 1 /* sAttributes */,
false, 0,
false, 0,
false, 0,
5,
12,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] },
{ sAttributes, &sNativeProperties_propertyInfos[11] }
}
};
static_assert(5 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
"We have an iterator alias index that is oversized");
static_assert(12 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
// This may allocate too many slots, because we only really need
// slots for our non-interface-typed members that we cache. But
// allocating slots only for those would make the slot index
// computations much more complicated, so let's do this the simple
// way for now.
DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
nullptr,
{ sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited },
prototypes::id::TestInterfaceMaplikeObject,
constructors::id::TestInterfaceMaplikeObject,
&sXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceMaplikeObject", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceMaplikeObject");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceMaplikeObject,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceMaplikeObject>(mozilla::dom::TestInterfaceMaplikeObject::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceMaplikeObject constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceMaplikeObject,
PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceMaplikeObjectPrototype",
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::TestInterfaceMaplikeObject,
PrototypeTraits<prototypes::id::TestInterfaceMaplikeObject>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceMaplikeObject",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceMaplikeObject, 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<nsISupports, mozilla::dom::TestInterfaceMaplikeObject>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceMaplikeObject>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceMaplikeObject>::Get(),
nullptr,
_getWrapperCache
};
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
"Must have the right minimal number of reserved slots.");
static_assert(2 >= 2,
"Must have enough reserved slots.");
bool
Wrap(JSContext* aCx, mozilla::dom::TestInterfaceMaplikeObject* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceMaplikeObject>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceMaplikeObject*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceMaplikeObject> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceMaplikeObject);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceMaplikeObject);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceMaplikeObject", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "entries", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> iteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::iterator));
if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceMaplikeObject_Binding
namespace TestInterfaceSetlike_Binding {
namespace SetlikeHelpers {
void
Clear(mozilla::dom::TestInterfaceSetlike* self, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
if (!JS::SetClear(cx, backingObj)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
bool
Delete(mozilla::dom::TestInterfaceSetlike* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
bool retVal;
if (!JS::SetDelete(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
bool
Has(mozilla::dom::TestInterfaceSetlike* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
bool retVal;
if (!JS::SetHas(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
void
Add(mozilla::dom::TestInterfaceSetlike* self, const nsAString& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
do {
if (!xpc::NonVoidStringToJsval(cx, aKey, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
if (!JS::SetAdd(cx, backingObj, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
} // namespace SetlikeHelpers
MOZ_CAN_RUN_SCRIPT static bool
get_size(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "size", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
uint32_t result = JS::SetSize(cx, backingObj);
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setNumber(result);
return true;
}
static const JSJitInfo size_getterinfo = {
{ get_size },
{ prototypes::id::TestInterfaceSetlike },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
JSJitInfo::Getter,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
true, /* 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
entries(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "entries", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::SetEntries(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo entries_methodinfo = {
{
{ (JSJitGetterOp)entries },
{ prototypes::id::TestInterfaceSetlike },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlike>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
entries_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
keys(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "keys", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::SetKeys(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo keys_methodinfo = {
{
{ (JSJitGetterOp)keys },
{ prototypes::id::TestInterfaceSetlike },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlike>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
keys_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::SetValues(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceSetlike },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlike>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
forEach(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceSetlike.forEach");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "forEach", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlike*>(void_self);
JS::Rooted<JSObject*> arg0(cx);
if (args.get(0).isObject()) {
arg0 = &args.get(0).toObject();
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JS::Value> arg1(cx);
if (args.hasDefined(1)) {
arg1 = args.get(1);
} else {
arg1 = JS::UndefinedValue();
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
// Create a wrapper function.
JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
if (!func) {
return false;
}
JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
JS::ObjectValue(*arg0));
js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
JS::ObjectValue(*obj));
if (!JS::SetForEach(cx, backingObj, funcVal, arg1)) {
return false;
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo forEach_methodinfo = {
{ (JSJitGetterOp)forEach },
{ prototypes::id::TestInterfaceSetlike },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlike>::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
has(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "has", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlike*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
bool result;
if (!JS::SetHas(cx, backingObj, arg0Val, &result)) {
return false;
}
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::String, JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo has_methodinfo = {
{
{ (JSJitGetterOp)has },
{ prototypes::id::TestInterfaceSetlike },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
has_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
clear(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "clear", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlike*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
if (!JS::SetClear(cx, backingObj)) {
return false;
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo clear_methodinfo = {
{ (JSJitGetterOp)clear },
{ prototypes::id::TestInterfaceSetlike },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlike>::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
_delete_(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "delete", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlike*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
bool result;
if (!JS::SetDelete(cx, backingObj, arg0Val, &result)) {
return false;
}
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo delete_methodinfo = {
{ (JSJitGetterOp)_delete_ },
{ prototypes::id::TestInterfaceSetlike },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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
add(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "add", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlike*>(void_self);
binding_detail::FakeString<char16_t> arg0;
if (!ConvertJSValueToString(cx, args.get(0), eStringify, eStringify, arg0)) {
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlike>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
JS::Rooted<JSObject*> result(cx);
if (!JS::SetAdd(cx, backingObj, arg0Val)) {
return false;
}
result = obj;
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo add_methodinfo = {
{ (JSJitGetterOp)add },
{ prototypes::id::TestInterfaceSetlike },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlike>::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. */
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceSetlike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlike>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceSetlike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlike>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceSetlike>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceSetlike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlike>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceSetlike* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlike>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("forEach", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("has", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("clear", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&clear_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("delete", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&delete_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("add", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&add_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(8 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("size", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &size_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(1 <= 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,
2,
9,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] },
{ sAttributes, &sNativeProperties_propertyInfos[8] }
}
};
static_assert(2 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
"We have an iterator alias index that is oversized");
static_assert(9 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
// This may allocate too many slots, because we only really need
// slots for our non-interface-typed members that we cache. But
// allocating slots only for those would make the slot index
// computations much more complicated, so let's do this the simple
// way for now.
DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
nullptr,
{ sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited },
prototypes::id::TestInterfaceSetlike,
constructors::id::TestInterfaceSetlike,
&sXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlike", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceSetlike");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceSetlike,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceSetlike>(mozilla::dom::TestInterfaceSetlike::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceSetlike constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceSetlike,
PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceSetlikePrototype",
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::TestInterfaceSetlike,
PrototypeTraits<prototypes::id::TestInterfaceSetlike>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceSetlike",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceSetlike, 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<nsISupports, mozilla::dom::TestInterfaceSetlike>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceSetlike>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceSetlike>::Get(),
nullptr,
_getWrapperCache
};
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
"Must have the right minimal number of reserved slots.");
static_assert(2 >= 2,
"Must have enough reserved slots.");
bool
Wrap(JSContext* aCx, mozilla::dom::TestInterfaceSetlike* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceSetlike>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceSetlike*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceSetlike> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceSetlike);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceSetlike);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceSetlike", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "values", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> iteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::iterator));
if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceSetlike_Binding
namespace TestInterfaceSetlikeNode_Binding {
namespace SetlikeHelpers {
void
Clear(mozilla::dom::TestInterfaceSetlikeNode* self, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
if (!JS::SetClear(cx, backingObj)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
bool
Delete(mozilla::dom::TestInterfaceSetlikeNode* self, nsINode& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!GetOrCreateDOMReflector(cx, aKey, argv[0])) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
bool retVal;
if (!JS::SetDelete(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
bool
Has(mozilla::dom::TestInterfaceSetlikeNode* self, nsINode& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
do {
if (!GetOrCreateDOMReflector(cx, aKey, argv[0])) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
bool retVal;
if (!JS::SetHas(cx, backingObj, argv[0], &retVal)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return bool(0);
}
return retVal;
}
void
Add(mozilla::dom::TestInterfaceSetlikeNode* self, nsINode& aKey, ErrorResult& aRv)
{
MOZ_ASSERT(self);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
// It's safe to use UnprivilegedJunkScopeOrWorkerGlobal here because
// all we want is to wrap into _some_ scope and then unwrap to find
// the reflector, and wrapping has no side-effects.
JSObject* scope = UnprivilegedJunkScopeOrWorkerGlobal(fallible);
if (!scope) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
JSAutoRealm tempRealm(cx, scope);
JS::Rooted<JS::Value> v(cx);
if(!ToJSValue(cx, self, &v)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoRealm reflectorRealm(cx, obj);
JS::RootedVector<JS::Value> argv(cx);
if (!argv.resize(1)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
do {
if (!GetOrCreateDOMReflector(cx, aKey, argv[0])) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
break;
} while (false);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
if (!JS::SetAdd(cx, backingObj, argv[0])) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
}
} // namespace SetlikeHelpers
MOZ_CAN_RUN_SCRIPT static bool
get_size(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, JSJitGetterCallArgs args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "size", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_GETTER) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
uint32_t result = JS::SetSize(cx, backingObj);
MOZ_ASSERT(!JS_IsExceptionPending(cx));
args.rval().setNumber(result);
return true;
}
static const JSJitInfo size_getterinfo = {
{ get_size },
{ prototypes::id::TestInterfaceSetlikeNode },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
JSJitInfo::Getter,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
true, /* 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
entries(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "entries", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::SetEntries(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType entries_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo entries_methodinfo = {
{
{ (JSJitGetterOp)entries },
{ prototypes::id::TestInterfaceSetlikeNode },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
entries_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
keys(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "keys", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::SetKeys(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType keys_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo keys_methodinfo = {
{
{ (JSJitGetterOp)keys },
{ prototypes::id::TestInterfaceSetlikeNode },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
keys_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
values(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "values", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
// TODO (Bug 1173651): Xrays currently cannot wrap iterators. Change
// after bug 1023984 is fixed.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
JS_ReportErrorASCII(cx, "Xray wrapping of iterators not supported.");
return false;
}
JS::Rooted<JSObject*> result(cx);
JS::Rooted<JS::Value> v(cx);
if (!JS::SetValues(cx, backingObj, &v)) {
return false;
}
result = &v.toObject();
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo::ArgType values_methodinfo_argTypes[] = { JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo values_methodinfo = {
{
{ (JSJitGetterOp)values },
{ prototypes::id::TestInterfaceSetlikeNode },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
values_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
forEach(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceSetlikeNode.forEach");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "forEach", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(void_self);
JS::Rooted<JSObject*> arg0(cx);
if (args.get(0).isObject()) {
arg0 = &args.get(0).toObject();
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JS::Value> arg1(cx);
if (args.hasDefined(1)) {
arg1 = args.get(1);
} else {
arg1 = JS::UndefinedValue();
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
// Create a wrapper function.
JSFunction* func = js::NewFunctionWithReserved(cx, ForEachHandler, 3, 0, nullptr);
if (!func) {
return false;
}
JS::Rooted<JSObject*> funcObj(cx, JS_GetFunctionObject(func));
JS::Rooted<JS::Value> funcVal(cx, JS::ObjectValue(*funcObj));
js::SetFunctionNativeReserved(funcObj, FOREACH_CALLBACK_SLOT,
JS::ObjectValue(*arg0));
js::SetFunctionNativeReserved(funcObj, FOREACH_MAPLIKEORSETLIKEOBJ_SLOT,
JS::ObjectValue(*obj));
if (!JS::SetForEach(cx, backingObj, funcVal, arg1)) {
return false;
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo forEach_methodinfo = {
{ (JSJitGetterOp)forEach },
{ prototypes::id::TestInterfaceSetlikeNode },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::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
has(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceSetlikeNode.has");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "has", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(void_self);
NonNull<nsINode> arg0;
if (args.get(0).isObject()) {
{
// Our JSContext should be in the right global to do unwrapping in.
nsresult rv = UnwrapObject<prototypes::id::Node, nsINode>(args[0], arg0, cx);
if (NS_FAILED(rv)) {
cx.ThrowErrorMessage<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("Argument 1", "Node");
return false;
}
}
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
bool result;
if (!JS::SetHas(cx, backingObj, arg0Val, &result)) {
return false;
}
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo::ArgType has_methodinfo_argTypes[] = { JSJitInfo::Object, JSJitInfo::ArgTypeListEnd };
static const JSTypedMethodJitInfo has_methodinfo = {
{
{ (JSJitGetterOp)has },
{ prototypes::id::TestInterfaceSetlikeNode },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasDOMSets, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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. */
true, /* isTypedMethod. Only relevant for methods. */
0 /* Reserved slot index, if we're stored in a slot, else 0. */
},
has_methodinfo_argTypes
};
MOZ_CAN_RUN_SCRIPT static bool
clear(JSContext* cx, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "clear", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(void_self);
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
if (!JS::SetClear(cx, backingObj)) {
return false;
}
args.rval().setUndefined();
return true;
}
static const JSJitInfo clear_methodinfo = {
{ (JSJitGetterOp)clear },
{ prototypes::id::TestInterfaceSetlikeNode },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::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
_delete_(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceSetlikeNode.delete");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "delete", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(void_self);
NonNull<nsINode> arg0;
if (args.get(0).isObject()) {
{
// Our JSContext should be in the right global to do unwrapping in.
nsresult rv = UnwrapObject<prototypes::id::Node, nsINode>(args[0], arg0, cx);
if (NS_FAILED(rv)) {
cx.ThrowErrorMessage<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("Argument 1", "Node");
return false;
}
}
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
bool result;
if (!JS::SetDelete(cx, backingObj, arg0Val, &result)) {
return false;
}
args.rval().setBoolean(result);
return true;
}
static const JSJitInfo delete_methodinfo = {
{ (JSJitGetterOp)_delete_ },
{ prototypes::id::TestInterfaceSetlikeNode },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth },
JSJitInfo::Method,
JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
JSVAL_TYPE_BOOLEAN, /* 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
add(JSContext* cx_, JS::Handle<JSObject*> obj, void* void_self, const JSJitMethodCallArgs& args)
{
BindingCallContext cx(cx_, "TestInterfaceSetlikeNode.add");
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "add", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::STRING_TEMPLATE_METHOD) |
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
auto* self = static_cast<mozilla::dom::TestInterfaceSetlikeNode*>(void_self);
NonNull<nsINode> arg0;
if (args.get(0).isObject()) {
{
// Our JSContext should be in the right global to do unwrapping in.
nsresult rv = UnwrapObject<prototypes::id::Node, nsINode>(args[0], arg0, cx);
if (NS_FAILED(rv)) {
cx.ThrowErrorMessage<MSG_DOES_NOT_IMPLEMENT_INTERFACE>("Argument 1", "Node");
return false;
}
}
} else {
cx.ThrowErrorMessage<MSG_NOT_OBJECT>("Argument 1");
return false;
}
JS::Rooted<JSObject*> backingObj(cx);
bool created = false;
if (!GetSetlikeBackingObject(cx, obj, (DOM_INSTANCE_RESERVED_SLOTS + 0), &backingObj, &created)) {
return false;
}
if (created) {
PreserveWrapper<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
JS::Rooted<JS::Value> arg0Val(cx);
if (!ToJSValue(cx, arg0, &arg0Val)) {
return false;
}
JS::Rooted<JSObject*> result(cx);
if (!JS::SetAdd(cx, backingObj, arg0Val)) {
return false;
}
result = obj;
JS::ExposeObjectToActiveJS(result);
args.rval().setObject(*result);
if (!MaybeWrapObjectValue(cx, args.rval())) {
return false;
}
return true;
}
static const JSJitInfo add_methodinfo = {
{ (JSJitGetterOp)add },
{ prototypes::id::TestInterfaceSetlikeNode },
{ PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::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. */
};
static bool
_addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
{
mozilla::dom::TestInterfaceSetlikeNode* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlikeNode>(obj);
// We don't want to preserve if we don't have a wrapper, and we
// obviously can't preserve if we're not initialized.
if (self && self->GetWrapperPreserveColor()) {
PreserveWrapper(self);
}
return true;
}
static void
_finalize(JS::GCContext* gcx, JSObject* obj)
{
mozilla::dom::TestInterfaceSetlikeNode* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlikeNode>(obj);
if (self) {
JS::SetReservedSlot(obj, DOM_OBJECT_SLOT, JS::UndefinedValue());
ClearWrapper(self, self, obj);
if (size_t mallocBytes = BindingJSObjectMallocBytes(self)) {
JS::RemoveAssociatedMemory(obj, mallocBytes,
JS::MemoryUse::DOMBinding);
}
AddForDeferredFinalization<mozilla::dom::TestInterfaceSetlikeNode>(self);
}
}
static nsWrapperCache*
_getWrapperCache(JS::Handle<JSObject*> obj)
{
mozilla::dom::TestInterfaceSetlikeNode* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlikeNode>(obj);
return self;
}
static size_t
_objectMoved(JSObject* obj, JSObject* old)
{
mozilla::dom::TestInterfaceSetlikeNode* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::TestInterfaceSetlikeNode>(obj);
if (self) {
UpdateWrapper(self, self, obj, old);
}
return 0;
}
static const JSFunctionSpec sMethods_specs[] = {
JS_FNSPEC("entries", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&entries_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("keys", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&keys_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("values", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&values_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("forEach", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&forEach_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("has", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&has_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("clear", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&clear_methodinfo), 0, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("delete", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&delete_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FNSPEC("add", (GenericMethod<NormalThisPolicy, ThrowExceptions>), reinterpret_cast<const JSJitInfo*>(&add_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
JS_FS_END
};
static const Prefable<const JSFunctionSpec> 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(8 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
"We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
static const JSPropertySpec sAttributes_specs[] = {
JSPropertySpec::nativeAccessors("size", JSPROP_ENUMERATE, GenericGetter<NormalThisPolicy, ThrowExceptions>, &size_getterinfo, nullptr, nullptr),
JS_PS_END
};
static const Prefable<const JSPropertySpec> 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(1 <= 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,
2,
9,
sNativeProperties_sortedPropertyIndices,
{
{ sMethods, &sNativeProperties_propertyInfos[0] },
{ sAttributes, &sNativeProperties_propertyInfos[8] }
}
};
static_assert(2 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.iteratorAliasMethodIndex) - 1),
"We have an iterator alias index that is oversized");
static_assert(9 < 1ull << (CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount)),
"We have a property info count that is oversized");
// This may allocate too many slots, because we only really need
// slots for our non-interface-typed members that we cache. But
// allocating slots only for those would make the slot index
// computations much more complicated, so let's do this the simple
// way for now.
DEFINE_XRAY_EXPANDO_CLASS(static, sXrayExpandoObjectClass, 1);
bool sNativePropertiesInited = false;
const NativePropertyHooks sNativePropertyHooks = {
nullptr,
{ sNativeProperties.Upcast(), nullptr, &sNativePropertiesInited },
prototypes::id::TestInterfaceSetlikeNode,
constructors::id::TestInterfaceSetlikeNode,
&sXrayExpandoObjectClass
};
static bool
_constructor(JSContext* cx, unsigned argc, JS::Value* vp)
{
AUTO_PROFILER_LABEL_DYNAMIC_FAST(
"TestInterfaceSetlikeNode", "constructor", DOM, cx,
uint32_t(js::ProfilingStackFrame::Flags::RELEVANT_FOR_JS));
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
if (!args.isConstructing()) {
return ThrowConstructorWithoutNew(cx, "TestInterfaceSetlikeNode");
}
JS::Rooted<JSObject*> desiredProto(cx);
if (!GetDesiredProto(cx, args,
prototypes::id::TestInterfaceSetlikeNode,
CreateInterfaceObjects,
&desiredProto)) {
return false;
}
GlobalObject global(cx, obj);
if (global.Failed()) {
return false;
}
bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
Maybe<JSAutoRealm> 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;
}
}
FastErrorResult rv;
auto result(StrongOrRawPtr<mozilla::dom::TestInterfaceSetlikeNode>(mozilla::dom::TestInterfaceSetlikeNode::Constructor(global, rv)));
if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx, "TestInterfaceSetlikeNode constructor"))) {
return false;
}
MOZ_ASSERT(!JS_IsExceptionPending(cx));
static_assert(!std::is_pointer_v<decltype(result)>,
"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::GetRealmFunctionPrototype,
prototypes::id::TestInterfaceSetlikeNode,
PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth,
true,
};
static const DOMIfaceAndProtoJSClass sPrototypeClass = {
{
"TestInterfaceSetlikeNodePrototype",
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::TestInterfaceSetlikeNode,
PrototypeTraits<prototypes::id::TestInterfaceSetlikeNode>::Depth,
&sNativePropertyHooks,
JS::GetRealmObjectPrototype
};
bool
ConstructorEnabled(JSContext* aCx, JS::Handle<JSObject*> aObj)
{
return StaticPrefs::dom_expose_test_interfaces();
}
static const JSClassOps sClassOps = {
_addProperty, /* addProperty */
nullptr, /* delProperty */
nullptr, /* enumerate */
nullptr, /* newEnumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
_finalize, /* finalize */
nullptr, /* call */
nullptr, /* construct */
nullptr, /* trace */
};
static const js::ClassExtension sClassExtension = {
_objectMoved /* objectMovedOp */
};
static const DOMJSClass sClass = {
{ "TestInterfaceSetlikeNode",
JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(2),
&sClassOps,
JS_NULL_CLASS_SPEC,
&sClassExtension,
JS_NULL_OBJECT_OPS
},
{ prototypes::id::TestInterfaceSetlikeNode, 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<nsISupports, mozilla::dom::TestInterfaceSetlikeNode>,
&sNativePropertyHooks,
FindAssociatedGlobalForNative<mozilla::dom::TestInterfaceSetlikeNode>::Get,
GetProtoObjectHandle,
GetCCParticipant<mozilla::dom::TestInterfaceSetlikeNode>::Get(),
nullptr,
_getWrapperCache
};
static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
"Must have the right minimal number of reserved slots.");
static_assert(2 >= 2,
"Must have enough reserved slots.");
bool
Wrap(JSContext* aCx, mozilla::dom::TestInterfaceSetlikeNode* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
{
static_assert(!std::is_base_of_v<NonRefcountedDOMObject, mozilla::dom::TestInterfaceSetlikeNode>,
"Shouldn't have wrappercached things that are not refcounted.");
static_assert(std::is_same_v<decltype(aObject), mozilla::dom::TestInterfaceSetlikeNode*>);
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<JSObject*> 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<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
if (!canonicalProto) {
return false;
}
JS::Rooted<JSObject*> 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<mozilla::dom::TestInterfaceSetlikeNode> 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<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
{
JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::TestInterfaceSetlikeNode);
JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::TestInterfaceSetlikeNode);
JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
if (!parentProto) {
return;
}
JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
if (!constructorProto) {
return;
}
dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
&sPrototypeClass, protoCache,
constructorProto, &sInterfaceObjectInfo, 0, false, Span<const LegacyFactoryFunction, 0>{},
interfaceCache,
sNativeProperties.Upcast(),
nullptr,
"TestInterfaceSetlikeNode", aDefineOnGlobal,
nullptr,
false,
nullptr);
JS::AssertObjectIsNotGray(*protoCache);
JS::Handle<JSObject*> proto = JS::Handle<JSObject*>::fromMarkedLocation(protoCache->address());
if (!proto) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
// Set up aliases on the interface prototype object we just created.
JS::Rooted<JS::Value> aliasedVal(aCx);
if (!JS_GetProperty(aCx, proto, "values", &aliasedVal)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
JS::Rooted<jsid> iteratorId(aCx, JS::GetWellKnownSymbolKey(aCx, JS::SymbolCode::iterator));
if (!JS_DefinePropertyById(aCx, proto, iteratorId, aliasedVal, 0)) {
*protoCache = nullptr;
if (interfaceCache) {
*interfaceCache = nullptr;
}
return;
}
}
JSObject*
GetConstructorObject(JSContext* aCx)
{
return GetConstructorObjectHandle(aCx);
}
} // namespace TestInterfaceSetlikeNode_Binding
} // namespace mozilla::dom