Bug 945788. Add support for dictionary return values to example codegen and js-implemented codegen. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 05 Dec 2013 11:39:50 -0500
changeset 174625 a439f81ded5c3b97e40b22552773184facd12ff9
parent 174624 71e8967053dce4ef32e1b8a326db89e2b262958a
child 174626 fea4b49abfa21c4191b7ae6c7842bf9fb725db3b
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs945788
milestone28.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 945788. Add support for dictionary return values to example codegen and js-implemented codegen. r=smaug
dom/bindings/Codegen.py
dom/bindings/parser/WebIDL.py
dom/bindings/test/TestBindingHeader.h
dom/bindings/test/TestCodeGen.webidl
dom/bindings/test/TestExampleGen.webidl
dom/bindings/test/TestJSImplGen.webidl
dom/webidl/PeerConnectionObserver.webidl
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3738,17 +3738,17 @@ for (uint32_t i = 0; i < length; ++i) {
     if type.isDictionary():
         # There are no nullable dictionaries
         assert not type.nullable()
         # All optional dictionaries always have default values, so we
         # should be able to assume not isOptional here.
         assert not isOptional
 
         typeName = CGDictionary.makeDictionaryName(type.inner)
-        if not isMember:
+        if not isMember and not isCallbackReturnValue:
             # Since we're not a member and not nullable or optional, no one will
             # see our real type, so we can do the fast version of the dictionary
             # that doesn't pre-initialize members.
             typeName = "dictionary_detail::Fast" + typeName
 
         declType = CGGeneric(typeName)
 
         # We do manual default value handling here, because we
@@ -3778,17 +3778,21 @@ for (uint32_t i = 0; i < length; ++i) {
 
         template += ('if (!${declName}.Init(cx, %s, "%s")) {\n'
                      "%s\n"
                      "}" % (val, firstCap(sourceDescription),
                             exceptionCodeIndented.define()))
 
         # Dictionary arguments that might contain traceable things need to get
         # traced
-        if not isMember and typeNeedsRooting(type):
+        if not isMember and isCallbackReturnValue:
+            # Go ahead and just convert directly into our actual return value
+            declType = CGWrapper(declType, post="&")
+            declArgs = "retval"
+        elif not isMember and typeNeedsRooting(type):
             declType = CGTemplatedType("RootedDictionary", declType);
             declArgs = "cx"
         else:
             declArgs = None
 
         return JSToNativeConversionInfo(template, declType=declType,
                                         declArgs=declArgs)
 
@@ -9703,36 +9707,53 @@ class CGNativeMember(ClassMethod):
                 returnCode = "retval.SwapElements(${declName});"
             return "void", "", returnCode
         if type.isDate():
             result = CGGeneric("Date")
             if type.nullable():
                 result = CGTemplatedType("Nullable", result)
             return (result.define(), "%s()" % result.define(),
                     "return ${declName};")
+        if type.isDictionary():
+            if isMember:
+                # Only the first member of the tuple matters here, but return
+                # bogus values for the others in case someone decides to use
+                # them.
+                return CGDictionary.makeDictionaryName(type.inner), None, None
+            # In this case we convert directly into our outparam to start with
+            return "void", "", ""
+
         raise TypeError("Don't know how to declare return value for %s" %
                         type)
 
     def getArgs(self, returnType, argList):
         args = [self.getArg(arg) for arg in argList]
         # Now the outparams
         if returnType.isDOMString():
             args.append(Argument("nsString&", "retval"))
-        if returnType.isByteString():
+        elif returnType.isByteString():
             args.append(Argument("nsCString&", "retval"))
         elif returnType.isSequence():
             nullable = returnType.nullable()
             if nullable:
                 returnType = returnType.inner
             # And now the actual underlying type
             elementDecl = self.getReturnType(returnType.inner, True)
             type = CGTemplatedType("nsTArray", CGGeneric(elementDecl))
             if nullable:
                 type = CGTemplatedType("Nullable", type)
             args.append(Argument("%s&" % type.define(), "retval"))
+        elif returnType.isDictionary():
+            nullable = returnType.nullable()
+            if nullable:
+                returnType = returnType.inner
+            dictType = CGGeneric(CGDictionary.makeDictionaryName(returnType.inner))
+            if nullable:
+                dictType = CGTemplatedType("Nullable", dictType)
+            args.append(Argument("%s&" % dictType.define(), "retval"))
         # And the ErrorResult
         if not 'infallible' in self.extendedAttrs:
             # Use aRv so it won't conflict with local vars named "rv"
             args.append(Argument("ErrorResult&", "aRv"))
         # The legacycaller thisval
         if self.member.isMethod() and self.member.isLegacycaller():
             # If it has an identifier, we can't deal with it yet
             assert self.member.isIdentifierLess()
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -2027,17 +2027,17 @@ class IDLWrapperType(IDLType):
     def isSerializable(self):
         if self.isInterface():
             if self.inner.isExternal():
                 return False
             return any(m.isMethod() and m.isJsonifier() for m in self.inner.members)
         elif self.isEnum():
             return True
         elif self.isDictionary():
-            return all(m.isSerializable() for m in self.inner.members)
+            return all(m.type.isSerializable() for m in self.inner.members)
         else:
             raise WebIDLError("IDLWrapperType wraps type %s that we don't know if "
                               "is serializable" % type(self.inner), [self.location])
 
     def resolveType(self, parentScope):
         assert isinstance(parentScope, IDLScope)
         self.inner.resolve(parentScope)
 
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -336,16 +336,17 @@ public:
   void PassOptionalNonNullCallbackInterface(const Optional<OwningNonNull<TestCallbackInterface> >&);
   void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterface*);
 
   already_AddRefed<IndirectlyImplementedInterface> ReceiveConsequentialInterface();
   void PassConsequentialInterface(IndirectlyImplementedInterface&);
 
   // Sequence types
   void GetReadonlySequence(nsTArray<int32_t>&);
+  void GetReadonlySequenceOfDictionaries(JSContext*, nsTArray<Dict>&);
   void ReceiveSequence(nsTArray<int32_t>&);
   void ReceiveNullableSequence(Nullable< nsTArray<int32_t> >&);
   void ReceiveSequenceOfNullableInts(nsTArray< Nullable<int32_t> >&);
   void ReceiveNullableSequenceOfNullableInts(Nullable< nsTArray< Nullable<int32_t> > >&);
   void PassSequence(const Sequence<int32_t> &);
   void PassNullableSequence(const Nullable< Sequence<int32_t> >&);
   void PassSequenceOfNullableInts(const Sequence<Nullable<int32_t> >&);
   void PassOptionalSequenceOfNullableInts(const Optional<Sequence<Nullable<int32_t> > > &);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -292,16 +292,18 @@ interface TestInterface {
 
   // Miscellaneous interface tests
   IndirectlyImplementedInterface receiveConsequentialInterface();
   void passConsequentialInterface(IndirectlyImplementedInterface arg);
 
   // Sequence types
   [Cached, Pure]
   readonly attribute sequence<long> readonlySequence;
+  [Cached, Pure]
+  readonly attribute sequence<Dict> readonlySequenceOfDictionaries;
   sequence<long> receiveSequence();
   sequence<long>? receiveNullableSequence();
   sequence<long?> receiveSequenceOfNullableInts();
   sequence<long?>? receiveNullableSequenceOfNullableInts();
   void passSequence(sequence<long> arg);
   void passNullableSequence(sequence<long>? arg);
   void passSequenceOfNullableInts(sequence<long?> arg);
   void passOptionalSequenceOfNullableInts(optional sequence<long?> arg);
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -188,16 +188,18 @@ interface TestExampleInterface {
 
   // Miscellaneous interface tests
   IndirectlyImplementedInterface receiveConsequentialInterface();
   void passConsequentialInterface(IndirectlyImplementedInterface arg);
 
   // Sequence types
   [Cached, Pure]
   readonly attribute sequence<long> readonlySequence;
+  [Cached, Pure]
+  readonly attribute sequence<Dict> readonlySequenceOfDictionaries;
   sequence<long> receiveSequence();
   sequence<long>? receiveNullableSequence();
   sequence<long?> receiveSequenceOfNullableInts();
   sequence<long?>? receiveNullableSequenceOfNullableInts();
   void passSequence(sequence<long> arg);
   void passNullableSequence(sequence<long>? arg);
   void passSequenceOfNullableInts(sequence<long?> arg);
   void passOptionalSequenceOfNullableInts(optional sequence<long?> arg);
@@ -422,29 +424,28 @@ interface TestExampleInterface {
 
   // binaryNames tests
   void methodRenamedFrom();
   void methodRenamedFrom(byte argument);
   readonly attribute byte attributeGetterRenamedFrom;
   attribute byte attributeRenamedFrom;
 
   void passDictionary(optional Dict x);
-  // FIXME: Bug 863949 no dictionary return values in callbacks
-  // Dict receiveDictionary();
-  // Dict? receiveNullableDictionary();
+  Dict receiveDictionary();
+  Dict? receiveNullableDictionary();
   void passOtherDictionary(optional GrandparentDict x);
   void passSequenceOfDictionaries(sequence<Dict> x);
   // No support for nullable dictionaries inside a sequence (nor should there be)
   //  void passSequenceOfNullableDictionaries(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();
+  DictContainingSequence receiveDictContainingSequence();
 
   // EnforceRange/Clamp tests
   void dontEnforceRangeOrClamp(byte arg);
   void doEnforceRange([EnforceRange] byte arg);
   void doClamp([Clamp] byte arg);
   [EnforceRange] attribute byte enforcedByte;
   [Clamp] attribute byte clampedByte;
 
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -209,16 +209,18 @@ interface TestJSImplInterface {
 
   // Miscellaneous interface tests
   IndirectlyImplementedInterface receiveConsequentialInterface();
   void passConsequentialInterface(IndirectlyImplementedInterface arg);
 
   // Sequence types
   [Cached, Pure]
   readonly attribute sequence<long> readonlySequence;
+  [Cached, Pure]
+  readonly attribute sequence<Dict> readonlySequenceOfDictionaries;
   sequence<long> receiveSequence();
   sequence<long>? receiveNullableSequence();
   sequence<long?> receiveSequenceOfNullableInts();
   sequence<long?>? receiveNullableSequenceOfNullableInts();
   void passSequence(sequence<long> arg);
   void passNullableSequence(sequence<long>? arg);
   void passSequenceOfNullableInts(sequence<long?> arg);
   void passOptionalSequenceOfNullableInts(optional sequence<long?> arg);
@@ -446,30 +448,29 @@ interface TestJSImplInterface {
 
   // binaryNames tests
   void methodRenamedFrom();
   void methodRenamedFrom(byte argument);
   readonly attribute byte attributeGetterRenamedFrom;
   attribute byte attributeRenamedFrom;
 
   void passDictionary(optional Dict x);
-  // FIXME: Bug 863949 no dictionary return values
-  //   Dict receiveDictionary();
-  //   Dict? receiveNullableDictionary();
+  Dict receiveDictionary();
+  // No support for nullable dictionary return values here yet
+  //  Dict? receiveNullableDictionary();
   void passOtherDictionary(optional GrandparentDict x);
   void passSequenceOfDictionaries(sequence<Dict> x);
   // No support for nullable dictionaries inside a sequence (nor should there be)
   //  void passSequenceOfNullableDictionaries(sequence<Dict?> x);
   void passDictionaryOrLong(optional Dict x);
   void passDictionaryOrLong(long x);
 
   void passDictContainingDict(optional DictContainingDict arg);
   void passDictContainingSequence(optional DictContainingSequence arg);
-  // FIXME: Bug 863949 no dictionary return values
-  //   DictContainingSequence receiveDictContainingSequence();
+  DictContainingSequence receiveDictContainingSequence();
 
   // EnforceRange/Clamp tests
   void dontEnforceRangeOrClamp(byte arg);
   void doEnforceRange([EnforceRange] byte arg);
   void doClamp([Clamp] byte arg);
   [EnforceRange] attribute byte enforcedByte;
   [Clamp] attribute byte clampedByte;
 
--- a/dom/webidl/PeerConnectionObserver.webidl
+++ b/dom/webidl/PeerConnectionObserver.webidl
@@ -44,13 +44,10 @@ interface PeerConnectionObserver
   void onAddStream(MediaStream stream);
   void onRemoveStream();
   void onAddTrack();
   void onRemoveTrack();
 
   /* Helper function to access supported constraints defined in webidl. Needs to
    * be in a separate webidl object we hold, so putting it here was convenient.
    */
-// TODO: Bug 863949
-//  MediaConstraintSet getSupportedConstraints(optional
-  object getSupportedConstraints(optional
-      MediaConstraintSet constraints);
+  MediaConstraintSet getSupportedConstraints(optional MediaConstraintSet constraints);
 };