Bug 812742. Fix sequence codegen to not do AppendElement multiple times by accident. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 27 Nov 2012 15:20:40 -0500
changeset 114266 c3d44fd7dce4c609f1e719848d16acb0e556c050
parent 114265 279541c0d07c68996d99f33984aa0dd0b4249931
child 114267 0e37dbe22164e4856a8312e3e486c40afa317162
push id23913
push useremorley@mozilla.com
push dateWed, 28 Nov 2012 17:11:31 +0000
treeherdermozilla-central@17c267a881cf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs812742
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 812742. Fix sequence codegen to not do AppendElement multiple times by accident. r=peterv
dom/bindings/Codegen.py
dom/bindings/test/TestBindingHeader.h
dom/bindings/test/TestCodeGen.webidl
dom/bindings/test/TestExampleGen.webidl
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2197,30 +2197,36 @@ if (!arr.SetCapacity(length)) {
   JS_ReportOutOfMemory(cx);
 %s
 }
 for (uint32_t i = 0; i < length; ++i) {
   jsval temp;
   if (!JS_GetElement(cx, seq, i, &temp)) {
 %s
   }
+  %s& slot = *arr.AppendElement();
 """ % (CGIndenter(CGGeneric(notSequence)).define(),
        exceptionCodeIndented.define(),
        elementDeclType.define(),
        elementDeclType.define(),
        arrayRef,
        exceptionCodeIndented.define(),
-       CGIndenter(exceptionCodeIndented).define()))
+       CGIndenter(exceptionCodeIndented).define(),
+       elementDeclType.define()))
 
         templateBody += CGIndenter(CGGeneric(
                 string.Template(elementTemplate).substitute(
                     {
                         "val" : "temp",
                         "valPtr": "&temp",
-                        "declName" : "(*arr.AppendElement())",
+                        "declName" : "slot",
+                        # We only need holderName here to handle isExternal()
+                        # interfaces, which use an internal holder for the
+                        # conversion even when forceOwningType ends up true.
+                        "holderName": "tempHolder",
                         # Use the same ${obj} as for the sequence itself
                         "obj": "${obj}"
                         }
                     ))).define()
 
         templateBody += "\n}"
         templateBody = wrapObjectTemplate(templateBody, type,
                                           "const_cast< %s & >(${declName}).SetNull()" % mutableTypeName.define())
@@ -2528,17 +2534,17 @@ for (uint32_t i = 0; i < length; ++i) {
                 "jsval tmpVal = ${val};\n" +
                 typePtr + " tmp;\n"
                 "if (NS_FAILED(xpc_qsUnwrapArg<" + typeName + ">(cx, ${val}, &tmp, static_cast<" + typeName + "**>(getter_AddRefs(${holderName})), &tmpVal))) {\n")
             templateBody += CGIndenter(onFailureBadType(failureCode,
                                                         descriptor.interface.identifier.name)).define()
             templateBody += ("}\n"
                 "MOZ_ASSERT(tmp);\n")
 
-            if not isDefinitelyObject:
+            if not isDefinitelyObject and not forceOwningType:
                 # Our tmpVal will go out of scope, so we can't rely on it
                 # for rooting
                 templateBody += (
                     "if (tmpVal != ${val} && !${holderName}) {\n"
                     "  // We have to have a strong ref, because we got this off\n"
                     "  // some random object that might get GCed\n"
                     "  ${holderName} = tmp;\n"
                     "}\n")
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -305,16 +305,18 @@ public:
   void PassCastableObjectSequence(const Sequence< OwningNonNull<TestInterface> >&);
   void PassNullableCastableObjectSequence(const Sequence< nsRefPtr<TestInterface> > &);
   void PassCastableObjectNullableSequence(const Nullable< Sequence< OwningNonNull<TestInterface> > >&);
   void PassNullableCastableObjectNullableSequence(const Nullable< Sequence< nsRefPtr<TestInterface> > >&);
   void PassOptionalSequence(const Optional<Sequence<int32_t> >&);
   void PassOptionalNullableSequence(const Optional<Nullable<Sequence<int32_t> > >&);
   void PassOptionalNullableSequenceWithDefaultValue(const Nullable< Sequence<int32_t> >&);
   void PassOptionalObjectSequence(const Optional<Sequence<OwningNonNull<TestInterface> > >&);
+  void PassExternalInterfaceSequence(const Sequence<nsRefPtr<TestExternalInterface> >&);
+  void PassNullableExternalInterfaceSequence(const Sequence<nsRefPtr<TestExternalInterface> >&);
 
   void ReceiveStringSequence(nsTArray<nsString>&);
   void PassStringSequence(const Sequence<nsString>&);
 
   void ReceiveAnySequence(JSContext*, nsTArray<JS::Value>&);
   void ReceiveNullableAnySequence(JSContext*, Nullable<nsTArray<JS::Value> >);
 
   // Typed array types
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -260,16 +260,18 @@ interface TestInterface {
   void passCastableObjectSequence(sequence<TestInterface> arg);
   void passNullableCastableObjectSequence(sequence<TestInterface?> arg);
   void passCastableObjectNullableSequence(sequence<TestInterface>? arg);
   void passNullableCastableObjectNullableSequence(sequence<TestInterface?>? arg);
   void passOptionalSequence(optional sequence<long> arg);
   void passOptionalNullableSequence(optional sequence<long>? arg);
   void passOptionalNullableSequenceWithDefaultValue(optional sequence<long>? arg = null);
   void passOptionalObjectSequence(optional sequence<TestInterface> arg);
+  void passExternalInterfaceSequence(sequence<TestExternalInterface> arg);
+  void passNullableExternalInterfaceSequence(sequence<TestExternalInterface?> arg);
 
   sequence<DOMString> receiveStringSequence();
   void passStringSequence(sequence<DOMString> arg);
 
   sequence<any> receiveAnySequence();
   sequence<any>? receiveNullableAnySequence();
 
   // Typed array types
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -181,16 +181,18 @@ interface TestExampleInterface {
   void passCastableObjectSequence(sequence<TestInterface> arg);
   void passNullableCastableObjectSequence(sequence<TestInterface?> arg);
   void passCastableObjectNullableSequence(sequence<TestInterface>? arg);
   void passNullableCastableObjectNullableSequence(sequence<TestInterface?>? arg);
   void passOptionalSequence(optional sequence<long> arg);
   void passOptionalNullableSequence(optional sequence<long>? arg);
   void passOptionalNullableSequenceWithDefaultValue(optional sequence<long>? arg = null);
   void passOptionalObjectSequence(optional sequence<TestInterface> arg);
+  void passExternalInterfaceSequence(sequence<TestExternalInterface> arg);
+  void passNullableExternalInterfaceSequence(sequence<TestExternalInterface?> arg);
 
   sequence<DOMString> receiveStringSequence();
   void passStringSequence(sequence<DOMString> arg);
 
   sequence<any> receiveAnySequence();
   sequence<any>? receiveNullableAnySequence();
 
   // Typed array types
@@ -279,23 +281,25 @@ interface TestExampleInterface {
 
   // binaryNames tests
   void methodRenamedFrom();
   void methodRenamedFrom(byte argument);
   readonly attribute byte attributeGetterRenamedFrom;
   attribute byte attributeRenamedFrom;
 
   void passDictionary(optional Dict x);
+  //UNSUPPORTED  Dict receiveDictionary();
   void passOtherDictionary(optional GrandparentDict x);
   void passSequenceOfDictionaries(sequence<Dict> x);
   void passDictionaryOrLong(optional Dict x);
   void passDictionaryOrLong(long x);
 
   void passDictContainingDict(optional DictContainingDict arg);
   void passDictContainingSequence(optional DictContainingSequence arg);
+  //UNSUPPORTED DictContainingSequence receiveDictContainingSequence();
 
   // EnforceRange/Clamp tests
   void dontEnforceRangeOrClamp(byte arg);
   void doEnforceRange([EnforceRange] byte arg);
   void doClamp([Clamp] byte arg);
 
   // Typedefs
   const myLong myLongConstant = 5;