diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 3ef29154057e7032f34980ff2fdd04946c096a91..f889808fe8fb7b9e1245467751ecb3c61c887e2a 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -63,7 +63,6 @@ #include "mozilla/dom/Element.h" #include "mozilla/dom/ErrorEvent.h" #include "mozilla/dom/FetchUtil.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/SerializedStackHolder.h" #include "mozilla/CycleCollectedJSRuntime.h" diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index acbf49e9e7c6b56ab1e1ac6914a784db6e46e043..a2c3ebcc1406ee4e5c988c41db99255ccfa49ee5 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -35,6 +35,7 @@ from Configuration import ( getAllTypes, Descriptor, MemberIsLegacyUnforgeable, + iteratorNativeType, ) AUTOGENERATED_WARNING_COMMENT = ( @@ -1854,9 +1855,6 @@ class CGAbstractMethod(CGThing): arguments. canRunScript should be True to generate a MOZ_CAN_RUN_SCRIPT annotation. - - signatureOnly should be True to only declare the signature (either in - the header, or if static is True in the cpp file). """ def __init__( @@ -1870,7 +1868,6 @@ class CGAbstractMethod(CGThing): static=False, templateArgs=None, canRunScript=False, - signatureOnly=False, ): CGThing.__init__(self) self.descriptor = descriptor @@ -1882,7 +1879,6 @@ class CGAbstractMethod(CGThing): self.static = static self.templateArgs = templateArgs self.canRunScript = canRunScript - self.signatureOnly = signatureOnly def _argstring(self, declare): return ", ".join([a.declare() if declare else a.define() for a in self.args]) @@ -1906,7 +1902,9 @@ class CGAbstractMethod(CGThing): maybeNewline = " " if self.inline else "\n" return " ".join(decorators) + maybeNewline - def signature(self): + def declare(self): + if self.inline: + return self._define(True) return "%s%s%s(%s);\n" % ( self._template(), self._decorators(), @@ -1914,13 +1912,6 @@ class CGAbstractMethod(CGThing): self._argstring(True), ) - def declare(self): - if self.static: - return "" - if self.inline: - return self._define(True) - return self.signature() - def indent_body(self, body): """ Indent the code returned by self.definition_body(). Most classes @@ -1937,12 +1928,7 @@ class CGAbstractMethod(CGThing): ) def define(self): - if self.signatureOnly: - if self.static: - # self.static makes us not output anything in the header, so output the signature here. - return self.signature() - return "" - return "" if (self.inline and not self.static) else self._define() + return "" if self.inline else self._define() def definition_prologue(self, fromDeclare): error_reporting_label = self.error_reporting_label() @@ -2027,6 +2013,10 @@ class CGAbstractStaticMethod(CGAbstractMethod): canRunScript=canRunScript, ) + def declare(self): + # We only have implementation + return "" + class CGAbstractClassHook(CGAbstractStaticMethod): """ @@ -2050,6 +2040,14 @@ class CGAbstractClassHook(CGAbstractStaticMethod): assert False # Override me! +class CGGetJSClassMethod(CGAbstractMethod): + def __init__(self, descriptor): + CGAbstractMethod.__init__(self, descriptor, "GetJSClass", "const JSClass*", []) + + def definition_body(self): + return "return sClass.ToJSClass();\n" + + class CGAddPropertyHook(CGAbstractClassHook): """ A hook for addProperty, used to preserve our wrapper from GC. @@ -3566,7 +3564,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): """ def __init__( - self, descriptor, properties, haveUnscopables, haveLegacyWindowAliases, static + self, descriptor, properties, haveUnscopables, haveLegacyWindowAliases ): args = [ Argument("JSContext*", "aCx"), @@ -3575,7 +3573,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod): Argument("bool", "aDefineOnGlobal"), ] CGAbstractMethod.__init__( - self, descriptor, "CreateInterfaceObjects", "void", args, static=static + self, descriptor, "CreateInterfaceObjects", "void", args ) self.properties = properties self.haveUnscopables = haveUnscopables @@ -3948,7 +3946,7 @@ class CGGetProtoObjectHandleMethod(CGAbstractMethod): A method for getting the interface prototype object. """ - def __init__(self, descriptor, static, signatureOnly=False): + def __init__(self, descriptor): CGAbstractMethod.__init__( self, descriptor, @@ -3956,8 +3954,6 @@ class CGGetProtoObjectHandleMethod(CGAbstractMethod): "JS::Handle<JSObject*>", [Argument("JSContext*", "aCx")], inline=True, - static=static, - signatureOnly=signatureOnly, ) def definition_body(self): @@ -4308,7 +4304,7 @@ class CGDeserializer(CGAbstractMethod): ) -def CreateBindingJSObject(descriptor): +def CreateBindingJSObject(descriptor, properties): objDecl = "BindingJSObjectCreator<%s> creator(aCx);\n" % descriptor.nativeType # We don't always need to root obj, but there are a variety @@ -4501,17 +4497,9 @@ def CopyUnforgeablePropertiesToInstance(descriptor, failureCode): def AssertInheritanceChain(descriptor): - # We can skip the reinterpret_cast check for the descriptor's nativeType - # if aObject is a pointer of that type. - asserts = fill( - """ - static_assert(std::is_same_v<decltype(aObject), ${nativeType}*>); - """, - nativeType=descriptor.nativeType, - ) + asserts = "" iface = descriptor.interface - while iface.parent: - iface = iface.parent + while iface: desc = descriptor.getDescriptor(iface.identifier.name) asserts += ( "MOZ_ASSERT(static_cast<%s*>(aObject) == \n" @@ -4519,6 +4507,7 @@ def AssertInheritanceChain(descriptor): ' "Multiple inheritance for %s is broken.");\n' % (desc.nativeType, desc.nativeType, desc.nativeType) ) + iface = iface.parent asserts += "MOZ_ASSERT(ToSupportsIsCorrect(aObject));\n" return asserts @@ -4544,26 +4533,16 @@ def InitMemberSlots(descriptor, failureCode): ) -def DeclareProto(descriptor, noGivenProto=False): +def DeclareProto(descriptor): """ Declare the canonicalProto and proto we have for our wrapping operation. """ - getCanonical = dedent( + preamble = dedent( """ - JS::Handle<JSObject*> ${canonicalProto} = GetProtoObjectHandle(aCx); - if (!${canonicalProto}) { + JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx); + if (!canonicalProto) { return false; } - """ - ) - - if noGivenProto: - return fill(getCanonical, canonicalProto="proto") - - getCanonical = fill(getCanonical, canonicalProto="canonicalProto") - - preamble = getCanonical + dedent( - """ JS::Rooted<JSObject*> proto(aCx); """ ) @@ -4600,9 +4579,11 @@ def DeclareProto(descriptor, noGivenProto=False): class CGWrapWithCacheMethod(CGAbstractMethod): """ Create a wrapper JSObject for a given native that implements nsWrapperCache. + + properties should be a PropertyArrays instance. """ - def __init__(self, descriptor): + def __init__(self, descriptor, properties): assert descriptor.interface.hasInterfacePrototypeObject() args = [ Argument("JSContext*", "aCx"), @@ -4612,6 +4593,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod): Argument("JS::MutableHandle<JSObject*>", "aReflector"), ] CGAbstractMethod.__init__(self, descriptor, "Wrap", "bool", args) + self.properties = properties def definition_body(self): failureCode = dedent( @@ -4695,7 +4677,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod): nativeType=self.descriptor.nativeType, assertInheritance=AssertInheritanceChain(self.descriptor), declareProto=DeclareProto(self.descriptor), - createObject=CreateBindingJSObject(self.descriptor), + createObject=CreateBindingJSObject(self.descriptor, self.properties), unforgeable=CopyUnforgeablePropertiesToInstance( self.descriptor, failureCode ), @@ -4736,48 +4718,29 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod): """ Create a wrapper JSObject for a given native that does not implement nsWrapperCache. + + properties should be a PropertyArrays instance. """ - def __init__(self, descriptor, static=False, signatureOnly=False): + def __init__(self, descriptor, properties): # XXX can we wrap if we don't have an interface prototype object? assert descriptor.interface.hasInterfacePrototypeObject() - self.noGivenProto = ( - descriptor.interface.isIteratorInterface() - or descriptor.interface.isAsyncIteratorInterface() - ) args = [ Argument("JSContext*", "aCx"), Argument(descriptor.nativeType + "*", "aObject"), + Argument("JS::Handle<JSObject*>", "aGivenProto"), + Argument("JS::MutableHandle<JSObject*>", "aReflector"), ] - if not self.noGivenProto: - args.append(Argument("JS::Handle<JSObject*>", "aGivenProto")) - args.append(Argument("JS::MutableHandle<JSObject*>", "aReflector")) - CGAbstractMethod.__init__( - self, - descriptor, - "Wrap", - "bool", - args, - static=static, - signatureOnly=signatureOnly, - ) + CGAbstractMethod.__init__(self, descriptor, "Wrap", "bool", args) + self.properties = properties def definition_body(self): failureCode = "return false;\n" - declareProto = DeclareProto(self.descriptor, noGivenProto=self.noGivenProto) - if self.noGivenProto: - assertGivenProto = "" - else: - assertGivenProto = dedent( - """ - MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx)); - """ - ) return fill( """ $*{assertions} - $*{assertGivenProto} + MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx)); JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx)); $*{declareProto} @@ -4792,9 +4755,8 @@ class CGWrapNonWrapperCacheMethod(CGAbstractMethod): return true; """, assertions=AssertInheritanceChain(self.descriptor), - assertGivenProto=assertGivenProto, - declareProto=declareProto, - createObject=CreateBindingJSObject(self.descriptor), + declareProto=DeclareProto(self.descriptor), + createObject=CreateBindingJSObject(self.descriptor, self.properties), unforgeable=CopyUnforgeablePropertiesToInstance( self.descriptor, failureCode ), @@ -5343,7 +5305,7 @@ class CastableObjectUnwrapper: } """, exceptionCode=exceptionCode, - **self.substitution, + **self.substitution ) else: self.substitution["codeOnFailure"] = codeOnFailure @@ -5363,7 +5325,7 @@ class CastableObjectUnwrapper: } } """, - **substitution, + **substitution ) @@ -9581,6 +9543,7 @@ class CGPerSignatureCall(CGThing): cgThings.append( CGIterableMethodGenerator( descriptor, + idlNode.maplikeOrSetlikeOrIterable, idlNode.identifier.name, self.getArgumentNames(), ) @@ -12849,7 +12812,7 @@ class CGUnionStruct(CGThing): mType = e${name}; return mValue.m${name}.SetValue(${ctorArgs}); """, - **vars, + **vars ) # bodyInHeader must be false for return values because they own @@ -12916,7 +12879,7 @@ class CGUnionStruct(CGThing): mValue.m${name}.Destroy(); mType = eUninitialized; """, - **vars, + **vars ) methods.append( ClassMethod( @@ -12934,7 +12897,7 @@ class CGUnionStruct(CGThing): MOZ_RELEASE_ASSERT(Is${name}(), "Wrong type!"); return mValue.m${name}.Value(); """, - **vars, + **vars ) # The non-const version of GetAs* returns our internal type getterReturnType = "%s&" % vars["structType"] @@ -13281,7 +13244,7 @@ class CGUnionConversionStruct(CGThing): mUnion.mType = mUnion.e${name}; return mUnion.mValue.m${name}.SetValue(${ctorArgs}); """, - **vars, + **vars ) methods.append( ClassMethod( @@ -16393,52 +16356,19 @@ class CGDescriptor(CGThing): self._deps = descriptor.interface.getDeps() - iteratorCGThings = None - if ( - descriptor.interface.isIterable() - and descriptor.interface.maplikeOrSetlikeOrIterable.isPairIterator() - ) or descriptor.interface.isAsyncIterable(): - # We need the Wrap function when using the [Async]IterableIterator type, so we want to declare it before we need it. We don't really want to expose it in the header file, so we make it static too. - iteratorCGThings = [] - itr_iface = ( - descriptor.interface.maplikeOrSetlikeOrIterable.iteratorType.inner - ) - iteratorDescriptor = descriptor.getDescriptor(itr_iface.identifier.name) - iteratorCGThings.append( - CGWrapNonWrapperCacheMethod( - iteratorDescriptor, static=True, signatureOnly=True - ) - ) - iteratorCGThings = CGList( - (CGIndenter(t, declareOnly=True) for t in iteratorCGThings), "\n" - ) - iteratorCGThings = CGWrapper(iteratorCGThings, pre="\n", post="\n") - iteratorCGThings = CGWrapper( - CGNamespace( - toBindingNamespace(iteratorDescriptor.name), iteratorCGThings - ), - post="\n", - ) - cgThings = [] - - isIteratorInterface = ( - descriptor.interface.isIteratorInterface() - or descriptor.interface.isAsyncIteratorInterface() + cgThings.append( + CGGeneric(declare="typedef %s NativeType;\n" % descriptor.nativeType) ) - if not isIteratorInterface: + parent = descriptor.interface.parent + if parent: cgThings.append( - CGGeneric(declare="typedef %s NativeType;\n" % descriptor.nativeType) - ) - parent = descriptor.interface.parent - if parent: - cgThings.append( - CGGeneric( - "static_assert(IsRefcounted<NativeType>::value == IsRefcounted<%s::NativeType>::value,\n" - ' "Can\'t inherit from an interface with a different ownership model.");\n' - % toBindingNamespace(descriptor.parentPrototypeName) - ) + CGGeneric( + "static_assert(IsRefcounted<NativeType>::value == IsRefcounted<%s::NativeType>::value,\n" + ' "Can\'t inherit from an interface with a different ownership model.");\n' + % toBindingNamespace(descriptor.parentPrototypeName) ) + ) defaultToJSONMethod = None needCrossOriginPropertyArrays = False @@ -16641,19 +16571,12 @@ class CGDescriptor(CGThing): cgThings.append(CGSerializer(descriptor)) cgThings.append(CGDeserializer(descriptor)) - # CGDOMProxyJSClass/CGDOMJSClass need GetProtoObjectHandle, but we don't want to export it for the iterator interfaces, so declare it here. - if isIteratorInterface: - cgThings.append( - CGGetProtoObjectHandleMethod( - descriptor, static=True, signatureOnly=True - ) - ) - if descriptor.proxy: cgThings.append(CGDOMJSProxyHandlerDefiner(handlerThing)) cgThings.append(CGDOMProxyJSClass(descriptor)) else: cgThings.append(CGDOMJSClass(descriptor)) + cgThings.append(CGGetJSClassMethod(descriptor)) if descriptor.interface.hasMembersInSlots(): cgThings.append(CGUpdateMemberSlotsMethod(descriptor)) @@ -16662,12 +16585,10 @@ class CGDescriptor(CGThing): assert descriptor.wrapperCache cgThings.append(CGWrapGlobalMethod(descriptor, properties)) elif descriptor.wrapperCache: - cgThings.append(CGWrapWithCacheMethod(descriptor)) + cgThings.append(CGWrapWithCacheMethod(descriptor, properties)) cgThings.append(CGWrapMethod(descriptor)) else: - cgThings.append( - CGWrapNonWrapperCacheMethod(descriptor, static=isIteratorInterface) - ) + cgThings.append(CGWrapNonWrapperCacheMethod(descriptor, properties)) # If we're not wrappercached, we don't know how to clear our # cached values, since we can't get at the JSObject. @@ -16726,11 +16647,7 @@ class CGDescriptor(CGThing): # CGDOMJSClass and unscopables, if any. cgThings.append( CGCreateInterfaceObjectsMethod( - descriptor, - properties, - haveUnscopables, - haveLegacyWindowAliases, - static=isIteratorInterface, + descriptor, properties, haveUnscopables, haveLegacyWindowAliases ) ) @@ -16740,11 +16657,8 @@ class CGDescriptor(CGThing): descriptor.interface.hasInterfacePrototypeObject() and not descriptor.hasOrdinaryObjectPrototype ): - cgThings.append( - CGGetProtoObjectHandleMethod(descriptor, static=isIteratorInterface) - ) + cgThings.append(CGGetProtoObjectHandleMethod(descriptor)) if descriptor.interface.hasChildInterfaces(): - assert not isIteratorInterface cgThings.append(CGGetProtoObjectMethod(descriptor)) if descriptor.interface.hasInterfaceObject(): cgThings.append(CGGetConstructorObjectHandleMethod(descriptor)) @@ -16756,10 +16670,9 @@ class CGDescriptor(CGThing): cgThings = CGList((CGIndenter(t, declareOnly=True) for t in cgThings), "\n") cgThings = CGWrapper(cgThings, pre="\n", post="\n") - cgThings = CGWrapper( + self.cgRoot = CGWrapper( CGNamespace(toBindingNamespace(descriptor.name), cgThings), post="\n" ) - self.cgRoot = CGList([iteratorCGThings, cgThings], "\n") def declare(self): return self.cgRoot.declare() @@ -18377,11 +18290,8 @@ class CGBindingRoot(CGThing): bindingDeclareHeaders["mozilla/dom/BindingUtils.h"] = any( d.isObject() for t in unionTypes for d in t.flatMemberTypes ) - bindingHeaders["mozilla/dom/IterableIterator.h"] = any( - ( - d.interface.isIteratorInterface() - and d.interface.maplikeOrSetlikeOrIterable.isPairIterator() - ) + bindingDeclareHeaders["mozilla/dom/IterableIterator.h"] = any( + d.interface.isIteratorInterface() or d.interface.isAsyncIteratorInterface() or d.interface.isIterable() or d.interface.isAsyncIterable() @@ -22280,7 +22190,7 @@ class CGIterableMethodGenerator(CGGeneric): using CGCallGenerator. """ - def __init__(self, descriptor, methodName, args): + def __init__(self, descriptor, iterable, methodName, args): if methodName == "forEach": assert len(args) == 2 @@ -22319,51 +22229,43 @@ class CGIterableMethodGenerator(CGGeneric): return if descriptor.interface.isIterable(): - assert descriptor.interface.maplikeOrSetlikeOrIterable.isPairIterator() assert len(args) == 0 - wrap = f"{descriptor.interface.identifier.name}Iterator_Binding::Wrap" - iterClass = f"mozilla::dom::binding_detail::WrappableIterableIterator<{descriptor.nativeType}, &{wrap}>" + binding = descriptor.interface.identifier.name + "Iterator_Binding" + init = "" else: - needReturnMethod = toStringBool( - descriptor.interface.maplikeOrSetlikeOrIterable.getExtendedAttribute( - "GenerateReturnMethod" - ) - is not None - ) - wrap = f"{descriptor.interface.identifier.name}AsyncIterator_Binding::Wrap" - iterClass = f"mozilla::dom::binding_detail::WrappableAsyncIterableIterator<{descriptor.nativeType}, {needReturnMethod}, &{wrap}>" + assert descriptor.interface.isAsyncIterable() - createIterator = fill( - """ - typedef ${iterClass} itrType; - RefPtr<itrType> result(new itrType(self, - itrType::IteratorType::${itrMethod})); - """, - iterClass=iterClass, - itrMethod=methodName.title(), - ) - - if descriptor.interface.isAsyncIterable(): - args.append("initError") - createIterator = fill( + binding = descriptor.interface.identifier.name + "AsyncIterator_Binding" + init = fill( """ - $*{createIterator} { ErrorResult initError; - self->InitAsyncIteratorData(result->Data(), itrType::IteratorType::${itrMethod}, ${args}); + self->InitAsyncIterator(result.get(), ${args}initError); if (initError.MaybeSetPendingException(cx, "Asynchronous iterator initialization steps for ${ifaceName} failed")) { return false; } } """, - createIterator=createIterator, - itrMethod=methodName.title(), - args=", ".join(args), + args="".join(a + ", " for a in args), ifaceName=descriptor.interface.identifier.name, ) - - CGGeneric.__init__(self, createIterator) + CGGeneric.__init__( + self, + fill( + """ + typedef ${iterClass} itrType; + RefPtr<itrType> result(new itrType(self, + itrType::IteratorType::${itrMethod}, + &${binding}::Wrap)); + $*{init} + """, + iterClass=iteratorNativeType(descriptor), + itrMethod=methodName.title(), + binding=binding, + init=init, + ), + ) def getObservableArrayBackingObject(descriptor, attr, errorReturn="return false;\n"): diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index c1eb524b407f3a15333f2bda3aa76fe0454062ef..dd317fecf6a79d4842ceed3caa749d307150d4d3 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -13,13 +13,6 @@ from collections import defaultdict autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n" -def toStringBool(arg): - """ - Converts IDL/Python Boolean (True/False) to C++ Boolean (true/false) - """ - return str(not not arg).lower() - - class DescriptorProvider: """ A way of getting descriptors for interface names. Subclasses must @@ -764,8 +757,6 @@ class Descriptor(DescriptorProvider): if name in self.implicitJSContext: attrs.append("implicitJSContext") if member.isMethod(): - if self.interface.isAsyncIteratorInterface() and name == "next": - attrs.append("implicitJSContext") # JSObject-returning [NewObject] methods must be fallible, # since they have to (fallibly) allocate the new JSObject. if member.getExtendedAttribute("NewObject"): @@ -1059,16 +1050,7 @@ def iteratorNativeType(descriptor): assert iterableDecl.isPairIterator() or descriptor.interface.isAsyncIterable() if descriptor.interface.isIterable(): return "mozilla::dom::IterableIterator<%s>" % descriptor.nativeType - needReturnMethod = toStringBool( - descriptor.interface.maplikeOrSetlikeOrIterable.getExtendedAttribute( - "GenerateReturnMethod" - ) - is not None - ) - return "mozilla::dom::binding_detail::AsyncIterableIteratorNative<%s, %s>" % ( - descriptor.nativeType, - needReturnMethod, - ) + return "mozilla::dom::AsyncIterableIterator<%s>" % descriptor.nativeType def findInnermostType(t): diff --git a/dom/bindings/IterableIterator.cpp b/dom/bindings/IterableIterator.cpp index e2183865f7e1f3b1029c83b5399e4889a9f571e0..438d581786d15f932c491b521face9c0647e485a 100644 --- a/dom/bindings/IterableIterator.cpp +++ b/dom/bindings/IterableIterator.cpp @@ -5,7 +5,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/IterableIterator.h" -#include "mozilla/dom/Promise-inl.h" namespace mozilla::dom { @@ -16,8 +15,8 @@ namespace mozilla::dom { NS_IMPL_CYCLE_COLLECTION_CLASS(IterableIteratorBase) -NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(IterableIteratorBase, AddRef) -NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(IterableIteratorBase, Release) +NS_IMPL_CYCLE_COLLECTING_ADDREF(IterableIteratorBase) +NS_IMPL_CYCLE_COLLECTING_RELEASE(IterableIteratorBase) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IterableIteratorBase) tmp->TraverseHelper(cb); @@ -27,9 +26,12 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(IterableIteratorBase) tmp->UnlinkHelper(); NS_IMPL_CYCLE_COLLECTION_UNLINK_END -namespace iterator_utils { +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IterableIteratorBase) + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END -void DictReturn(JSContext* aCx, JS::MutableHandle<JS::Value> aResult, +namespace iterator_utils { +void DictReturn(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, bool aDone, JS::Handle<JS::Value> aValue, ErrorResult& aRv) { RootedDictionary<IterableKeyOrValueResult> dict(aCx); dict.mDone = aDone; @@ -39,16 +41,6 @@ void DictReturn(JSContext* aCx, JS::MutableHandle<JS::Value> aResult, aRv.Throw(NS_ERROR_FAILURE); return; } - aResult.set(dictValue); -} - -void DictReturn(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, - bool aDone, JS::Handle<JS::Value> aValue, ErrorResult& aRv) { - JS::Rooted<JS::Value> dictValue(aCx); - DictReturn(aCx, &dictValue, aDone, aValue, aRv); - if (aRv.Failed()) { - return; - } aResult.set(&dictValue.toObject()); } @@ -75,249 +67,43 @@ void KeyAndValueReturn(JSContext* aCx, JS::Handle<JS::Value> aKey, aResult.set(&dictValue.toObject()); } -} // namespace iterator_utils - -namespace binding_detail { - -static already_AddRefed<Promise> PromiseOrErr( - Result<RefPtr<Promise>, nsresult>&& aResult, ErrorResult& aError) { - if (aResult.isErr()) { - aError.Throw(aResult.unwrapErr()); - return nullptr; - } - - return aResult.unwrap().forget(); -} - -already_AddRefed<Promise> AsyncIterableNextImpl::NextSteps( - JSContext* aCx, AsyncIterableIteratorBase* aObject, - nsIGlobalObject* aGlobalObject, ErrorResult& aRv) { - // 2. If object’s is finished is true, then: - if (aObject->mIsFinished) { - // 1. Let result be CreateIterResultObject(undefined, true). - JS::Rooted<JS::Value> dict(aCx); - iterator_utils::DictReturn(aCx, &dict, true, JS::UndefinedHandleValue, aRv); - if (aRv.Failed()) { - return Promise::CreateRejectedWithErrorResult(aGlobalObject, aRv); - } +void ResolvePromiseForFinished(JSContext* aCx, Promise* aPromise, + ErrorResult& aRv) { + MOZ_ASSERT(aPromise); - // 2. Perform ! Call(nextPromiseCapability.[[Resolve]], undefined, - // «result»). - // 3. Return nextPromiseCapability.[[Promise]]. - return Promise::Resolve(aGlobalObject, aCx, dict, aRv); - } - - // 4. Let nextPromise be the result of getting the next iteration result with - // object’s target and object. - RefPtr<Promise> nextPromise = GetNextResult(aRv); - - // 5. Let fulfillSteps be the following steps, given next: - auto fulfillSteps = [](JSContext* aCx, JS::Handle<JS::Value> aNext, - ErrorResult& aRv, - const RefPtr<AsyncIterableIteratorBase>& aObject, - const nsCOMPtr<nsIGlobalObject>& aGlobalObject) - -> already_AddRefed<Promise> { - // 1. Set object’s ongoing promise to null. - aObject->mOngoingPromise = nullptr; - - // 2. If next is end of iteration, then: - JS::Rooted<JS::Value> dict(aCx); - if (aNext.isMagic(binding_details::END_OF_ITERATION)) { - // 1. Set object’s is finished to true. - aObject->mIsFinished = true; - // 2. Return CreateIterResultObject(undefined, true). - iterator_utils::DictReturn(aCx, &dict, true, JS::UndefinedHandleValue, - aRv); - if (aRv.Failed()) { - return nullptr; - } - } else { - // 3. Otherwise, if interface has a pair asynchronously iterable - // declaration: - // 1. Assert: next is a value pair. - // 2. Return the iterator result for next and kind. - // 4. Otherwise: - // 1. Assert: interface has a value asynchronously iterable declaration. - // 2. Assert: next is a value of the type that appears in the - // declaration. - // 3. Let value be next, converted to an ECMAScript value. - // 4. Return CreateIterResultObject(value, false). - iterator_utils::DictReturn(aCx, &dict, false, aNext, aRv); - if (aRv.Failed()) { - return nullptr; - } - } - // Note that ThenCatchWithCycleCollectedArgs expects a Promise, so - // we use Promise::Resolve here. The specs do convert this to a - // promise too at another point, but the end result should be the - // same. - return Promise::Resolve(aGlobalObject, aCx, dict, aRv); - }; - // 7. Let rejectSteps be the following steps, given reason: - auto rejectSteps = [](JSContext* aCx, JS::Handle<JS::Value> aReason, - ErrorResult& aRv, - const RefPtr<AsyncIterableIteratorBase>& aObject, - const nsCOMPtr<nsIGlobalObject>& aGlobalObject) { - // 1. Set object’s ongoing promise to null. - aObject->mOngoingPromise = nullptr; - // 2. Set object’s is finished to true. - aObject->mIsFinished = true; - // 3. Throw reason. - return Promise::Reject(aGlobalObject, aCx, aReason, aRv); - }; - // 9. Perform PerformPromiseThen(nextPromise, onFulfilled, onRejected, - // nextPromiseCapability). - Result<RefPtr<Promise>, nsresult> result = - nextPromise->ThenCatchWithCycleCollectedArgs( - std::move(fulfillSteps), std::move(rejectSteps), RefPtr{aObject}, - nsCOMPtr{aGlobalObject}); - - // 10. Return nextPromiseCapability.[[Promise]]. - return PromiseOrErr(std::move(result), aRv); -} - -already_AddRefed<Promise> AsyncIterableNextImpl::Next( - JSContext* aCx, AsyncIterableIteratorBase* aObject, - nsISupports* aGlobalObject, ErrorResult& aRv) { - nsCOMPtr<nsIGlobalObject> globalObject = do_QueryInterface(aGlobalObject); - - // 3.7.10.2. Asynchronous iterator prototype object - // … - // 10. If ongoingPromise is not null, then: - if (aObject->mOngoingPromise) { - // 1. Let afterOngoingPromiseCapability be - // ! NewPromiseCapability(%Promise%). - // 2. Let onSettled be CreateBuiltinFunction(nextSteps, « »). - - // aObject is the same object as 'this', so it's fine to capture 'this' - // without taking a strong reference, because we already take a strong - // reference to it through aObject. - auto onSettled = [this](JSContext* aCx, JS::Handle<JS::Value> aValue, - ErrorResult& aRv, - const RefPtr<AsyncIterableIteratorBase>& aObject, - const nsCOMPtr<nsIGlobalObject>& aGlobalObject) { - return NextSteps(aCx, aObject, aGlobalObject, aRv); - }; - - // 3. Perform PerformPromiseThen(ongoingPromise, onSettled, onSettled, - // afterOngoingPromiseCapability). - Result<RefPtr<Promise>, nsresult> afterOngoingPromise = - aObject->mOngoingPromise->ThenCatchWithCycleCollectedArgs( - onSettled, onSettled, RefPtr{aObject}, std::move(globalObject)); - if (afterOngoingPromise.isErr()) { - aRv.Throw(afterOngoingPromise.unwrapErr()); - return nullptr; - } - - // 4. Set object’s ongoing promise to - // afterOngoingPromiseCapability.[[Promise]]. - aObject->mOngoingPromise = afterOngoingPromise.unwrap().forget(); - } else { - // 11. Otherwise: - // 1. Set object’s ongoing promise to the result of running nextSteps. - aObject->mOngoingPromise = NextSteps(aCx, aObject, globalObject, aRv); + JS::Rooted<JSObject*> dict(aCx); + DictReturn(aCx, &dict, true, JS::UndefinedHandleValue, aRv); + if (aRv.Failed()) { + return; } - - // 12. Return object’s ongoing promise. - return do_AddRef(aObject->mOngoingPromise); + aPromise->MaybeResolve(dict); } -already_AddRefed<Promise> AsyncIterableReturnImpl::ReturnSteps( - JSContext* aCx, AsyncIterableIteratorBase* aObject, - nsIGlobalObject* aGlobalObject, JS::Handle<JS::Value> aValue, - ErrorResult& aRv) { - // 2. If object’s is finished is true, then: - if (aObject->mIsFinished) { - // 1. Let result be CreateIterResultObject(value, true). - JS::Rooted<JS::Value> dict(aCx); - iterator_utils::DictReturn(aCx, &dict, true, aValue, aRv); - if (aRv.Failed()) { - return Promise::CreateRejectedWithErrorResult(aGlobalObject, aRv); - } +void ResolvePromiseWithKeyOrValue(JSContext* aCx, Promise* aPromise, + JS::Handle<JS::Value> aKeyOrValue, + ErrorResult& aRv) { + MOZ_ASSERT(aPromise); - // 2. Perform ! Call(returnPromiseCapability.[[Resolve]], undefined, - // «result»). - // 3. Return returnPromiseCapability.[[Promise]]. - return Promise::Resolve(aGlobalObject, aCx, dict, aRv); + JS::Rooted<JSObject*> dict(aCx); + DictReturn(aCx, &dict, false, aKeyOrValue, aRv); + if (aRv.Failed()) { + return; } - - // 3. Set object’s is finished to true. - aObject->mIsFinished = true; - - // 4. Return the result of running the asynchronous iterator return algorithm - // for interface, given object’s target, object, and value. - return GetReturnPromise(aCx, aValue, aRv); + aPromise->MaybeResolve(dict); } -already_AddRefed<Promise> AsyncIterableReturnImpl::Return( - JSContext* aCx, AsyncIterableIteratorBase* aObject, - nsISupports* aGlobalObject, JS::Handle<JS::Value> aValue, - ErrorResult& aRv) { - nsCOMPtr<nsIGlobalObject> globalObject = do_QueryInterface(aGlobalObject); +void ResolvePromiseWithKeyAndValue(JSContext* aCx, Promise* aPromise, + JS::Handle<JS::Value> aKey, + JS::Handle<JS::Value> aValue, + ErrorResult& aRv) { + MOZ_ASSERT(aPromise); - // 3.7.10.2. Asynchronous iterator prototype object - // … - RefPtr<Promise> returnStepsPromise; - // 11. If ongoingPromise is not null, then: - if (aObject->mOngoingPromise) { - // 1. Let afterOngoingPromiseCapability be - // ! NewPromiseCapability(%Promise%). - // 2. Let onSettled be CreateBuiltinFunction(returnSteps, « »). - - // aObject is the same object as 'this', so it's fine to capture 'this' - // without taking a strong reference, because we already take a strong - // reference to it through aObject. - auto onSettled = [this](JSContext* aCx, JS::Handle<JS::Value> aValue, - ErrorResult& aRv, - const RefPtr<AsyncIterableIteratorBase>& aObject, - const nsCOMPtr<nsIGlobalObject>& aGlobalObject, - JS::Handle<JS::Value> aVal) { - return ReturnSteps(aCx, aObject, aGlobalObject, aVal, aRv); - }; - - // 3. Perform PerformPromiseThen(ongoingPromise, onSettled, onSettled, - // afterOngoingPromiseCapability). - Result<RefPtr<Promise>, nsresult> afterOngoingPromise = - aObject->mOngoingPromise->ThenCatchWithCycleCollectedArgsJS( - onSettled, onSettled, - std::make_tuple(RefPtr{aObject}, nsCOMPtr{globalObject}), - std::make_tuple(aValue)); - if (afterOngoingPromise.isErr()) { - aRv.Throw(afterOngoingPromise.unwrapErr()); - return nullptr; - } - - // 4. Set returnStepsPromise to afterOngoingPromiseCapability.[[Promise]]. - returnStepsPromise = afterOngoingPromise.unwrap().forget(); - } else { - // 12. Otherwise: - // 1. Set returnStepsPromise to the result of running returnSteps. - returnStepsPromise = ReturnSteps(aCx, aObject, globalObject, aValue, aRv); + JS::Rooted<JSObject*> dict(aCx); + KeyAndValueReturn(aCx, aKey, aValue, &dict, aRv); + if (aRv.Failed()) { + return; } - - // 13. Let fulfillSteps be the following steps: - auto onFullFilled = [](JSContext* aCx, JS::Handle<JS::Value>, - ErrorResult& aRv, - const nsCOMPtr<nsIGlobalObject>& aGlobalObject, - JS::Handle<JS::Value> aVal) { - // 1. Return CreateIterResultObject(value, true). - JS::Rooted<JS::Value> dict(aCx); - iterator_utils::DictReturn(aCx, &dict, true, aVal, aRv); - return Promise::Resolve(aGlobalObject, aCx, dict, aRv); - }; - - // 14. Let onFulfilled be CreateBuiltinFunction(fulfillSteps, « »). - // 15. Perform PerformPromiseThen(returnStepsPromise, onFulfilled, undefined, - // returnPromiseCapability). - Result<RefPtr<Promise>, nsresult> returnPromise = - returnStepsPromise->ThenWithCycleCollectedArgsJS( - onFullFilled, std::make_tuple(std::move(globalObject)), - std::make_tuple(aValue)); - - // 16. Return returnPromiseCapability.[[Promise]]. - return PromiseOrErr(std::move(returnPromise), aRv); + aPromise->MaybeResolve(dict); } - -} // namespace binding_detail - +} // namespace iterator_utils } // namespace mozilla::dom diff --git a/dom/bindings/IterableIterator.h b/dom/bindings/IterableIterator.h index 2ca32750f3d6bbb4bf50de2ef1cbd66c616cbfeb..2534fbbecc88d382360e1895a7aa7fd0e1eb6b77 100644 --- a/dom/bindings/IterableIterator.h +++ b/dom/bindings/IterableIterator.h @@ -31,7 +31,6 @@ #include "js/TypeDecls.h" #include "js/Value.h" #include "nsISupports.h" -#include "mozilla/AlreadyAddRefed.h" #include "mozilla/dom/IterableIteratorBinding.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/RootedDictionary.h" @@ -40,19 +39,7 @@ namespace mozilla::dom { -namespace binding_details { - -// JS::MagicValue(END_OF_ITERATION) is the value we use for -// https://webidl.spec.whatwg.org/#end-of-iteration. It shouldn't be returned to -// JS, because AsyncIterableIteratorBase::NextSteps will detect it and will -// return the result of CreateIterResultObject(undefined, true) instead -// (discarding the magic value). -static const JSWhyMagic END_OF_ITERATION = JS_GENERIC_MAGIC; - -} // namespace binding_details - namespace iterator_utils { - void DictReturn(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, bool aDone, JS::Handle<JS::Value> aValue, ErrorResult& aRv); @@ -60,23 +47,23 @@ void KeyAndValueReturn(JSContext* aCx, JS::Handle<JS::Value> aKey, JS::Handle<JS::Value> aValue, JS::MutableHandle<JSObject*> aResult, ErrorResult& aRv); -inline void ResolvePromiseForFinished(Promise* aPromise) { - aPromise->MaybeResolve(JS::MagicValue(binding_details::END_OF_ITERATION)); -} +void ResolvePromiseForFinished(JSContext* aCx, Promise* aPromise, + ErrorResult& aRv); -template <typename Key, typename Value> -void ResolvePromiseWithKeyAndValue(Promise* aPromise, const Key& aKey, - const Value& aValue) { - aPromise->MaybeResolve(MakeTuple(aKey, aValue)); -} +void ResolvePromiseWithKeyOrValue(JSContext* aCx, Promise* aPromise, + JS::Handle<JS::Value> aKeyOrValue, + ErrorResult& aRv); +void ResolvePromiseWithKeyAndValue(JSContext* aCx, Promise* aPromise, + JS::Handle<JS::Value> aKey, + JS::Handle<JS::Value> aValue, + ErrorResult& aRv); } // namespace iterator_utils -class IterableIteratorBase { +class IterableIteratorBase : public nsISupports { public: - NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(IterableIteratorBase) - NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(IterableIteratorBase) - + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(IterableIteratorBase) typedef enum { Keys = 0, Values, Entries } IteratorType; IterableIteratorBase() = default; @@ -127,11 +114,20 @@ bool CallIterableGetter(JSContext* aCx, } template <typename T> -class IterableIterator : public IterableIteratorBase { +class IterableIterator final : public IterableIteratorBase { public: - IterableIterator(T* aIterableObj, IteratorType aIteratorType) - : mIterableObj(aIterableObj), mIteratorType(aIteratorType), mIndex(0) { + typedef bool (*WrapFunc)(JSContext* aCx, IterableIterator<T>* aObject, + JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aReflector); + + explicit IterableIterator(T* aIterableObj, IteratorType aIteratorType, + WrapFunc aWrapFunc) + : mIterableObj(aIterableObj), + mIteratorType(aIteratorType), + mWrapFunc(aWrapFunc), + mIndex(0) { MOZ_ASSERT(mIterableObj); + MOZ_ASSERT(mWrapFunc); } bool GetKeyAtIndex(JSContext* aCx, uint32_t aIndex, @@ -189,6 +185,11 @@ class IterableIterator : public IterableIteratorBase { ++mIndex; } + bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aObj) { + return (*mWrapFunc)(aCx, this, aGivenProto, aObj); + } + protected: virtual ~IterableIterator() = default; @@ -205,215 +206,85 @@ class IterableIterator : public IterableIteratorBase { RefPtr<T> mIterableObj; // Tells whether this is a key, value, or entries iterator. IteratorType mIteratorType; + // Function pointer to binding-type-specific Wrap() call for this iterator. + WrapFunc mWrapFunc; // Current index of iteration. uint32_t mIndex; }; -namespace binding_detail { - -class AsyncIterableNextImpl; -class AsyncIterableReturnImpl; - -} // namespace binding_detail - -class AsyncIterableIteratorBase : public IterableIteratorBase { +template <typename T> +class AsyncIterableIterator final : public IterableIteratorBase, + public SupportsWeakPtr { public: - IteratorType GetIteratorType() { return mIteratorType; } + typedef bool (*WrapFunc)(JSContext* aCx, AsyncIterableIterator<T>* aObject, + JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aReflector); + + explicit AsyncIterableIterator(T* aIterableObj, IteratorType aIteratorType, + WrapFunc aWrapFunc) + : mIterableObj(aIterableObj), + mIteratorType(aIteratorType), + mWrapFunc(aWrapFunc) { + MOZ_ASSERT(mIterableObj); + MOZ_ASSERT(mWrapFunc); + } - protected: - explicit AsyncIterableIteratorBase(IteratorType aIteratorType) - : mIteratorType(aIteratorType) {} + void SetData(void* aData) { mData = aData; } - private: - friend class binding_detail::AsyncIterableNextImpl; - friend class binding_detail::AsyncIterableReturnImpl; + void* GetData() { return mData; } - // 3.7.10.1. Default asynchronous iterator objects - // Target is in AsyncIterableIterator - // Kind - IteratorType mIteratorType; - // Ongoing promise - RefPtr<Promise> mOngoingPromise; - // Is finished - bool mIsFinished = false; -}; - -template <typename T> -class AsyncIterableIterator : public AsyncIterableIteratorBase { - private: - using IteratorData = typename T::IteratorData; + IteratorType GetIteratorType() { return mIteratorType; } - public: - AsyncIterableIterator(T* aIterableObj, IteratorType aIteratorType) - : AsyncIterableIteratorBase(aIteratorType), mIterableObj(aIterableObj) { - MOZ_ASSERT(mIterableObj); + void Next(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, + ErrorResult& aRv) { + RefPtr<Promise> promise = mIterableObj->GetNextPromise(aCx, this, aRv); + if (!promise) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + aResult.set(promise->PromiseObj()); } - IteratorData& Data() { return mData; } - - protected: - // We'd prefer to use ImplCycleCollectionTraverse/ImplCycleCollectionUnlink on - // the iterator data, but unfortunately that doesn't work because it's - // dependent on the template parameter. Instead we detect if the data - // structure has Traverse and Unlink functions and call those. - template <typename Data> - auto TraverseData(Data& aData, nsCycleCollectionTraversalCallback& aCallback, - int) -> decltype(aData.Traverse(aCallback)) { - return aData.Traverse(aCallback); + bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, + JS::MutableHandle<JSObject*> aObj) { + return (*mWrapFunc)(aCx, this, aGivenProto, aObj); } - template <typename Data> - void TraverseData(Data& aData, nsCycleCollectionTraversalCallback& aCallback, - double) {} - template <typename Data> - auto UnlinkData(Data& aData, int) -> decltype(aData.Unlink()) { - return aData.Unlink(); + protected: + virtual ~AsyncIterableIterator() { + // As long as iterable object does not hold strong ref to its iterators, + // iterators will not be added to CC graph, thus make sure + // DestroyAsyncIterator still take place. + if (mIterableObj) { + mIterableObj->DestroyAsyncIterator(this); + } } - template <typename Data> - void UnlinkData(Data& aData, double) {} // Since we're templated on a binding, we need to possibly CC it, but can't do // that through macros. So it happens here. + // DestroyAsyncIterator is expected to assume that its AsyncIterableIterator + // does not need access to mData anymore. AsyncIterator does not manage mData + // so it should be release and null out explicitly. void UnlinkHelper() final { - AsyncIterableIterator<T>* tmp = this; - NS_IMPL_CYCLE_COLLECTION_UNLINK(mIterableObj); - UnlinkData(tmp->mData, 0); + mIterableObj->DestroyAsyncIterator(this); + mIterableObj = nullptr; } virtual void TraverseHelper(nsCycleCollectionTraversalCallback& cb) override { AsyncIterableIterator<T>* tmp = this; NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIterableObj); - TraverseData(tmp->mData, cb, 0); } - // 3.7.10.1. Default asynchronous iterator objects - // Target + // Binding Implementation object that we're iterating over. RefPtr<T> mIterableObj; - // Kind - // Ongoing promise - // Is finished - // See AsyncIterableIteratorBase - + // Tells whether this is a key, value, or entries iterator. + IteratorType mIteratorType; + // Function pointer to binding-type-specific Wrap() call for this iterator. + WrapFunc mWrapFunc; // Opaque data of the backing object. - IteratorData mData; + void* mData{nullptr}; }; -namespace binding_detail { - -template <typename T> -using IterableIteratorWrapFunc = - bool (*)(JSContext* aCx, IterableIterator<T>* aObject, - JS::MutableHandle<JSObject*> aReflector); - -template <typename T, IterableIteratorWrapFunc<T> WrapFunc> -class WrappableIterableIterator final : public IterableIterator<T> { - public: - using IterableIterator<T>::IterableIterator; - - bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, - JS::MutableHandle<JSObject*> aObj) { - MOZ_ASSERT(!aGivenProto); - return (*WrapFunc)(aCx, this, aObj); - } -}; - -class AsyncIterableNextImpl { - protected: - already_AddRefed<Promise> Next(JSContext* aCx, - AsyncIterableIteratorBase* aObject, - nsISupports* aGlobalObject, ErrorResult& aRv); - virtual already_AddRefed<Promise> GetNextResult(ErrorResult& aRv) = 0; - - private: - already_AddRefed<Promise> NextSteps(JSContext* aCx, - AsyncIterableIteratorBase* aObject, - nsIGlobalObject* aGlobalObject, - ErrorResult& aRv); -}; - -class AsyncIterableReturnImpl { - protected: - already_AddRefed<Promise> Return(JSContext* aCx, - AsyncIterableIteratorBase* aObject, - nsISupports* aGlobalObject, - JS::Handle<JS::Value> aValue, - ErrorResult& aRv); - virtual already_AddRefed<Promise> GetReturnPromise( - JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv) = 0; - - private: - already_AddRefed<Promise> ReturnSteps(JSContext* aCx, - AsyncIterableIteratorBase* aObject, - nsIGlobalObject* aGlobalObject, - JS::Handle<JS::Value> aValue, - ErrorResult& aRv); -}; - -template <typename T> -class AsyncIterableIteratorNoReturn : public AsyncIterableIterator<T>, - public AsyncIterableNextImpl { - public: - using AsyncIterableIterator<T>::AsyncIterableIterator; - - already_AddRefed<Promise> Next(JSContext* aCx, ErrorResult& aRv) { - return AsyncIterableNextImpl::Next( - aCx, this, this->mIterableObj->GetParentObject(), aRv); - } - - protected: - already_AddRefed<Promise> GetNextResult(ErrorResult& aRv) override { - return this->mIterableObj->GetNextIterationResult( - static_cast<AsyncIterableIterator<T>*>(this), aRv); - } -}; - -template <typename T> -class AsyncIterableIteratorWithReturn : public AsyncIterableIteratorNoReturn<T>, - public AsyncIterableReturnImpl { - public: - already_AddRefed<Promise> Return(JSContext* aCx, JS::Handle<JS::Value> aValue, - ErrorResult& aRv) { - return AsyncIterableReturnImpl::Return( - aCx, this, this->mIterableObj->GetParentObject(), aValue, aRv); - } - - protected: - using AsyncIterableIteratorNoReturn<T>::AsyncIterableIteratorNoReturn; - - already_AddRefed<Promise> GetReturnPromise(JSContext* aCx, - JS::Handle<JS::Value> aValue, - ErrorResult& aRv) override { - return this->mIterableObj->IteratorReturn( - aCx, static_cast<AsyncIterableIterator<T>*>(this), aValue, aRv); - } -}; - -template <typename T, bool NeedReturnMethod> -using AsyncIterableIteratorNative = - std::conditional_t<NeedReturnMethod, AsyncIterableIteratorWithReturn<T>, - AsyncIterableIteratorNoReturn<T>>; - -template <typename T, bool NeedReturnMethod> -using AsyncIterableIteratorWrapFunc = bool (*)( - JSContext* aCx, AsyncIterableIteratorNative<T, NeedReturnMethod>* aObject, - JS::MutableHandle<JSObject*> aReflector); - -template <typename T, bool NeedReturnMethod, - AsyncIterableIteratorWrapFunc<T, NeedReturnMethod> WrapFunc, - typename Base = AsyncIterableIteratorNative<T, NeedReturnMethod>> -class WrappableAsyncIterableIterator final : public Base { - public: - using Base::Base; - - bool WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto, - JS::MutableHandle<JSObject*> aObj) { - MOZ_ASSERT(!aGivenProto); - return (*WrapFunc)(aCx, this, aObj); - } -}; - -} // namespace binding_detail - } // namespace mozilla::dom #endif // mozilla_dom_IterableIterator_h diff --git a/dom/bindings/ToJSValue.h b/dom/bindings/ToJSValue.h index 4655993578b9d1edfb3794c4ed9ca240e0e39648..21173051739996dc89fb75824d3b89a756204937 100644 --- a/dom/bindings/ToJSValue.h +++ b/dom/bindings/ToJSValue.h @@ -406,34 +406,6 @@ template <typename T> return true; } -// Accept tuple of other things we accept. The result will be a JS array object. -template <typename... Elements> -[[nodiscard]] bool ToJSValue(JSContext* aCx, - const Tuple<Elements...>& aArguments, - JS::MutableHandle<JS::Value> aValue) { - // Make sure we're called in a compartment - MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx)); - - JS::RootedVector<JS::Value> v(aCx); - if (!v.resize(sizeof...(Elements))) { - return false; - } - bool ok = true; - size_t i = 0; - ForEach(aArguments, [aCx, &ok, &v, &i](auto& aElem) { - ok = ok && ToJSValue(aCx, aElem, v[i++]); - }); - if (!ok) { - return false; - } - JSObject* arrayObj = JS::NewArrayObject(aCx, v); - if (!arrayObj) { - return false; - } - aValue.setObject(*arrayObj); - return true; -} - // Accept records of other things we accept. N.B. This assumes that // keys are either UTF-8 or UTF-16-ish. See Bug 1706058. template <typename K, typename V> diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index ddfce6488bf10ba2f71240608bf6d0083dfbb89a..c6581ef2249c60aa5a10470028b81ff829fe9fec 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -8886,6 +8886,7 @@ class Parser(Tokenizer): if isinstance(p, IDLInterface): interfaceStatements.append(p) + iterableIteratorIface = None for iface in interfaceStatements: iterable = None # We haven't run finish() on the interface yet, so we don't know @@ -8901,46 +8902,13 @@ class Parser(Tokenizer): def simpleExtendedAttr(str): return IDLExtendedAttribute(iface.location, (str,)) - if isinstance(iterable, IDLAsyncIterable): - nextReturnType = IDLPromiseType( - iterable.location, BuiltinTypes[IDLBuiltinType.Types.any] - ) - else: - nextReturnType = BuiltinTypes[IDLBuiltinType.Types.object] nextMethod = IDLMethod( - iterable.location, - IDLUnresolvedIdentifier(iterable.location, "next"), - nextReturnType, + iface.location, + IDLUnresolvedIdentifier(iface.location, "next"), + BuiltinTypes[IDLBuiltinType.Types.object], [], ) nextMethod.addExtendedAttributes([simpleExtendedAttr("Throws")]) - - methods = [nextMethod] - - if iterable.getExtendedAttribute("GenerateReturnMethod"): - assert isinstance(iterable, IDLAsyncIterable) - - returnMethod = IDLMethod( - iterable.location, - IDLUnresolvedIdentifier(iterable.location, "return"), - IDLPromiseType( - iterable.location, BuiltinTypes[IDLBuiltinType.Types.any] - ), - [ - IDLArgument( - iterable.location, - IDLUnresolvedIdentifier( - BuiltinLocation("<auto-generated-identifier>"), - "value", - ), - BuiltinTypes[IDLBuiltinType.Types.any], - optional=True, - ), - ], - ) - returnMethod.addExtendedAttributes([simpleExtendedAttr("Throws")]) - methods.append(returnMethod) - if iterable.isIterable(): itr_suffix = "Iterator" else: @@ -8957,7 +8925,7 @@ class Parser(Tokenizer): self.globalScope(), itr_ident, None, - methods, + [nextMethod], isKnownNonPartial=True, classNameOverride=classNameOverride, ) diff --git a/dom/bindings/test/TestInterfaceAsyncIterableDouble.cpp b/dom/bindings/test/TestInterfaceAsyncIterableDouble.cpp index a0ec0d64f0914840c85f72ba61a253edd7986d36..c47bcb5aa299ba96d645d80dfe30f1a453cc206d 100644 --- a/dom/bindings/test/TestInterfaceAsyncIterableDouble.cpp +++ b/dom/bindings/test/TestInterfaceAsyncIterableDouble.cpp @@ -54,44 +54,73 @@ nsPIDOMWindowInner* TestInterfaceAsyncIterableDouble::GetParentObject() const { return mParent; } -already_AddRefed<Promise> -TestInterfaceAsyncIterableDouble::GetNextIterationResult(Iterator* aIterator, - ErrorResult& aRv) { +void TestInterfaceAsyncIterableDouble::InitAsyncIterator(Iterator* aIterator, + ErrorResult& aError) { + UniquePtr<IteratorData> data(new IteratorData(0)); + aIterator->SetData((void*)data.release()); +} + +void TestInterfaceAsyncIterableDouble::DestroyAsyncIterator( + Iterator* aIterator) { + auto* data = reinterpret_cast<IteratorData*>(aIterator->GetData()); + delete data; +} + +already_AddRefed<Promise> TestInterfaceAsyncIterableDouble::GetNextPromise( + JSContext* aCx, Iterator* aIterator, ErrorResult& aRv) { RefPtr<Promise> promise = Promise::Create(mParent->AsGlobal(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } - NS_DispatchToMainThread(NewRunnableMethod<RefPtr<Iterator>, RefPtr<Promise>>( - "TestInterfaceAsyncIterableDouble::GetNextIterationResult", this, - &TestInterfaceAsyncIterableDouble::ResolvePromise, aIterator, promise)); + auto* data = reinterpret_cast<IteratorData*>(aIterator->GetData()); + data->mPromise = promise; + + IterableIteratorBase::IteratorType type = aIterator->GetIteratorType(); + NS_DispatchToMainThread(NS_NewRunnableFunction( + "TestInterfaceAsyncIterableDouble::GetNextPromise", + [data, type, self = RefPtr{this}] { self->ResolvePromise(data, type); })); return promise.forget(); } -void TestInterfaceAsyncIterableDouble::ResolvePromise(Iterator* aIterator, - Promise* aPromise) { - IteratorData& data = aIterator->Data(); +void TestInterfaceAsyncIterableDouble::ResolvePromise( + IteratorData* aData, IterableIteratorBase::IteratorType aType) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(mParent))) { + return; + } + JSContext* cx = jsapi.cx(); + ErrorResult rv; // Test data: ['a', 'b'], ['c', 'd'], ['e', 'f'] - uint32_t idx = data.mIndex; + uint32_t idx = aData->mIndex; if (idx >= mValues.Length()) { - iterator_utils::ResolvePromiseForFinished(aPromise); + iterator_utils::ResolvePromiseForFinished(cx, aData->mPromise, rv); } else { - switch (aIterator->GetIteratorType()) { + JS::Rooted<JS::Value> key(cx); + JS::Rooted<JS::Value> value(cx); + switch (aType) { case IterableIteratorBase::IteratorType::Keys: - aPromise->MaybeResolve(mValues[idx].first); + Unused << ToJSValue(cx, mValues[idx].first, &key); + iterator_utils::ResolvePromiseWithKeyOrValue(cx, aData->mPromise, key, + rv); break; case IterableIteratorBase::IteratorType::Values: - aPromise->MaybeResolve(mValues[idx].second); + Unused << ToJSValue(cx, mValues[idx].second, &value); + iterator_utils::ResolvePromiseWithKeyOrValue(cx, aData->mPromise, value, + rv); break; case IterableIteratorBase::IteratorType::Entries: - iterator_utils::ResolvePromiseWithKeyAndValue( - aPromise, mValues[idx].first, mValues[idx].second); + Unused << ToJSValue(cx, mValues[idx].first, &key); + Unused << ToJSValue(cx, mValues[idx].second, &value); + iterator_utils::ResolvePromiseWithKeyAndValue(cx, aData->mPromise, key, + value, rv); break; } - data.mIndex++; + aData->mIndex++; + aData->mPromise = nullptr; } } diff --git a/dom/bindings/test/TestInterfaceAsyncIterableDouble.h b/dom/bindings/test/TestInterfaceAsyncIterableDouble.h index 4b458617dc677017a03f14a8d146777a183dcf3d..cbf9e19ad621a94bab52d170e7d8bba975d67be1 100644 --- a/dom/bindings/test/TestInterfaceAsyncIterableDouble.h +++ b/dom/bindings/test/TestInterfaceAsyncIterableDouble.h @@ -38,21 +38,27 @@ class TestInterfaceAsyncIterableDouble final : public nsISupports, static already_AddRefed<TestInterfaceAsyncIterableDouble> Constructor( const GlobalObject& aGlobal, ErrorResult& rv); - struct IteratorData { - uint32_t mIndex = 0; - }; - using Iterator = AsyncIterableIterator<TestInterfaceAsyncIterableDouble>; - - void InitAsyncIteratorData(IteratorData& aData, Iterator::IteratorType aType, - ErrorResult& aError) {} - - already_AddRefed<Promise> GetNextIterationResult(Iterator* aIterator, - ErrorResult& aRv); + void InitAsyncIterator(Iterator* aIterator, ErrorResult& aError); + void DestroyAsyncIterator(Iterator* aIterator); + already_AddRefed<Promise> GetNextPromise(JSContext* aCx, Iterator* aIterator, + ErrorResult& aRv); private: + struct IteratorData { + explicit IteratorData(int32_t aIndex) : mIndex(aIndex) {} + ~IteratorData() { + if (mPromise) { + mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + mPromise = nullptr; + } + } + RefPtr<Promise> mPromise; + uint32_t mIndex; + }; virtual ~TestInterfaceAsyncIterableDouble() = default; - void ResolvePromise(Iterator* aIterator, Promise* aPromise); + void ResolvePromise(IteratorData* aData, + IterableIteratorBase::IteratorType aType); nsCOMPtr<nsPIDOMWindowInner> mParent; nsTArray<std::pair<nsString, nsString>> mValues; diff --git a/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.cpp b/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.cpp index 300574d7d70f0c21c6384f3b733b31decf7be1b2..c001aa7da56dd38130e7684d206526cadb429ab2 100644 --- a/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.cpp +++ b/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.cpp @@ -60,46 +60,74 @@ nsPIDOMWindowInner* TestInterfaceAsyncIterableDoubleUnion::GetParentObject() return mParent; } -already_AddRefed<Promise> -TestInterfaceAsyncIterableDoubleUnion::GetNextIterationResult( - Iterator* aIterator, ErrorResult& aRv) { +void TestInterfaceAsyncIterableDoubleUnion::InitAsyncIterator( + Iterator* aIterator, ErrorResult& aError) { + UniquePtr<IteratorData> data(new IteratorData(0)); + aIterator->SetData((void*)data.release()); +} + +void TestInterfaceAsyncIterableDoubleUnion::DestroyAsyncIterator( + Iterator* aIterator) { + auto* data = reinterpret_cast<IteratorData*>(aIterator->GetData()); + delete data; +} + +already_AddRefed<Promise> TestInterfaceAsyncIterableDoubleUnion::GetNextPromise( + JSContext* aCx, Iterator* aIterator, ErrorResult& aRv) { RefPtr<Promise> promise = Promise::Create(mParent->AsGlobal(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } - NS_DispatchToMainThread(NewRunnableMethod<RefPtr<Iterator>, RefPtr<Promise>>( - "TestInterfaceAsyncIterableDoubleUnion::GetNextIterationResult", this, - &TestInterfaceAsyncIterableDoubleUnion::ResolvePromise, aIterator, - promise)); + auto* data = reinterpret_cast<IteratorData*>(aIterator->GetData()); + data->mPromise = promise; + + IterableIteratorBase::IteratorType type = aIterator->GetIteratorType(); + NS_DispatchToMainThread(NS_NewRunnableFunction( + "TestInterfaceAsyncIterableDoubleUnion::GetNextPromise", + [data, type, self = RefPtr{this}] { self->ResolvePromise(data, type); })); return promise.forget(); } -void TestInterfaceAsyncIterableDoubleUnion::ResolvePromise(Iterator* aIterator, - Promise* aPromise) { - IteratorData& data = aIterator->Data(); +void TestInterfaceAsyncIterableDoubleUnion::ResolvePromise( + IteratorData* aData, IterableIteratorBase::IteratorType aType) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(mParent))) { + return; + } + JSContext* cx = jsapi.cx(); + ErrorResult rv; // Test data: // [long, 1], [string, "a"] - uint32_t idx = data.mIndex; + uint32_t idx = aData->mIndex; if (idx >= mValues.Length()) { - iterator_utils::ResolvePromiseForFinished(aPromise); + iterator_utils::ResolvePromiseForFinished(cx, aData->mPromise, rv); } else { - switch (aIterator->GetIteratorType()) { + JS::Rooted<JS::Value> key(cx); + JS::Rooted<JS::Value> value(cx); + switch (aType) { case IterableIteratorBase::IteratorType::Keys: - aPromise->MaybeResolve(mValues[idx].first); + Unused << ToJSValue(cx, mValues[idx].first, &key); + iterator_utils::ResolvePromiseWithKeyOrValue(cx, aData->mPromise, key, + rv); break; case IterableIteratorBase::IteratorType::Values: - aPromise->MaybeResolve(mValues[idx].second); + Unused << ToJSValue(cx, mValues[idx].second, &value); + iterator_utils::ResolvePromiseWithKeyOrValue(cx, aData->mPromise, value, + rv); break; case IterableIteratorBase::IteratorType::Entries: - iterator_utils::ResolvePromiseWithKeyAndValue( - aPromise, mValues[idx].first, mValues[idx].second); + Unused << ToJSValue(cx, mValues[idx].first, &key); + Unused << ToJSValue(cx, mValues[idx].second, &value); + iterator_utils::ResolvePromiseWithKeyAndValue(cx, aData->mPromise, key, + value, rv); break; } - data.mIndex++; + aData->mIndex++; + aData->mPromise = nullptr; } } diff --git a/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.h b/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.h index 902c99b1a91e649df4dc13d05d07691b4d2d1716..d3e34f3ece0a40013639ef8ed59b1633ae4ac855 100644 --- a/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.h +++ b/dom/bindings/test/TestInterfaceAsyncIterableDoubleUnion.h @@ -38,21 +38,28 @@ class TestInterfaceAsyncIterableDoubleUnion final : public nsISupports, static already_AddRefed<TestInterfaceAsyncIterableDoubleUnion> Constructor( const GlobalObject& aGlobal, ErrorResult& rv); - struct IteratorData { - uint32_t mIndex = 0; - }; - using Iterator = AsyncIterableIterator<TestInterfaceAsyncIterableDoubleUnion>; - - void InitAsyncIteratorData(IteratorData& aData, Iterator::IteratorType aType, - ErrorResult& aError) {} - - already_AddRefed<Promise> GetNextIterationResult(Iterator* aIterator, - ErrorResult& aRv); + void InitAsyncIterator(Iterator* aIterator, ErrorResult& aError); + void DestroyAsyncIterator(Iterator* aIterator); + already_AddRefed<Promise> GetNextPromise(JSContext* aCx, Iterator* aIterator, + ErrorResult& aRv); private: + struct IteratorData { + explicit IteratorData(int32_t aIndex) : mIndex(aIndex) {} + ~IteratorData() { + if (mPromise) { + mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + mPromise = nullptr; + } + } + RefPtr<Promise> mPromise; + uint32_t mIndex; + }; + virtual ~TestInterfaceAsyncIterableDoubleUnion() = default; - void ResolvePromise(Iterator* aIterator, Promise* aPromise); + void ResolvePromise(IteratorData* aData, + IterableIteratorBase::IteratorType aType); nsCOMPtr<nsPIDOMWindowInner> mParent; nsTArray<std::pair<nsString, OwningStringOrLong>> mValues; diff --git a/dom/bindings/test/TestInterfaceAsyncIterableSingle.cpp b/dom/bindings/test/TestInterfaceAsyncIterableSingle.cpp index 5c77ef868250f32f2ae631f0e2dc892eae3f0860..2baa9286da4465b2c39dfe271814e5e37b6cf187 100644 --- a/dom/bindings/test/TestInterfaceAsyncIterableSingle.cpp +++ b/dom/bindings/test/TestInterfaceAsyncIterableSingle.cpp @@ -9,8 +9,6 @@ #include "nsPIDOMWindow.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/IterableIterator.h" -#include "mozilla/dom/Promise-inl.h" -#include "nsThreadUtils.h" namespace mozilla::dom { @@ -54,75 +52,68 @@ nsPIDOMWindowInner* TestInterfaceAsyncIterableSingle::GetParentObject() const { return mParent; } -void TestInterfaceAsyncIterableSingle::InitAsyncIteratorData( - IteratorData& aData, Iterator::IteratorType aType, ErrorResult& aError) { +void TestInterfaceAsyncIterableSingle::InitAsyncIterator(Iterator* aIterator, + ErrorResult& aError) { if (mFailToInit) { aError.ThrowTypeError("Caller asked us to fail"); return; } - // Nothing else to do. - MOZ_ASSERT(aData.mIndex == 0); - MOZ_ASSERT(aData.mMultiplier == 1); + UniquePtr<IteratorData> data(new IteratorData(0, 1)); + aIterator->SetData((void*)data.release()); } -already_AddRefed<Promise> -TestInterfaceAsyncIterableSingle::GetNextIterationResult(Iterator* aIterator, - ErrorResult& aRv) { - return GetNextIterationResult(aIterator, aIterator->Data(), aRv); +void TestInterfaceAsyncIterableSingle::DestroyAsyncIterator( + Iterator* aIterator) { + auto* data = reinterpret_cast<IteratorData*>(aIterator->GetData()); + delete data; } -already_AddRefed<Promise> -TestInterfaceAsyncIterableSingle::GetNextIterationResult( - IterableIteratorBase* aIterator, IteratorData& aData, ErrorResult& aRv) { +already_AddRefed<Promise> TestInterfaceAsyncIterableSingle::GetNextPromise( + JSContext* aCx, Iterator* aIterator, ErrorResult& aRv) { + return GetNextPromise(aCx, aIterator, + reinterpret_cast<IteratorData*>(aIterator->GetData()), + aRv); +} + +already_AddRefed<Promise> TestInterfaceAsyncIterableSingle::GetNextPromise( + JSContext* aCx, IterableIteratorBase* aIterator, IteratorData* aData, + ErrorResult& aRv) { RefPtr<Promise> promise = Promise::Create(mParent->AsGlobal(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } + aData->mPromise = promise; - nsCOMPtr<nsIRunnable> callResolvePromise = - NewRunnableMethod<RefPtr<IterableIteratorBase>, IteratorData&, - RefPtr<Promise>>( - "TestInterfaceAsyncIterableSingle::GetNextIterationResult", this, - &TestInterfaceAsyncIterableSingle::ResolvePromise, aIterator, aData, - promise); - if (aData.mBlockingPromisesIndex < aData.mBlockingPromises.Length()) { - aData.mBlockingPromises[aData.mBlockingPromisesIndex] - ->AddCallbacksWithCycleCollectedArgs( - [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv, - nsIRunnable* aCallResolvePromise) { - NS_DispatchToMainThread(aCallResolvePromise); - }, - [](JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv, - nsIRunnable* aCallResolvePromise) {}, - std::move(callResolvePromise)); - ++aData.mBlockingPromisesIndex; - } else { - NS_DispatchToMainThread(callResolvePromise); - } + NS_DispatchToMainThread(NS_NewRunnableFunction( + "TestInterfaceAsyncIterableSingle::GetNextPromise", + [iterator = RefPtr{aIterator}, aData, self = RefPtr{this}] { + self->ResolvePromise(iterator, aData); + })); return promise.forget(); } void TestInterfaceAsyncIterableSingle::ResolvePromise( - IterableIteratorBase* aIterator, IteratorData& aData, Promise* aPromise) { - if (aData.mIndex >= 10) { - iterator_utils::ResolvePromiseForFinished(aPromise); + IterableIteratorBase* aIterator, IteratorData* aData) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(mParent))) { + return; + } + JSContext* cx = jsapi.cx(); + ErrorResult rv; + if (aData->mIndex >= 10) { + iterator_utils::ResolvePromiseForFinished(cx, aData->mPromise, rv); } else { - aPromise->MaybeResolve(int32_t(aData.mIndex * 9 % 7 * aData.mMultiplier)); + JS::Rooted<JS::Value> value(cx); + Unused << ToJSValue( + cx, (int32_t)(aData->mIndex * 9 % 7 * aData->mMultiplier), &value); + iterator_utils::ResolvePromiseWithKeyOrValue(cx, aData->mPromise, value, + rv); - aData.mIndex++; + aData->mIndex++; } -} - -void TestInterfaceAsyncIterableSingle::IteratorData::Traverse( - nsCycleCollectionTraversalCallback& cb) { - TestInterfaceAsyncIterableSingle::IteratorData* tmp = this; - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBlockingPromises); -} -void TestInterfaceAsyncIterableSingle::IteratorData::Unlink() { - TestInterfaceAsyncIterableSingle::IteratorData* tmp = this; - NS_IMPL_CYCLE_COLLECTION_UNLINK(mBlockingPromises); + aData->mPromise = nullptr; } } // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceAsyncIterableSingle.h b/dom/bindings/test/TestInterfaceAsyncIterableSingle.h index a8da2336d6cadd77166389aa3d096adbb215aa03..9b8dbed67e20e58bc3375562f723170723ae667c 100644 --- a/dom/bindings/test/TestInterfaceAsyncIterableSingle.h +++ b/dom/bindings/test/TestInterfaceAsyncIterableSingle.h @@ -41,31 +41,35 @@ class TestInterfaceAsyncIterableSingle : public nsISupports, const TestInterfaceAsyncIterableSingleOptions& aOptions, ErrorResult& rv); using Iterator = AsyncIterableIterator<TestInterfaceAsyncIterableSingle>; - already_AddRefed<Promise> GetNextIterationResult(Iterator* aIterator, - ErrorResult& aRv); + void InitAsyncIterator(Iterator* aIterator, ErrorResult& aError); + void DestroyAsyncIterator(Iterator* aIterator); + already_AddRefed<Promise> GetNextPromise(JSContext* aCx, Iterator* aIterator, + ErrorResult& aRv); + protected: struct IteratorData { - void Traverse(nsCycleCollectionTraversalCallback& cb); - void Unlink(); - - uint32_t mIndex = 0; - uint32_t mMultiplier = 1; - Sequence<OwningNonNull<Promise>> mBlockingPromises; - size_t mBlockingPromisesIndex = 0; + IteratorData(int32_t aIndex, uint32_t aMultiplier) + : mIndex(aIndex), mMultiplier(aMultiplier) {} + ~IteratorData() { + if (mPromise) { + mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + mPromise = nullptr; + } + } + RefPtr<Promise> mPromise; + uint32_t mIndex; + uint32_t mMultiplier; }; - void InitAsyncIteratorData(IteratorData& aData, Iterator::IteratorType aType, - ErrorResult& aError); - - protected: - already_AddRefed<Promise> GetNextIterationResult( - IterableIteratorBase* aIterator, IteratorData& aData, ErrorResult& aRv); + already_AddRefed<Promise> GetNextPromise(JSContext* aCx, + IterableIteratorBase* aIterator, + IteratorData* aData, + ErrorResult& aRv); virtual ~TestInterfaceAsyncIterableSingle() = default; private: - void ResolvePromise(IterableIteratorBase* aIterator, IteratorData& aData, - Promise* aPromise); + void ResolvePromise(IterableIteratorBase* aIterator, IteratorData* aData); nsCOMPtr<nsPIDOMWindowInner> mParent; bool mFailToInit; diff --git a/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.cpp b/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.cpp index 02e459fccf4cb46528730ae2c9c9d46fa021900a..aa8f61b094fe673cfc85816bdef383b1c5a18a60 100644 --- a/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.cpp +++ b/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.cpp @@ -5,39 +5,13 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/dom/TestInterfaceAsyncIterableSingleWithArgs.h" -#include "js/Value.h" #include "mozilla/dom/TestInterfaceJSMaplikeSetlikeIterableBinding.h" #include "nsPIDOMWindow.h" #include "mozilla/dom/BindingUtils.h" #include "mozilla/dom/IterableIterator.h" -#include "mozilla/dom/Promise-inl.h" namespace mozilla::dom { -NS_IMPL_CYCLE_COLLECTION_CLASS(TestInterfaceAsyncIterableSingleWithArgs) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED( - TestInterfaceAsyncIterableSingleWithArgs, TestInterfaceAsyncIterableSingle) -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED( - TestInterfaceAsyncIterableSingleWithArgs, TestInterfaceAsyncIterableSingle) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED( - TestInterfaceAsyncIterableSingleWithArgs, TestInterfaceAsyncIterableSingle) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mReturnLastCalledWith) -NS_IMPL_CYCLE_COLLECTION_TRACE_END - -NS_IMPL_ADDREF_INHERITED(TestInterfaceAsyncIterableSingleWithArgs, - TestInterfaceAsyncIterableSingle) -NS_IMPL_RELEASE_INHERITED(TestInterfaceAsyncIterableSingleWithArgs, - TestInterfaceAsyncIterableSingle) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION( - TestInterfaceAsyncIterableSingleWithArgs) -NS_INTERFACE_MAP_END_INHERITING(TestInterfaceAsyncIterableSingle) - // static already_AddRefed<TestInterfaceAsyncIterableSingleWithArgs> TestInterfaceAsyncIterableSingleWithArgs::Constructor( @@ -60,34 +34,26 @@ JSObject* TestInterfaceAsyncIterableSingleWithArgs::WrapObject( aGivenProto); } -void TestInterfaceAsyncIterableSingleWithArgs::InitAsyncIteratorData( - IteratorData& aData, Iterator::IteratorType aType, - const TestInterfaceAsyncIteratorOptions& aOptions, ErrorResult& aError) { - aData.mMultiplier = aOptions.mMultiplier; - aData.mBlockingPromises = aOptions.mBlockingPromises; +void TestInterfaceAsyncIterableSingleWithArgs::InitAsyncIterator( + Iterator* aIterator, const TestInterfaceAsyncIteratorOptions& aOptions, + ErrorResult& aError) { + UniquePtr<IteratorData> data(new IteratorData(0, aOptions.mMultiplier)); + aIterator->SetData((void*)data.release()); } -already_AddRefed<Promise> -TestInterfaceAsyncIterableSingleWithArgs::GetNextIterationResult( - Iterator* aIterator, ErrorResult& aRv) { - return TestInterfaceAsyncIterableSingle::GetNextIterationResult( - aIterator, aIterator->Data(), aRv); +void TestInterfaceAsyncIterableSingleWithArgs::DestroyAsyncIterator( + Iterator* aIterator) { + auto* data = reinterpret_cast<IteratorData*>(aIterator->GetData()); + delete data; } already_AddRefed<Promise> -TestInterfaceAsyncIterableSingleWithArgs::IteratorReturn( - JSContext* aCx, Iterator* aIterator, JS::Handle<JS::Value> aValue, - ErrorResult& aRv) { - ++mReturnCallCount; - - RefPtr<Promise> promise = Promise::Create(GetParentObject()->AsGlobal(), aRv); - if (NS_WARN_IF(aRv.Failed())) { - return nullptr; - } - - mReturnLastCalledWith = aValue; - promise->MaybeResolve(JS::UndefinedHandleValue); - return promise.forget(); +TestInterfaceAsyncIterableSingleWithArgs::GetNextPromise(JSContext* aCx, + Iterator* aIterator, + ErrorResult& aRv) { + return TestInterfaceAsyncIterableSingle::GetNextPromise( + aCx, aIterator, reinterpret_cast<IteratorData*>(aIterator->GetData()), + aRv); } } // namespace mozilla::dom diff --git a/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.h b/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.h index a632f8b6eee7bd19a626f23aa8f88dcb91fa8f84..30d7b8455b6cad08fe0538aeb6b576eee3f66bb2 100644 --- a/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.h +++ b/dom/bindings/test/TestInterfaceAsyncIterableSingleWithArgs.h @@ -18,11 +18,6 @@ struct TestInterfaceAsyncIteratorOptions; class TestInterfaceAsyncIterableSingleWithArgs final : public TestInterfaceAsyncIterableSingle { public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED( - TestInterfaceAsyncIterableSingleWithArgs, - TestInterfaceAsyncIterableSingle) - using TestInterfaceAsyncIterableSingle::TestInterfaceAsyncIterableSingle; virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; @@ -31,28 +26,13 @@ class TestInterfaceAsyncIterableSingleWithArgs final using Iterator = AsyncIterableIterator<TestInterfaceAsyncIterableSingleWithArgs>; + void InitAsyncIterator(Iterator* aIterator, + const TestInterfaceAsyncIteratorOptions& aOptions, + ErrorResult& aError); + void DestroyAsyncIterator(Iterator* aIterator); - void InitAsyncIteratorData(IteratorData& aData, Iterator::IteratorType aType, - const TestInterfaceAsyncIteratorOptions& aOptions, - ErrorResult& aError); - - already_AddRefed<Promise> GetNextIterationResult(Iterator* aIterator, - ErrorResult& aRv); - already_AddRefed<Promise> IteratorReturn(JSContext* aCx, Iterator* aIterator, - JS::Handle<JS::Value> aValue, + already_AddRefed<Promise> GetNextPromise(JSContext* aCx, Iterator* aIterator, ErrorResult& aRv); - - uint32_t ReturnCallCount() { return mReturnCallCount; } - void GetReturnLastCalledWith(JSContext* aCx, - JS::MutableHandle<JS::Value> aReturnCalledWith) { - aReturnCalledWith.set(mReturnLastCalledWith); - } - - private: - ~TestInterfaceAsyncIterableSingleWithArgs() = default; - - JS::Heap<JS::Value> mReturnLastCalledWith; - uint32_t mReturnCallCount = 0; }; } // namespace mozilla::dom diff --git a/dom/bindings/test/test_async_iterable.html b/dom/bindings/test/test_async_iterable.html index 8dabf157d8e1c69deb9826c8b5fde3f87ec398b4..03af2097a5e72e19777630ab6182598ca04e6115 100644 --- a/dom/bindings/test/test_async_iterable.html +++ b/dom/bindings/test/test_async_iterable.html @@ -14,24 +14,17 @@ add_task(async function init() { await SpecialPowers.pushPrefEnv({set: [["dom.expose_test_interfaces", true]]}); }); -const singleValues = Array(10).fill(0).map((_, i) => i * 9 % 7); - -async function check_single_result_values(values, multiplier = 1) { - dump(JSON.stringify(values)); - is(values.length, 10, `AsyncIterableSingle: should return 10 elements`); - for (let i = 0; i < 10; i++) { - let expected = singleValues[i] * multiplier; - is(values[i], expected, - `AsyncIterableSingle: should be ${expected}, get ${values[i]}`); - } -} - async function check_single_result(itr, multiplier = 1) { let values = []; for await (let v of itr) { values.push(v); } - check_single_result_values(values, multiplier); + is(values.length, 10, `AsyncIterableSingle: should returns 10 elements`); + for (let i = 0; i < 10; i++) { + let expected = i * 9 % 7 * multiplier; + is(values[i], expected, + `AsyncIterableSingle: should be ${expected}, get ${values[i]}`); + } } async function test_data_single() { @@ -65,104 +58,6 @@ async function test_data_single() { await check_single_result(itr, 1); await check_single_result(itr.values({ multiplier: 2 }), 2); - - // eslint-disable-next-line no-undef - itr = new TestInterfaceAsyncIterableSingle(); - let itrValues = itr.values(); - let values = []; - for (let i = 0; i < 10; ++i) { - values.push(itrValues.next()); - } - check_single_result_values(await Promise.all(values).then(v => v.map(w => w.value))); - - // Test that there is only one ongoing promise at a time. - // Async iterables return a promise that is then resolved with the iterator - // value. We create an array of unresolved promises here, one promise for - // every result that we expect from the iterator. We pass that array of - // promises to the .value() method of the - // TestInterfaceAsyncIterableSingleWithArgs, and it will chain the resolving - // of each resulting iterator value on the corresponding promise from this - // array. We then resolve the promises in the array one by one in reverse - // order. This tries to make sure that the iterator always resolves the - // promises in the order of iteration. - let unblockers = []; - let blockingPromises = []; - for (let i = 0; i < 10; ++i) { - let unblocker; - let promise = new Promise((resolve, reject) => { - unblocker = resolve; - }); - unblockers.push(unblocker); - blockingPromises.push(promise); - } - - // eslint-disable-next-line no-undef - itr = new TestInterfaceAsyncIterableSingleWithArgs(); - itrValues = itr.values({ blockingPromises }); - values = []; - for (let i = 0; i < 10; ++i) { - values.push(itrValues.next()); - } - unblockers.reverse(); - for (let unblocker of unblockers) { - unblocker(); - } - - check_single_result_values(await Promise.all(values).then(v => v.map(w => w.value))); - - // eslint-disable-next-line no-undef - itr = new TestInterfaceAsyncIterableSingleWithArgs(); - - let callCount = itr.returnCallCount; - - let i = 0; - for await (let v of itr) { - if (++i > 1) { - break; - } - values.push(v); - } - - is(itr.returnCallCount, callCount + 1, - `AsyncIterableSingle: breaking out of for-await-of loop should call "return"`); - is(itr.returnLastCalledWith, undefined, - `AsyncIterableSingleWithArgs: the asynchronous iterator return algorithm should be called with the argument that was passed in.`); - - // eslint-disable-next-line no-undef - itr = new TestInterfaceAsyncIterableSingleWithArgs(); - - async function * yieldFromIterator () { - yield * itr - } - - let yieldingIterator = yieldFromIterator(); - - let result = await yieldingIterator.next(); - is(result.value, singleValues[0], - `AsyncIterableSingle: should be ${singleValues[0]}, get ${result.value}`); - result = await yieldingIterator.next(); - is(result.value, singleValues[1], - `AsyncIterableSingle: should be ${singleValues[1]}, get ${result.value}`); - - result = await yieldingIterator.return("abcd"); - is(typeof result, "object", - `AsyncIterableSingleWithArgs: "return("abcd")" should return { done: true, value: "abcd" }`); - is(result.done, true, - `AsyncIterableSingleWithArgs: "return("abcd")" should return { done: true, value: "abcd" }`); - is(result.value, "abcd", - `AsyncIterableSingleWithArgs: "return("abcd")" should return { done: true, value: "abcd" }`); - is(itr.returnLastCalledWith, "abcd", - `AsyncIterableSingleWithArgs: the asynchronous iterator return algorithm should be called with the argument that was passed in.`); - - result = await yieldingIterator.return("efgh"); - is(typeof result, "object", - `AsyncIterableSingleWithArgs: "return("efgh")" should return { done: true, value: "efgh" }`); - is(result.done, true, - `AsyncIterableSingleWithArgs: "return("efgh")" should return { done: true, value: "efgh" }`); - is(result.value, "efgh", - `AsyncIterableSingleWithArgs: "return("efgh")" should return { done: true, value: "efgh" }`); - is(itr.returnLastCalledWith, "abcd", - `AsyncIterableSingleWithArgs: the asynchronous iterator return algorithm shouldn't be called if the iterator's 'is finished' flag is true already.`); } async function test_data_double() { diff --git a/dom/broadcastchannel/BroadcastChannel.cpp b/dom/broadcastchannel/BroadcastChannel.cpp index ee8581f769741ed65d2548e3cc27a783508c8cc7..c3607e90a8a2784f4c6ae119d9d446af89d16a9f 100644 --- a/dom/broadcastchannel/BroadcastChannel.cpp +++ b/dom/broadcastchannel/BroadcastChannel.cpp @@ -14,7 +14,6 @@ #include "mozilla/dom/StructuredCloneHolder.h" #include "mozilla/dom/ipc/StructuredCloneData.h" #include "mozilla/dom/RefMessageBodyService.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/SharedMessageBody.h" #include "mozilla/dom/WorkerScope.h" #include "mozilla/dom/WorkerRef.h" diff --git a/dom/cache/Cache.cpp b/dom/cache/Cache.cpp index d9b94f6b14bc7320c6ef68ec034a3c4547e4dc3e..5da7a5cb42a9bc795134179d82aa10d613524174 100644 --- a/dom/cache/Cache.cpp +++ b/dom/cache/Cache.cpp @@ -13,7 +13,6 @@ #include "mozilla/dom/Promise.h" #include "mozilla/dom/PromiseNativeHandler.h" #include "mozilla/dom/Response.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/CacheBinding.h" #include "mozilla/dom/cache/AutoUtils.h" diff --git a/dom/cache/CacheStorage.h b/dom/cache/CacheStorage.h index 306c7cccd42d24430f23f99ad88d7cd9d6cff240..78cbafe37e27eb30b7e8643eb3d8177823bb7ea1 100644 --- a/dom/cache/CacheStorage.h +++ b/dom/cache/CacheStorage.h @@ -20,8 +20,6 @@ class nsIGlobalObject; namespace mozilla { class ErrorResult; -enum UseCounter : int16_t; -enum class UseCounterWorker : int16_t; namespace ipc { class PrincipalInfo; diff --git a/dom/cache/TypeUtils.cpp b/dom/cache/TypeUtils.cpp index 07fe4223f4b6874be1367f726e254f39fde94c74..029446ad18e72b9f993a04bb5c67c4e7991f7189 100644 --- a/dom/cache/TypeUtils.cpp +++ b/dom/cache/TypeUtils.cpp @@ -15,7 +15,6 @@ #include "mozilla/dom/InternalRequest.h" #include "mozilla/dom/Request.h" #include "mozilla/dom/Response.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/cache/CacheTypes.h" #include "mozilla/dom/cache/ReadStream.h" #include "mozilla/ipc/BackgroundChild.h" diff --git a/dom/fs/api/FileSystemDirectoryHandle.cpp b/dom/fs/api/FileSystemDirectoryHandle.cpp index a2d4bfaad86e36b8bcac27c0b73e5d907d6b679c..81fb530f5f20885f0e3919348f8211e55cd0b8c0 100644 --- a/dom/fs/api/FileSystemDirectoryHandle.cpp +++ b/dom/fs/api/FileSystemDirectoryHandle.cpp @@ -12,6 +12,7 @@ #include "js/TypeDecls.h" #include "mozilla/ErrorResult.h" #include "mozilla/dom/FileSystemDirectoryHandleBinding.h" +#include "mozilla/dom/FileSystemDirectoryIterator.h" #include "mozilla/dom/FileSystemHandleBinding.h" #include "mozilla/dom/FileSystemManager.h" #include "mozilla/dom/PFileSystemManager.h" @@ -50,15 +51,27 @@ FileSystemHandleKind FileSystemDirectoryHandle::Kind() const { return FileSystemHandleKind::Directory; } -void FileSystemDirectoryHandle::InitAsyncIteratorData( - IteratorData& aData, iterator_t::IteratorType aType, ErrorResult& aError) { - aData.mImpl = - fs::FileSystemDirectoryIteratorFactory::Create(mMetadata, aType); +void FileSystemDirectoryHandle::InitAsyncIterator( + FileSystemDirectoryHandle::iterator_t* aIterator, ErrorResult& aError) { + aIterator->SetData( + static_cast<void*>(fs::FileSystemDirectoryIteratorFactory::Create( + mMetadata, aIterator->GetIteratorType()) + .release())); } -already_AddRefed<Promise> FileSystemDirectoryHandle::GetNextIterationResult( - FileSystemDirectoryHandle::iterator_t* aIterator, ErrorResult& aError) { - return aIterator->Data().mImpl->Next(mGlobal, mManager, aError); +void FileSystemDirectoryHandle::DestroyAsyncIterator( + FileSystemDirectoryHandle::iterator_t* aIterator) { + auto* it = + static_cast<FileSystemDirectoryIterator::Impl*>(aIterator->GetData()); + delete it; + aIterator->SetData(nullptr); +} + +already_AddRefed<Promise> FileSystemDirectoryHandle::GetNextPromise( + JSContext* /* aCx */, FileSystemDirectoryHandle::iterator_t* aIterator, + ErrorResult& aError) { + return static_cast<FileSystemDirectoryIterator::Impl*>(aIterator->GetData()) + ->Next(mGlobal, mManager, aError); } already_AddRefed<Promise> FileSystemDirectoryHandle::GetFileHandle( diff --git a/dom/fs/api/FileSystemDirectoryHandle.h b/dom/fs/api/FileSystemDirectoryHandle.h index 36ac7455c55be231559ff0ec4a8fa10d5af0d081..87b0695fd3ce1809e86a0713ee502461bd2e1120 100644 --- a/dom/fs/api/FileSystemDirectoryHandle.h +++ b/dom/fs/api/FileSystemDirectoryHandle.h @@ -17,6 +17,7 @@ class ErrorResult; namespace dom { +class FileSystemDirectoryIterator; struct FileSystemGetFileOptions; struct FileSystemGetDirectoryOptions; struct FileSystemRemoveOptions; @@ -45,16 +46,13 @@ class FileSystemDirectoryHandle final : public FileSystemHandle { // WebIDL Interface FileSystemHandleKind Kind() const override; - struct IteratorData { - UniquePtr<FileSystemDirectoryIterator::Impl> mImpl; - }; + void InitAsyncIterator(iterator_t* aIterator, ErrorResult& aError); - void InitAsyncIteratorData(IteratorData& aData, - iterator_t::IteratorType aType, - ErrorResult& aError); + void DestroyAsyncIterator(iterator_t* aIterator); - [[nodiscard]] already_AddRefed<Promise> GetNextIterationResult( - iterator_t* aIterator, ErrorResult& aError); + [[nodiscard]] already_AddRefed<Promise> GetNextPromise(JSContext* aCx, + iterator_t* aIterator, + ErrorResult& aError); already_AddRefed<Promise> GetFileHandle( const nsAString& aName, const FileSystemGetFileOptions& aOptions, diff --git a/dom/fs/child/FileSystemDirectoryIteratorFactory.cpp b/dom/fs/child/FileSystemDirectoryIteratorFactory.cpp index ce2c9ac062f82e7d2c0ec52f5322e5dfd7cbaf3c..573b47c3f836aba8e0454eff077b1cf6167ca91b 100644 --- a/dom/fs/child/FileSystemDirectoryIteratorFactory.cpp +++ b/dom/fs/child/FileSystemDirectoryIteratorFactory.cpp @@ -22,23 +22,52 @@ namespace mozilla::dom::fs { namespace { +inline JSContext* GetContext(const RefPtr<Promise>& aPromise) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(aPromise->GetGlobalObject()))) { + return nullptr; + } + return jsapi.cx(); +} + template <IterableIteratorBase::IteratorType Type> struct ValueResolver; template <> struct ValueResolver<IterableIteratorBase::Keys> { - void operator()(nsIGlobalObject* aGlobal, RefPtr<FileSystemManager>& aManager, - const FileSystemEntryMetadata& aValue, - const RefPtr<Promise>& aPromise) { - aPromise->MaybeResolve(aValue.entryName()); + nsresult operator()(nsIGlobalObject* aGlobal, + RefPtr<FileSystemManager>& aManager, + const FileSystemEntryMetadata& aValue, + const RefPtr<Promise>& aPromise, ErrorResult& aError) { + JSContext* cx = GetContext(aPromise); + if (!cx) { + return NS_ERROR_UNEXPECTED; + } + + JS::Rooted<JS::Value> key(cx); + + if (!ToJSValue(cx, aValue.entryName(), &key)) { + return NS_ERROR_INVALID_ARG; + } + + iterator_utils::ResolvePromiseWithKeyOrValue(cx, aPromise.get(), key, + aError); + + return NS_OK; } }; template <> struct ValueResolver<IterableIteratorBase::Values> { - void operator()(nsIGlobalObject* aGlobal, RefPtr<FileSystemManager>& aManager, - const FileSystemEntryMetadata& aValue, - const RefPtr<Promise>& aPromise) { + nsresult operator()(nsIGlobalObject* aGlobal, + RefPtr<FileSystemManager>& aManager, + const FileSystemEntryMetadata& aValue, + const RefPtr<Promise>& aPromise, ErrorResult& aError) { + JSContext* cx = GetContext(aPromise); + if (!cx) { + return NS_ERROR_UNEXPECTED; + } + RefPtr<FileSystemHandle> handle; if (aValue.directory()) { @@ -47,15 +76,34 @@ struct ValueResolver<IterableIteratorBase::Values> { handle = new FileSystemFileHandle(aGlobal, aManager, aValue); } - aPromise->MaybeResolve(std::move(handle)); + JS::Rooted<JS::Value> value(cx); + if (!ToJSValue(cx, handle, &value)) { + return NS_ERROR_INVALID_ARG; + } + + iterator_utils::ResolvePromiseWithKeyOrValue(cx, aPromise.get(), value, + aError); + + return NS_OK; } }; template <> struct ValueResolver<IterableIteratorBase::Entries> { - void operator()(nsIGlobalObject* aGlobal, RefPtr<FileSystemManager>& aManager, - const FileSystemEntryMetadata& aValue, - const RefPtr<Promise>& aPromise) { + nsresult operator()(nsIGlobalObject* aGlobal, + RefPtr<FileSystemManager>& aManager, + const FileSystemEntryMetadata& aValue, + const RefPtr<Promise>& aPromise, ErrorResult& aError) { + JSContext* cx = GetContext(aPromise); + if (!cx) { + return NS_ERROR_UNEXPECTED; + } + + JS::Rooted<JS::Value> key(cx); + if (!ToJSValue(cx, aValue.entryName(), &key)) { + return NS_ERROR_INVALID_ARG; + } + RefPtr<FileSystemHandle> handle; if (aValue.directory()) { @@ -64,8 +112,15 @@ struct ValueResolver<IterableIteratorBase::Entries> { handle = new FileSystemFileHandle(aGlobal, aManager, aValue); } - iterator_utils::ResolvePromiseWithKeyAndValue(aPromise, aValue.entryName(), - handle); + JS::Rooted<JS::Value> value(cx); + if (!ToJSValue(cx, handle, &value)) { + return NS_ERROR_INVALID_ARG; + } + + iterator_utils::ResolvePromiseWithKeyAndValue(cx, aPromise.get(), key, + value, aError); + + return NS_OK; } }; @@ -88,16 +143,27 @@ class DoubleBufferQueueImpl // XXX This doesn't have to be public void ResolveValue(nsIGlobalObject* aGlobal, RefPtr<FileSystemManager>& aManager, - const Maybe<DataType>& aValue, RefPtr<Promise> aPromise) { + const Maybe<DataType>& aValue, RefPtr<Promise> aPromise, + ErrorResult& aError) { MOZ_ASSERT(aPromise); MOZ_ASSERT(aPromise.get()); + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(aPromise->GetGlobalObject()))) { + aPromise->MaybeReject(NS_ERROR_DOM_UNKNOWN_ERR); + aError = NS_ERROR_DOM_UNKNOWN_ERR; + return; + } + + JSContext* aCx = jsapi.cx(); + MOZ_ASSERT(aCx); + if (!aValue) { - iterator_utils::ResolvePromiseForFinished(aPromise); + iterator_utils::ResolvePromiseForFinished(aCx, aPromise.get(), aError); return; } - ValueResolver{}(aGlobal, aManager, *aValue, aPromise); + ValueResolver{}(aGlobal, aManager, *aValue, aPromise, aError); } already_AddRefed<Promise> Next(nsIGlobalObject* aGlobal, @@ -108,7 +174,7 @@ class DoubleBufferQueueImpl return nullptr; } - next(aGlobal, aManager, promise); + next(aGlobal, aManager, promise, aError); return promise.forget(); } @@ -117,7 +183,7 @@ class DoubleBufferQueueImpl protected: void next(nsIGlobalObject* aGlobal, RefPtr<FileSystemManager>& aManager, - RefPtr<Promise> aResult) { + RefPtr<Promise> aResult, ErrorResult& aError) { MOZ_ASSERT(aResult); Maybe<DataType> rawValue; @@ -129,7 +195,7 @@ class DoubleBufferQueueImpl ErrorResult rv; RefPtr<Promise> promise = Promise::Create(aGlobal, rv); if (rv.Failed()) { - aResult->MaybeReject(std::move(rv)); + aResult->MaybeReject(NS_ERROR_DOM_UNKNOWN_ERR); return; } @@ -159,7 +225,7 @@ class DoubleBufferQueueImpl } IgnoredErrorResult rv; - ResolveValue(global, manager, value, aResult); + ResolveValue(global, manager, value, aResult, rv); }, [](nsresult aRv) {}); promise->AppendNativeHandler(listener); @@ -173,7 +239,7 @@ class DoubleBufferQueueImpl nextInternal(rawValue); - ResolveValue(aGlobal, aManager, rawValue, aResult); + ResolveValue(aGlobal, aManager, rawValue, aResult, aError); } bool nextInternal(Maybe<DataType>& aNext) { diff --git a/dom/fs/test/gtest/api/TestFileSystemDirectoryHandle.cpp b/dom/fs/test/gtest/api/TestFileSystemDirectoryHandle.cpp index 647f289bbd24da97ae50761ab87494f2d9c2ea67..6da71747c9a0a49d1f9fffafa89168bb574416b8 100644 --- a/dom/fs/test/gtest/api/TestFileSystemDirectoryHandle.cpp +++ b/dom/fs/test/gtest/api/TestFileSystemDirectoryHandle.cpp @@ -9,6 +9,7 @@ #include "mozilla/UniquePtr.h" #include "mozilla/dom/FileSystemDirectoryHandle.h" #include "mozilla/dom/FileSystemDirectoryHandleBinding.h" +#include "mozilla/dom/FileSystemDirectoryIterator.h" #include "mozilla/dom/FileSystemHandle.h" #include "mozilla/dom/FileSystemHandleBinding.h" #include "mozilla/dom/FileSystemManager.h" @@ -29,6 +30,12 @@ class TestFileSystemDirectoryHandle : public ::testing::Test { mManager = MakeAndAddRef<FileSystemManager>(mGlobal, nullptr); } + FileSystemDirectoryHandle::iterator_t::WrapFunc GetWrapFunc() const { + return [](JSContext*, AsyncIterableIterator<FileSystemDirectoryHandle>*, + JS::Handle<JSObject*>, + JS::MutableHandle<JSObject*>) -> bool { return true; }; + } + nsIGlobalObject* mGlobal = GetGlobal(); const IterableIteratorBase::IteratorType mIteratorType = IterableIteratorBase::IteratorType::Keys; @@ -45,7 +52,7 @@ TEST_F(TestFileSystemDirectoryHandle, constructDirectoryHandleRefPointer) { ASSERT_TRUE(dirHandle); } -TEST_F(TestFileSystemDirectoryHandle, initIterator) { +TEST_F(TestFileSystemDirectoryHandle, initAndDestroyIterator) { RefPtr<FileSystemDirectoryHandle> dirHandle = MakeAndAddRef<FileSystemDirectoryHandle>(mGlobal, mManager, mMetadata, mRequestHandler.release()); @@ -53,19 +60,28 @@ TEST_F(TestFileSystemDirectoryHandle, initIterator) { ASSERT_TRUE(dirHandle); RefPtr<FileSystemDirectoryHandle::iterator_t> iterator = - new FileSystemDirectoryHandle::iterator_t(dirHandle.get(), mIteratorType); + new FileSystemDirectoryHandle::iterator_t(dirHandle.get(), mIteratorType, + GetWrapFunc()); IgnoredErrorResult rv; - dirHandle->InitAsyncIteratorData(iterator->Data(), mIteratorType, rv); - ASSERT_TRUE(iterator->Data().mImpl); + dirHandle->InitAsyncIterator(iterator, rv); + ASSERT_TRUE(iterator->GetData()); + + dirHandle->DestroyAsyncIterator(iterator); + ASSERT_EQ(nullptr, iterator->GetData()); } class MockFileSystemDirectoryIteratorImpl final : public FileSystemDirectoryIterator::Impl { public: + NS_INLINE_DECL_REFCOUNTING(MockFileSystemDirectoryIteratorImpl) + MOCK_METHOD(already_AddRefed<Promise>, Next, (nsIGlobalObject * aGlobal, RefPtr<FileSystemManager>& aManager, ErrorResult& aError), (override)); + + protected: + ~MockFileSystemDirectoryIteratorImpl() = default; }; TEST_F(TestFileSystemDirectoryHandle, isNextPromiseReturned) { @@ -75,20 +91,22 @@ TEST_F(TestFileSystemDirectoryHandle, isNextPromiseReturned) { ASSERT_TRUE(dirHandle); - auto mockIter = MakeUnique<MockFileSystemDirectoryIteratorImpl>(); + auto* mockIter = new MockFileSystemDirectoryIteratorImpl(); IgnoredErrorResult error; EXPECT_CALL(*mockIter, Next(_, _, _)) .WillOnce(::testing::Return(Promise::Create(mGlobal, error))); RefPtr<FileSystemDirectoryHandle::iterator_t> iterator = - MakeAndAddRef<FileSystemDirectoryHandle::iterator_t>(dirHandle.get(), - mIteratorType); - iterator->Data().mImpl = std::move(mockIter); + MakeAndAddRef<FileSystemDirectoryHandle::iterator_t>( + dirHandle.get(), mIteratorType, GetWrapFunc()); + iterator->SetData(static_cast<void*>(mockIter)); IgnoredErrorResult rv; RefPtr<Promise> promise = - dirHandle->GetNextIterationResult(iterator.get(), rv); + dirHandle->GetNextPromise(nullptr, iterator.get(), rv); ASSERT_TRUE(promise); + + dirHandle->DestroyAsyncIterator(iterator.get()); } TEST_F(TestFileSystemDirectoryHandle, isHandleKindDirectory) { diff --git a/dom/ipc/SharedMap.cpp b/dom/ipc/SharedMap.cpp index 70e12784e925faa0bd97550df85af7342f97cb31..6bd83d822d35816b7806462598c3da8816f9d860 100644 --- a/dom/ipc/SharedMap.cpp +++ b/dom/ipc/SharedMap.cpp @@ -15,7 +15,6 @@ #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentProcessMessageManager.h" #include "mozilla/dom/IPCBlobUtils.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/IOBuffers.h" #include "mozilla/ScriptPreloader.h" diff --git a/dom/notification/Notification.cpp b/dom/notification/Notification.cpp index 24100656591b13e37dc5383fb1ed7768d0f0bbfc..0717d4fb6f5ddeacdf3474064946b67cf812fc37 100644 --- a/dom/notification/Notification.cpp +++ b/dom/notification/Notification.cpp @@ -27,7 +27,6 @@ #include "mozilla/dom/PermissionMessageUtils.h" #include "mozilla/dom/Promise.h" #include "mozilla/dom/PromiseWorkerProxy.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h" #include "mozilla/dom/ServiceWorkerManager.h" #include "mozilla/dom/ServiceWorkerUtils.h" diff --git a/dom/promise/Promise-inl.h b/dom/promise/Promise-inl.h index f472acbc166c7abdcb2f2f64555aeed61f50b5ac..b238db446c9f3a4da274c1d96db92dbc6b38681e 100644 --- a/dom/promise/Promise-inl.h +++ b/dom/promise/Promise-inl.h @@ -227,15 +227,13 @@ class NativeThenHandler<ResolveCallback, RejectCallback, std::tuple<Args...>, } // anonymous namespace -template <typename ResolveCallback, typename RejectCallback, typename... Args, - typename... JSArgs> -Result<RefPtr<Promise>, nsresult> -Promise::ThenCatchWithCycleCollectedArgsJSImpl( +template <typename ResolveCallback, typename RejectCallback, typename... Args> +Promise::ThenResult<ResolveCallback, Args...> +Promise::ThenCatchWithCycleCollectedArgsImpl( Maybe<ResolveCallback>&& aOnResolve, Maybe<RejectCallback>&& aOnReject, - std::tuple<Args...>&& aArgs, std::tuple<JSArgs...>&& aJSArgs) { - using HandlerType = - NativeThenHandler<ResolveCallback, RejectCallback, std::tuple<Args...>, - std::tuple<JSArgs...>>; + Args&&... aArgs) { + using HandlerType = NativeThenHandler<ResolveCallback, RejectCallback, + std::tuple<Args...>, std::tuple<>>; ErrorResult rv; RefPtr<Promise> promise = Promise::Create(GetParentObject(), rv); @@ -243,11 +241,10 @@ Promise::ThenCatchWithCycleCollectedArgsJSImpl( return Err(rv.StealNSResult()); } - auto* handler = new (fallible) - HandlerType(promise, std::forward<Maybe<ResolveCallback>>(aOnResolve), - std::forward<Maybe<RejectCallback>>(aOnReject), - std::forward<std::tuple<Args...>>(aArgs), - std::forward<std::tuple<JSArgs...>>(aJSArgs)); + auto* handler = new (fallible) HandlerType( + promise, std::forward<Maybe<ResolveCallback>>(aOnResolve), + std::forward<Maybe<RejectCallback>>(aOnReject), + std::make_tuple(std::forward<Args>(aArgs)...), std::make_tuple()); if (!handler) { return Err(NS_ERROR_OUT_OF_MEMORY); @@ -257,17 +254,6 @@ Promise::ThenCatchWithCycleCollectedArgsJSImpl( return std::move(promise); } -template <typename ResolveCallback, typename RejectCallback, typename... Args> -Promise::ThenResult<ResolveCallback, Args...> -Promise::ThenCatchWithCycleCollectedArgsImpl( - Maybe<ResolveCallback>&& aOnResolve, Maybe<RejectCallback>&& aOnReject, - Args&&... aArgs) { - return ThenCatchWithCycleCollectedArgsJSImpl( - std::forward<Maybe<ResolveCallback>>(aOnResolve), - std::forward<Maybe<RejectCallback>>(aOnReject), - std::make_tuple(std::forward<Args>(aArgs)...), std::make_tuple()); -} - template <typename ResolveCallback, typename RejectCallback, typename... Args> Promise::ThenResult<ResolveCallback, Args...> Promise::ThenCatchWithCycleCollectedArgs(ResolveCallback&& aOnResolve, @@ -293,22 +279,28 @@ Promise::ThenResult<Callback, Args...> Promise::CatchWithCycleCollectedArgs( std::forward<Args>(aArgs)...); } -template <typename ResolveCallback, typename RejectCallback, typename ArgsTuple, - typename JSArgsTuple> -Result<RefPtr<Promise>, nsresult> Promise::ThenCatchWithCycleCollectedArgsJS( - ResolveCallback&& aOnResolve, RejectCallback&& aOnReject, ArgsTuple&& aArgs, - JSArgsTuple&& aJSArgs) { - return ThenCatchWithCycleCollectedArgsJSImpl( - Some(aOnResolve), Some(aOnReject), std::forward<ArgsTuple>(aArgs), - std::forward<JSArgsTuple>(aJSArgs)); -} - template <typename Callback, typename ArgsTuple, typename JSArgsTuple> Result<RefPtr<Promise>, nsresult> Promise::ThenWithCycleCollectedArgsJS( Callback&& aOnResolve, ArgsTuple&& aArgs, JSArgsTuple&& aJSArgs) { - return ThenCatchWithCycleCollectedArgsJSImpl( - Some(aOnResolve), Maybe<Callback>(Nothing()), + using HandlerType = + NativeThenHandler<Callback, Callback, ArgsTuple, JSArgsTuple>; + + ErrorResult rv; + RefPtr<Promise> promise = Promise::Create(GetParentObject(), rv); + if (rv.Failed()) { + return Err(rv.StealNSResult()); + } + + auto* handler = new (fallible) HandlerType( + promise, Some(aOnResolve), Maybe<Callback>(Nothing()), std::forward<ArgsTuple>(aArgs), std::forward<JSArgsTuple>(aJSArgs)); + + if (!handler) { + return Err(NS_ERROR_OUT_OF_MEMORY); + } + + AppendNativeHandler(handler); + return std::move(promise); } template <typename ResolveCallback, typename RejectCallback, typename... Args> diff --git a/dom/promise/Promise.h b/dom/promise/Promise.h index 2c5d3e0f05379056a41410368dd3aa37a8fd5758..578a959c2ae605ff0b6205948f5633154e61cbf5 100644 --- a/dom/promise/Promise.h +++ b/dom/promise/Promise.h @@ -275,14 +275,9 @@ class Promise : public SupportsWeakPtr { ThenResult<Callback, Args...> CatchWithCycleCollectedArgs( Callback&& aOnReject, Args&&... aArgs); - // Same as Then[Catch]CycleCollectedArgs but the arguments are gathered into - // an `std::tuple` and there is an additional `std::tuple` for JS arguments - // after that. - template <typename ResolveCallback, typename RejectCallback, - typename ArgsTuple, typename JSArgsTuple> - Result<RefPtr<Promise>, nsresult> ThenCatchWithCycleCollectedArgsJS( - ResolveCallback&& aOnResolve, RejectCallback&& aOnReject, - ArgsTuple&& aArgs, JSArgsTuple&& aJSArgs); + // Same as ThenCycleCollectedArgs but the arguments are gathered into an + // `std::tuple` and there is an additional `std::tuple` for JS arguments after + // that. template <typename Callback, typename ArgsTuple, typename JSArgsTuple> Result<RefPtr<Promise>, nsresult> ThenWithCycleCollectedArgsJS( Callback&& aOnResolve, ArgsTuple&& aArgs, JSArgsTuple&& aJSArgs); @@ -337,11 +332,6 @@ class Promise : public SupportsWeakPtr { nsIGlobalObject* aGlobal, ErrorResult& aRejectionError); protected: - template <typename ResolveCallback, typename RejectCallback, typename... Args, - typename... JSArgs> - Result<RefPtr<Promise>, nsresult> ThenCatchWithCycleCollectedArgsJSImpl( - Maybe<ResolveCallback>&& aOnResolve, Maybe<RejectCallback>&& aOnReject, - std::tuple<Args...>&& aArgs, std::tuple<JSArgs...>&& aJSArgs); template <typename ResolveCallback, typename RejectCallback, typename... Args> ThenResult<ResolveCallback, Args...> ThenCatchWithCycleCollectedArgsImpl( Maybe<ResolveCallback>&& aOnResolve, Maybe<RejectCallback>&& aOnReject, diff --git a/dom/promise/gtest/ThenWithCycleCollectedArgsJS.cpp b/dom/promise/gtest/ThenWithCycleCollectedArgsJS.cpp index 31b9fde3cac2c83d9df547a98b9e4d63c102ca31..b97de65d093ad3dea36d7fa293734469088015e0 100644 --- a/dom/promise/gtest/ThenWithCycleCollectedArgsJS.cpp +++ b/dom/promise/gtest/ThenWithCycleCollectedArgsJS.cpp @@ -78,81 +78,3 @@ TEST(ThenWithCycleCollectedArgsJS, Mixed) std::make_tuple(global, promise), std::make_tuple(JS::UndefinedHandleValue, JS::HandleObject(obj))); } - -TEST(ThenCatchWithCycleCollectedArgsJS, Empty) -{ - nsCOMPtr<nsIGlobalObject> global = - xpc::NativeGlobal(xpc::PrivilegedJunkScope()); - - RefPtr<Promise> promise = Promise::Create(global, IgnoreErrors()); - auto result = promise->ThenCatchWithCycleCollectedArgsJS( - [](JSContext*, JS::Handle<JS::Value>, ErrorResult&) { return nullptr; }, - [](JSContext*, JS::Handle<JS::Value>, ErrorResult&) { return nullptr; }, - std::make_tuple(), std::make_tuple()); -} - -TEST(ThenCatchWithCycleCollectedArgsJS, nsCOMPtr) -{ - nsCOMPtr<nsIGlobalObject> global = - xpc::NativeGlobal(xpc::PrivilegedJunkScope()); - - RefPtr<Promise> promise = Promise::Create(global, IgnoreErrors()); - auto result = promise->ThenCatchWithCycleCollectedArgsJS( - [](JSContext*, JS::Handle<JS::Value>, ErrorResult&, nsIGlobalObject*) { - return nullptr; - }, - [](JSContext*, JS::Handle<JS::Value>, ErrorResult&, nsIGlobalObject*) { - return nullptr; - }, - std::make_tuple(global), std::make_tuple()); -} - -TEST(ThenCatchWithCycleCollectedArgsJS, RefPtr) -{ - nsCOMPtr<nsIGlobalObject> global = - xpc::NativeGlobal(xpc::PrivilegedJunkScope()); - - RefPtr<Promise> promise = Promise::Create(global, IgnoreErrors()); - auto result = promise->ThenCatchWithCycleCollectedArgsJS( - [](JSContext*, JS::Handle<JS::Value>, ErrorResult&, Promise*) { - return nullptr; - }, - [](JSContext*, JS::Handle<JS::Value>, ErrorResult&, Promise*) { - return nullptr; - }, - std::make_tuple(promise), std::make_tuple()); -} - -TEST(ThenCatchWithCycleCollectedArgsJS, RefPtrAndJSHandle) -{ - nsCOMPtr<nsIGlobalObject> global = - xpc::NativeGlobal(xpc::PrivilegedJunkScope()); - - RefPtr<Promise> promise = Promise::Create(global, IgnoreErrors()); - auto result = promise->ThenCatchWithCycleCollectedArgsJS( - [](JSContext*, JS::Handle<JS::Value> v, ErrorResult&, Promise*, - JS::Handle<JS::Value>) { return nullptr; }, - [](JSContext*, JS::Handle<JS::Value> v, ErrorResult&, Promise*, - JS::Handle<JS::Value>) { return nullptr; }, - std::make_tuple(promise), std::make_tuple(JS::UndefinedHandleValue)); -} - -TEST(ThenCatchWithCycleCollectedArgsJS, Mixed) -{ - AutoJSAPI jsapi; - MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope())); - JSContext* cx = jsapi.cx(); - nsCOMPtr<nsIGlobalObject> global = xpc::CurrentNativeGlobal(cx); - JS::Rooted<JSObject*> obj(cx, JS_NewPlainObject(cx)); - - RefPtr<Promise> promise = Promise::Create(global, IgnoreErrors()); - auto result = promise->ThenCatchWithCycleCollectedArgsJS( - [](JSContext*, JS::Handle<JS::Value>, ErrorResult&, nsIGlobalObject*, - Promise*, JS::Handle<JS::Value>, - JS::Handle<JSObject*>) { return nullptr; }, - [](JSContext*, JS::Handle<JS::Value>, ErrorResult&, nsIGlobalObject*, - Promise*, JS::Handle<JS::Value>, - JS::Handle<JSObject*>) { return nullptr; }, - std::make_tuple(global, promise), - std::make_tuple(JS::UndefinedHandleValue, JS::HandleObject(obj))); -} diff --git a/dom/serviceworkers/ServiceWorkerContainer.cpp b/dom/serviceworkers/ServiceWorkerContainer.cpp index 2ce6b60d5b3fb3887c33c360633491300048439c..eeb5862f7680c8d17b859faf39f7723c5692be31 100644 --- a/dom/serviceworkers/ServiceWorkerContainer.cpp +++ b/dom/serviceworkers/ServiceWorkerContainer.cpp @@ -32,7 +32,6 @@ #include "mozilla/dom/MessageEventBinding.h" #include "mozilla/dom/Navigator.h" #include "mozilla/dom/Promise.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/ServiceWorker.h" #include "mozilla/dom/ServiceWorkerContainerBinding.h" #include "mozilla/dom/ServiceWorkerManager.h" diff --git a/dom/webidl/TestInterfaceJSMaplikeSetlikeIterable.webidl b/dom/webidl/TestInterfaceJSMaplikeSetlikeIterable.webidl index 2363a8930b29aedcee79ca327e18706a13c493e6..3dadf84301b0c7c2694c247e6c897de474ec0d2f 100644 --- a/dom/webidl/TestInterfaceJSMaplikeSetlikeIterable.webidl +++ b/dom/webidl/TestInterfaceJSMaplikeSetlikeIterable.webidl @@ -111,7 +111,6 @@ interface TestInterfaceAsyncIterableSingle { dictionary TestInterfaceAsyncIteratorOptions { unsigned long multiplier = 1; - sequence<Promise<any>> blockingPromises = []; }; [Pref="dom.expose_test_interfaces", @@ -120,12 +119,7 @@ interface TestInterfaceAsyncIterableSingleWithArgs { [Throws] constructor(); - [GenerateReturnMethod] async iterable<long>(optional TestInterfaceAsyncIteratorOptions options = {}); - - readonly attribute long returnCallCount; - - readonly attribute any returnLastCalledWith; }; [Pref="dom.expose_test_interfaces", diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index e15afcdebdecb9ceed97cb539a511b34670b19c1..7ae860d4361ea41f3486c23a13e379c6513fbfc1 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -49,7 +49,6 @@ #include "mozilla/dom/PromiseDebugging.h" #include "mozilla/dom/RemoteWorkerChild.h" #include "mozilla/dom/RemoteWorkerService.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/TimeoutHandler.h" #include "mozilla/dom/WorkerBinding.h" #include "mozilla/dom/WorkerScope.h" diff --git a/dom/worklet/Worklet.cpp b/dom/worklet/Worklet.cpp index a73be7c4f4155881afd36a0f9693c2ba967ba636..36c4c66423d7c87ec765470a592e3afb56b67d05 100644 --- a/dom/worklet/Worklet.cpp +++ b/dom/worklet/Worklet.cpp @@ -16,7 +16,6 @@ #include "mozilla/dom/PromiseNativeHandler.h" #include "mozilla/dom/Request.h" #include "mozilla/dom/Response.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ScriptLoader.h" #include "mozilla/dom/WorkletImpl.h" diff --git a/mfbt/Tuple.h b/mfbt/Tuple.h index 7fec059ef9679924a21441f8f5fb921f5ff5488b..85ff3f314e15d1b1f016b009bd417d8900386e34 100644 --- a/mfbt/Tuple.h +++ b/mfbt/Tuple.h @@ -116,7 +116,7 @@ struct TupleImpl<Index> { bool operator==(const TupleImpl<Index>& aOther) const { return true; } template <typename F> - void ForEach(const F& aFunc) const {} + void ForEach(const F& aFunc) {} }; /* @@ -449,7 +449,7 @@ inline void ForEach(Tuple<>& aTuple, const F& aFunc) {} template <typename F, typename... Elements> void ForEach(const Tuple<Elements...>& aTuple, const F& aFunc) { - aTuple.ForEach(aFunc); + aTuple.ForEach(aTuple, aFunc); } template <typename F, typename... Elements> diff --git a/mfbt/tests/TestTuple.cpp b/mfbt/tests/TestTuple.cpp index 4e20101972b4a749d377cb8946525ced93d9a66f..13f61048f1e0eed6a36def8aae3b06583d24214d 100644 --- a/mfbt/tests/TestTuple.cpp +++ b/mfbt/tests/TestTuple.cpp @@ -292,59 +292,6 @@ static bool TestTieIgnore() { return true; } -template <typename... Elements, typename F> -static void CheckForEachCall(const Tuple<Elements...>& aTuple, - F&& CallForEach) { - constexpr std::size_t tupleSize = sizeof...(Elements); - - Tuple<Elements...> checkResult; - std::size_t i = 0; - auto createResult = [&](auto& aElem) { - static_assert(tupleSize == 3, - "Need to deal with more/less cases in the switch below"); - - CHECK(i < tupleSize); - switch (i) { - case 0: - Get<0>(checkResult) = aElem; - break; - case 1: - Get<1>(checkResult) = aElem; - break; - case 2: - Get<2>(checkResult) = aElem; - break; - } - ++i; - }; - - CallForEach(aTuple, createResult); - - CHECK(checkResult == aTuple); -} - -static bool TestForEach() { - Tuple<int, float, char> tuple = MakeTuple(42, 0.5f, 'c'); - - CheckForEachCall( - tuple, [](auto& aTuple, auto&& aLambda) { aTuple.ForEach(aLambda); }); - - CheckForEachCall( - tuple, [](auto& aTuple, auto&& aLambda) { ForEach(aTuple, aLambda); }); - - CheckForEachCall(tuple, [](auto& aTuple, auto&& aLambda) { - const decltype(aTuple)& constTuple = aTuple; - constTuple.ForEach(aLambda); - }); - - CheckForEachCall(tuple, [](auto& aTuple, auto&& aLambda) { - const decltype(aTuple)& constTuple = aTuple; - ForEach(constTuple, aLambda); - }); - - return true; -} - int main() { TestConstruction(); TestConstructionFromMozPair(); @@ -357,6 +304,5 @@ int main() { TestTie(); TestTieIgnore(); TestTieMozPair(); - TestForEach(); return 0; } diff --git a/toolkit/components/extensions/webrequest/StreamFilter.cpp b/toolkit/components/extensions/webrequest/StreamFilter.cpp index aab284dda202849980dcf4f121157f3bcebed3da..c6d8361573de61af51a71bfb755ea23e5598f4c1 100644 --- a/toolkit/components/extensions/webrequest/StreamFilter.cpp +++ b/toolkit/components/extensions/webrequest/StreamFilter.cpp @@ -16,7 +16,6 @@ #include "mozilla/extensions/StreamFilterParent.h" #include "mozilla/dom/AutoEntryScript.h" #include "mozilla/dom/ContentChild.h" -#include "mozilla/dom/RootedDictionary.h" #include "mozilla/ipc/Endpoint.h" #include "nsContentUtils.h" #include "nsCycleCollectionParticipant.h"