TestInterfaceAsyncIterableSingle.cpp (4825B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/TestInterfaceAsyncIterableSingle.h" 8 9 #include "mozilla/dom/BindingUtils.h" 10 #include "mozilla/dom/IterableIterator.h" 11 #include "mozilla/dom/Promise-inl.h" 12 #include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" 13 #include "nsPIDOMWindow.h" 14 #include "nsThreadUtils.h" 15 16 namespace mozilla::dom { 17 18 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TestInterfaceAsyncIterableSingle, mParent) 19 20 NS_IMPL_CYCLE_COLLECTING_ADDREF(TestInterfaceAsyncIterableSingle) 21 NS_IMPL_CYCLE_COLLECTING_RELEASE(TestInterfaceAsyncIterableSingle) 22 23 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TestInterfaceAsyncIterableSingle) 24 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 25 NS_INTERFACE_MAP_ENTRY(nsISupports) 26 NS_INTERFACE_MAP_END 27 28 TestInterfaceAsyncIterableSingle::TestInterfaceAsyncIterableSingle( 29 nsPIDOMWindowInner* aParent, bool aFailToInit) 30 : mParent(aParent), mFailToInit(aFailToInit) {} 31 32 // static 33 already_AddRefed<TestInterfaceAsyncIterableSingle> 34 TestInterfaceAsyncIterableSingle::Constructor( 35 const GlobalObject& aGlobal, 36 const TestInterfaceAsyncIterableSingleOptions& aOptions, ErrorResult& aRv) { 37 nsCOMPtr<nsPIDOMWindowInner> window = 38 do_QueryInterface(aGlobal.GetAsSupports()); 39 if (!window) { 40 aRv.Throw(NS_ERROR_FAILURE); 41 return nullptr; 42 } 43 44 RefPtr<TestInterfaceAsyncIterableSingle> r = 45 new TestInterfaceAsyncIterableSingle(window, aOptions.mFailToInit); 46 return r.forget(); 47 } 48 49 JSObject* TestInterfaceAsyncIterableSingle::WrapObject( 50 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) { 51 return TestInterfaceAsyncIterableSingle_Binding::Wrap(aCx, this, aGivenProto); 52 } 53 54 nsPIDOMWindowInner* TestInterfaceAsyncIterableSingle::GetParentObject() const { 55 return mParent; 56 } 57 58 void TestInterfaceAsyncIterableSingle::InitAsyncIteratorData( 59 IteratorData& aData, Iterator::IteratorType aType, ErrorResult& aError) { 60 if (mFailToInit) { 61 aError.ThrowTypeError("Caller asked us to fail"); 62 return; 63 } 64 65 // Nothing else to do. 66 MOZ_ASSERT(aData.mIndex == 0); 67 MOZ_ASSERT(aData.mMultiplier == 1); 68 } 69 70 already_AddRefed<Promise> 71 TestInterfaceAsyncIterableSingle::GetNextIterationResult(Iterator* aIterator, 72 ErrorResult& aRv) { 73 return GetNextIterationResult(aIterator, aIterator->Data(), aRv); 74 } 75 76 already_AddRefed<Promise> 77 TestInterfaceAsyncIterableSingle::GetNextIterationResult( 78 IterableIteratorBase* aIterator, IteratorData& aData, ErrorResult& aRv) { 79 RefPtr<Promise> promise = Promise::Create(mParent->AsGlobal(), aRv); 80 if (NS_WARN_IF(aRv.Failed())) { 81 return nullptr; 82 } 83 84 nsCOMPtr<nsIRunnable> callResolvePromise = 85 NewRunnableMethod<RefPtr<IterableIteratorBase>, IteratorData&, 86 RefPtr<Promise>>( 87 "TestInterfaceAsyncIterableSingle::GetNextIterationResult", this, 88 &TestInterfaceAsyncIterableSingle::ResolvePromise, aIterator, aData, 89 promise); 90 if (aData.mBlockingPromisesIndex < aData.mBlockingPromises.Length()) { 91 aData.mBlockingPromises[aData.mBlockingPromisesIndex] 92 ->AddCallbacksWithCycleCollectedArgs( 93 [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv, 94 nsIRunnable* aCallResolvePromise) { 95 NS_DispatchToMainThread(aCallResolvePromise); 96 }, 97 [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv, 98 nsIRunnable* aCallResolvePromise) {}, 99 std::move(callResolvePromise)); 100 ++aData.mBlockingPromisesIndex; 101 } else { 102 NS_DispatchToMainThread(callResolvePromise); 103 } 104 105 return promise.forget(); 106 } 107 108 void TestInterfaceAsyncIterableSingle::ResolvePromise( 109 IterableIteratorBase* aIterator, IteratorData& aData, Promise* aPromise) { 110 if (aData.mIndex >= 10) { 111 iterator_utils::ResolvePromiseForFinished(aPromise); 112 } else { 113 aPromise->MaybeResolve(int32_t(aData.mIndex * 9 % 7 * aData.mMultiplier)); 114 115 aData.mIndex++; 116 } 117 } 118 119 void TestInterfaceAsyncIterableSingle::IteratorData::Traverse( 120 nsCycleCollectionTraversalCallback& cb) { 121 TestInterfaceAsyncIterableSingle::IteratorData* tmp = this; 122 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBlockingPromises); 123 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mThrowFromReturn); 124 } 125 void TestInterfaceAsyncIterableSingle::IteratorData::Unlink() { 126 TestInterfaceAsyncIterableSingle::IteratorData* tmp = this; 127 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBlockingPromises); 128 NS_IMPL_CYCLE_COLLECTION_UNLINK(mThrowFromReturn); 129 } 130 131 } // namespace mozilla::dom