From 90dcaa61d537837d6e01a1711813e742667bfde0 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 16 May 2013 12:36:56 -0400 Subject: [PATCH] Bug 868715 part 8. Add tracing to WebIDL sequence return values. r=peterv --- dom/bindings/BindingUtils.h | 32 +++++++++++++++-- dom/bindings/Codegen.py | 69 +++++++++++++++++++++++-------------- 2 files changed, 73 insertions(+), 28 deletions(-) diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index 15b86a310622..b6e67b006dc4 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -1573,6 +1573,8 @@ public: template void DoTraceSequence(JSTracer* trc, FallibleTArray& seq); +template +void DoTraceSequence(JSTracer* trc, InfallibleTArray& seq); // Class for simple sequence arguments, only used internally by codegen. template @@ -1638,6 +1640,20 @@ public: } }; +// sequence> as return value +template +class SequenceTracer, false> +{ + explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated + +public: + static void TraceSequence(JSTracer* trc, nsTArray* seqp, nsTArray* end) { + for ( ; seqp != end; ++seqp) { + DoTraceSequence(trc, *seqp); + } + } +}; + // sequence template class SequenceTracer @@ -1706,11 +1722,18 @@ public: mSequenceType = eInfallibleArray; } -private: + void SetSequence(Nullable>* aSequence) + { + mNullableArray = aSequence; + mSequenceType = eNullableArray; + } + + private: enum SequenceType { eNone, eInfallibleArray, - eFallibleArray + eFallibleArray, + eNullableArray }; virtual void trace(JSTracer *trc) MOZ_OVERRIDE @@ -1719,12 +1742,17 @@ private: DoTraceSequence(trc, *mFallibleArray); } else if (mSequenceType == eInfallibleArray) { DoTraceSequence(trc, *mInfallibleArray); + } else if (mSequenceType == eNullableArray) { + if (!mNullableArray->IsNull()) { + DoTraceSequence(trc, mNullableArray->Value()); + } } } union { InfallibleTArray* mInfallibleArray; FallibleTArray* mFallibleArray; + Nullable >* mNullableArray; }; SequenceType mSequenceType; diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 6745882e9a47..d489e012d7de 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -4095,32 +4095,40 @@ def dictionaryNeedsCx(dictionary, descriptorProvider): return (any(typeNeedsCx(m.type, descriptorProvider) for m in dictionary.members) or (dictionary.parent and dictionaryNeedsCx(dictionary.parent, descriptorProvider))) -# Returns a tuple consisting of a CGThing containing the type of the return -# value, or None if there is no need for a return value, and a boolean signaling -# whether the return value is passed in an out parameter. -# # Whenever this is modified, please update CGNativeMember.getRetvalInfo as # needed to keep the types compatible. def getRetvalDeclarationForType(returnType, descriptorProvider, resultAlreadyAddRefed, isMember=False): + """ + Returns a tuple containing three things: + + 1) A CGThing for the type of the return value, or None if there is no need + for a return value. + + 2) A boolean indicating whether the return value is passed as an out + parameter. + + 3) A CGThing for a tracer for the return value, or None if no tracing is + needed. + """ if returnType is None or returnType.isVoid(): # Nothing to declare - return None, False + return None, False, None if returnType.isPrimitive() and returnType.tag() in builtinNames: result = CGGeneric(builtinNames[returnType.tag()]) if returnType.nullable(): result = CGTemplatedType("Nullable", result) - return result, False + return result, False, None if returnType.isString(): if isMember: - return CGGeneric("nsString"), True - return CGGeneric("DOMString"), True + return CGGeneric("nsString"), True, None + return CGGeneric("DOMString"), True, None if returnType.isEnum(): result = CGGeneric(returnType.unroll().inner.identifier.name) if returnType.nullable(): result = CGTemplatedType("Nullable", result) - return result, False + return result, False, None if returnType.isGeckoInterface(): result = CGGeneric(descriptorProvider.getDescriptor( returnType.unroll().inner.identifier.name).nativeType) @@ -4131,30 +4139,37 @@ def getRetvalDeclarationForType(returnType, descriptorProvider, result = CGTemplatedType("nsAutoPtr", result) else: result = CGWrapper(result, post="*") - return result, False + return result, False, None if returnType.isCallback(): name = returnType.unroll().identifier.name if descriptorProvider.workers: - return CGGeneric("JSObject*"), False - return CGGeneric("nsRefPtr<%s>" % name), False + return CGGeneric("JSObject*"), False, None + return CGGeneric("nsRefPtr<%s>" % name), False, None if returnType.isAny(): - return CGGeneric("JS::Value"), False + return CGGeneric("JS::Value"), False, None if returnType.isObject() or returnType.isSpiderMonkeyInterface(): - return CGGeneric("JSObject*"), False + return CGGeneric("JSObject*"), False, None if returnType.isSequence(): nullable = returnType.nullable() if nullable: returnType = returnType.inner # If our result is already addrefed, use the right type in the # sequence argument here. - (result, _) = getRetvalDeclarationForType(returnType.inner, - descriptorProvider, - resultAlreadyAddRefed, - isMember="Sequence") + (result, _, _) = getRetvalDeclarationForType(returnType.inner, + descriptorProvider, + resultAlreadyAddRefed, + isMember="Sequence") + # While we have our inner type, set up our rooter, if needed + if not isMember and typeNeedsCx(returnType, descriptorProvider): + rooter = CGGeneric("SequenceRooter<%s > resultRooter(cx);\n" + "resultRooter.SetSequence(&result);" % + result.define()) + else: + rooter = None result = CGTemplatedType("nsTArray", result) if nullable: result = CGTemplatedType("Nullable", result) - return result, True + return result, True, rooter if returnType.isDictionary(): nullable = returnType.nullable() result = CGGeneric( @@ -4163,14 +4178,14 @@ def getRetvalDeclarationForType(returnType, descriptorProvider, "Initializer") if nullable: result = CGTemplatedType("Nullable", result) - return result, True + return result, True, None if returnType.isUnion(): raise TypeError("Need to sort out ownership model for union retvals"); if returnType.isDate(): result = CGGeneric("Date") if returnType.nullable(): result = CGTemplatedType("Nullable", result) - return result, False + return result, False, None raise TypeError("Don't know how to declare return value for %s" % returnType) @@ -4204,9 +4219,8 @@ class CGCallGenerator(CGThing): resultAlreadyAddRefed = isResultAlreadyAddRefed(descriptorProvider, extendedAttributes) - (result, resultOutParam) = getRetvalDeclarationForType(returnType, - descriptorProvider, - resultAlreadyAddRefed) + (result, resultOutParam, resultRooter) = getRetvalDeclarationForType( + returnType, descriptorProvider, resultAlreadyAddRefed) args = CGList([CGGeneric(arg) for arg in argsPre], ", ") for (a, name) in arguments: @@ -4252,6 +4266,8 @@ class CGCallGenerator(CGThing): call = CGWrapper(call, pre="%s->" % object) call = CGList([call, CGWrapper(args, pre="(", post=");")]) if result is not None: + if resultRooter is not None: + self.cgRoot.prepend(resultRooter) result = CGWrapper(result, post=" result;") self.cgRoot.prepend(result) if not resultOutParam: @@ -5174,8 +5190,9 @@ class CGSpecializedGetter(CGAbstractStaticMethod): name = attr.identifier.name nativeName = MakeNativeName(descriptor.binaryNames.get(name, name)) # resultOutParam does not depend on whether resultAlreadyAddRefed is set - (_, resultOutParam) = getRetvalDeclarationForType(attr.type, descriptor, - False) + (_, resultOutParam, _) = getRetvalDeclarationForType(attr.type, + descriptor, + False) infallible = ('infallible' in descriptor.getExtendedAttributes(attr, getter=True)) if resultOutParam or attr.type.nullable() or not infallible: