Backed out changeset 877a227c502f (bug 882541) for causing bug 926305
authorEd Morley <emorley@mozilla.com>
Mon, 14 Oct 2013 17:31:06 +0100
changeset 164442 fcddc11fb2ef7747a638f7f5efc1fb1c62614996
parent 164441 b5dc6d9578e7c8f6d727e72cf768937f567271f0
child 164446 8a4374c8fc92f90c39ab7adf004172ab16460a68
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs882541, 926305
milestone27.0a1
backs out877a227c502f07a77a1600edf3285665218ae0fb
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
Backed out changeset 877a227c502f (bug 882541) for causing bug 926305
dom/bindings/parser/WebIDL.py
dom/bindings/parser/tests/test_dictionary.py
dom/bindings/parser/tests/test_optional_constraints.py
dom/bindings/parser/tests/test_overload.py
dom/bindings/parser/tests/test_variadic_constraints.py
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -3138,32 +3138,35 @@ class IDLMethod(IDLInterfaceMember, IDLS
         return self
 
     def signatures(self):
         return [(overload.returnType, overload.arguments) for overload in
                 self._overloads]
 
     def finish(self, scope):
         for overload in self._overloads:
+            inOptionalArguments = False
             variadicArgument = None
 
             arguments = overload.arguments
             for (idx, argument) in enumerate(arguments):
-                if not argument.isComplete():
-                    argument.complete(scope)
+                if argument.isComplete():
+                    continue
+
+                argument.complete(scope)
                 assert argument.type.isComplete()
 
                 if (argument.type.isDictionary() or
                     (argument.type.isUnion() and
                      argument.type.unroll().hasDictionaryType)):
                     # Dictionaries and unions containing dictionaries at the
                     # end of the list or followed by optional arguments must be
                     # optional.
                     if (not argument.optional and
-                        all(arg.optional for arg in arguments[idx+1:])):
+                        (idx == len(arguments) - 1 or arguments[idx+1].optional)):
                         raise WebIDLError("Dictionary argument or union "
                                           "argument containing a dictionary "
                                           "not followed by a required argument "
                                           "must be optional",
                                           [argument.location])
 
                     # An argument cannot be a Nullable Dictionary
                     if argument.type.nullable():
@@ -3171,16 +3174,23 @@ class IDLMethod(IDLInterfaceMember, IDLS
                                           "dictionary or nullable union "
                                           "containing a dictionary",
                                           [argument.location])
 
                 # Only the last argument can be variadic
                 if variadicArgument:
                     raise WebIDLError("Variadic argument is not last argument",
                                       [variadicArgument.location])
+                # Once we see an optional argument, there can't be any non-optional
+                # arguments.
+                if inOptionalArguments and not argument.optional:
+                    raise WebIDLError("Non-optional argument after optional "
+                                      "arguments",
+                                      [argument.location])
+                inOptionalArguments = argument.optional
                 if argument.variadic:
                     variadicArgument = argument
 
             returnType = overload.returnType
             if returnType.isComplete():
                 continue
 
             type = returnType.complete(scope)
@@ -3215,17 +3225,17 @@ class IDLMethod(IDLInterfaceMember, IDLS
                             (self.identifier.name, argCount, idx,
                              distinguishingIndex),
                             [self.location, overload.location])
 
     def overloadsForArgCount(self, argc):
         return [overload for overload in self._overloads if
                 len(overload.arguments) == argc or
                 (len(overload.arguments) > argc and
-                 all(arg.optional for arg in overload.arguments[argc:])) or
+                 overload.arguments[argc].optional) or
                 (len(overload.arguments) < argc and
                  len(overload.arguments) > 0 and
                  overload.arguments[-1].variadic)]
 
     def signaturesForArgCount(self, argc):
         return [(overload.returnType, overload.arguments) for overload
                 in self.overloadsForArgCount(argc)]
 
@@ -4045,16 +4055,31 @@ class Parser(Tokenizer):
         if stringifier:
             if len(arguments) != 0:
                 raise WebIDLError("stringifier has wrong number of arguments",
                                   [self.getLocation(p, 2)])
             if not returnType.isDOMString():
                 raise WebIDLError("stringifier must have DOMString return type",
                                   [self.getLocation(p, 2)])
 
+        inOptionalArguments = False
+        variadicArgument = False
+        for argument in arguments:
+            # Only the last argument can be variadic
+            if variadicArgument:
+                raise WebIDLError("Only the last argument can be variadic",
+                                  [variadicArgument.location])
+            # Once we see an optional argument, there can't be any non-optional
+            # arguments.
+            if inOptionalArguments and not argument.optional:
+                raise WebIDLError("Cannot have a non-optional argument following an optional argument",
+                                  [argument.location])
+            inOptionalArguments = argument.optional
+            variadicArgument = argument if argument.variadic else None
+
         # identifier might be None.  This is only permitted for special methods.
         if not identifier:
             if not getter and not setter and not creator and \
                not deleter and not legacycaller and not stringifier:
                 raise WebIDLError("Identifier required for non-special methods",
                                   [self.getLocation(p, 2)])
 
             location = BuiltinLocation("<auto-generated-identifier>")
--- a/dom/bindings/parser/tests/test_dictionary.py
+++ b/dom/bindings/parser/tests/test_dictionary.py
@@ -173,33 +173,16 @@ def WebIDLTest(parser, harness):
 
     parser = parser.reset()
     threw = False
     try:
         parser.parse("""
             dictionary A {
             };
             interface X {
-              void doFoo(A arg1, optional long arg2, long arg3);
-            };
-        """)
-        results = parser.finish()
-    except:
-        threw = True
-
-    harness.ok(not threw,
-               "Dictionary arg followed by non-optional arg doesn't have to be optional")
-
-    parser = parser.reset()
-    threw = False
-    try:
-        parser.parse("""
-            dictionary A {
-            };
-            interface X {
               void doFoo((A or DOMString) arg1, optional long arg2);
             };
         """)
         results = parser.finish()
     except:
         threw = True
 
     harness.ok(threw,
--- a/dom/bindings/parser/tests/test_optional_constraints.py
+++ b/dom/bindings/parser/tests/test_optional_constraints.py
@@ -6,19 +6,19 @@ def WebIDLTest(parser, harness):
               void foo(optional byte arg1, byte arg2);
             };
         """)
 
         results = parser.finish()
     except:
         threw = True
 
-    harness.ok(not threw,
-               "Should not have thrown on non-optional argument following "
-               "optional argument.")
+    harness.ok(threw,
+               "Should have thrown on non-optional argument following optional "
+               "argument.")
 
     parser = parser.reset()
     parser.parse("""
         interface OptionalConstraints2 {
           void foo(optional byte arg1 = 1, optional byte arg2 = 2,
                    optional byte arg3, optional byte arg4 = 4,
                    optional byte arg5, optional byte arg6 = 9);
         };
--- a/dom/bindings/parser/tests/test_overload.py
+++ b/dom/bindings/parser/tests/test_overload.py
@@ -6,31 +6,29 @@ def WebIDLTest(parser, harness):
           void basic();
           void basic(long arg1);
           boolean abitharder(TestOverloads foo);
           boolean abitharder(boolean foo);
           void abitharder(ArrayBuffer? foo);
           void withVariadics(long... numbers);
           void withVariadics(TestOverloads iface);
           void withVariadics(long num, TestOverloads iface);
-          void optionalTest();
-          void optionalTest(optional long num1, long num2);
         };
     """)
 
     results = parser.finish()
 
     harness.ok(True, "TestOverloads interface parsed without error.")
     harness.check(len(results), 1, "Should be one production.")
     iface = results[0]
     harness.ok(isinstance(iface, WebIDL.IDLInterface),
                "Should be an IDLInterface")
     harness.check(iface.identifier.QName(), "::TestOverloads", "Interface has the right QName")
     harness.check(iface.identifier.name, "TestOverloads", "Interface has the right name")
-    harness.check(len(iface.members), 4, "Expect %s members" % 4)
+    harness.check(len(iface.members), 3, "Expect %s members" % 3)
 
     member = iface.members[0]
     harness.check(member.identifier.QName(), "::TestOverloads::basic", "Method has the right QName")
     harness.check(member.identifier.name, "basic", "Method has the right name")
     harness.check(member.hasOverloads(), True, "Method has overloads")
 
     signatures = member.signatures()
     harness.check(len(signatures), 2, "Method should have 2 signatures")
@@ -45,16 +43,8 @@ def WebIDLTest(parser, harness):
     harness.check(len(argumentSet), 1, "Expect an argument set with one argument")
 
     argument = argumentSet[0]
     harness.ok(isinstance(argument, WebIDL.IDLArgument),
                "Should be an IDLArgument")
     harness.check(argument.identifier.QName(), "::TestOverloads::basic::arg1", "Argument has the right QName")
     harness.check(argument.identifier.name, "arg1", "Argument has the right name")
     harness.check(str(argument.type), "Long", "Argument has the right type")
-
-    member = iface.members[3]
-    harness.check(len(member.overloadsForArgCount(0)), 1,
-                  "Only one overload for no args")
-    harness.check(len(member.overloadsForArgCount(1)), 0,
-                  "No overloads for one arg")
-    harness.check(len(member.overloadsForArgCount(2)), 1,
-                  "Only one overload for two args")
--- a/dom/bindings/parser/tests/test_variadic_constraints.py
+++ b/dom/bindings/parser/tests/test_variadic_constraints.py
@@ -1,63 +1,52 @@
 def WebIDLTest(parser, harness):
     threw = False
     try:
-        parser.parse("""
+        results = parser.parse("""
             interface VariadicConstraints1 {
               void foo(byte... arg1, byte arg2);
             };
         """)
-        results = parser.finish()
 
     except:
         threw = True
 
-    harness.ok(threw,
-               "Should have thrown on variadic argument followed by required "
-               "argument.")
+    harness.ok(threw, "Should have thrown.")
 
-    parser = parser.reset()
     threw = False
     try:
-        parser.parse("""
+        results = parser.parse("""
             interface VariadicConstraints2 {
               void foo(byte... arg1, optional byte arg2);
             };
         """)
-        results = parser.finish();
+
     except:
         threw = True
 
-    harness.ok(threw,
-               "Should have thrown on variadic argument followed by optional "
-               "argument.")
+    harness.ok(threw, "Should have thrown.")
 
-    parser = parser.reset()
     threw = False
     try:
-        parser.parse("""
+        results = parser.parse("""
             interface VariadicConstraints3 {
               void foo(optional byte... arg1);
             };
         """)
-        results = parser.finish()
 
     except:
         threw = True
 
-    harness.ok(threw,
-               "Should have thrown on variadic argument explicitly flagged as "
-               "optional.")
+    harness.ok(threw, "Should have thrown.")
 
-    parser = parser.reset()
     threw = False
     try:
-        parser.parse("""
+        results = parser.parse("""
             interface VariadicConstraints4 {
               void foo(byte... arg1 = 0);
             };
         """)
-        results = parser.finish()
+
     except:
         threw = True
 
     harness.ok(threw, "Should have thrown on variadic argument with default value.")