Bug 1057541 part 2. Add a way to ask an IDLArgument whether it guarantees that it will always have a value. r=khuey
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 05 Sep 2014 14:28:43 -0400
changeset 203954 7206acdbc0553f0919286dbbc2b2aab555b046e7
parent 203953 ddea90d3a95ed76a34ed6bdeee165a70bccd6c1c
child 203955 2c54535a0c6b8f017dee4480539ad3067b6364c6
push id27446
push usercbook@mozilla.com
push dateMon, 08 Sep 2014 13:22:40 +0000
treeherdermozilla-central@dd3961697eb5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1057541
milestone35.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 1057541 part 2. Add a way to ask an IDLArgument whether it guarantees that it will always have a value. r=khuey
dom/bindings/Codegen.py
dom/bindings/parser/WebIDL.py
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5282,17 +5282,17 @@ class CGArgumentConverter(CGThing):
             "passedToJSImpl": toStringBool(isJSImplementedDescriptor(descriptorProvider))
         }
         self.replacementVariables["val"] = string.Template(
             "args[${index}]").substitute(replacer)
         haveValueCheck = string.Template(
             "args.hasDefined(${index})").substitute(replacer)
         self.replacementVariables["haveValue"] = haveValueCheck
         self.descriptorProvider = descriptorProvider
-        if self.argument.optional and not self.argument.defaultValue:
+        if self.argument.canHaveMissingValue():
             self.argcAndIndex = replacer
         else:
             self.argcAndIndex = None
         self.invalidEnumValueFatal = invalidEnumValueFatal
         self.lenientFloatCode = lenientFloatCode
 
     def define(self):
         typeConversion = getJSToNativeConversionInfo(
@@ -6125,20 +6125,19 @@ class CGCallGenerator(CGThing):
                 # nullable or not, and it turns out a const JS::Rooted
                 # is not very helpful at all (in particular, it won't
                 # even convert to a JS::Handle).
                 # XXX bz Well, why not???
                 if a.type.nullable() and not a.type.isObject():
                     return True
                 if a.type.isString():
                     return True
-                if a.optional and not a.defaultValue:
-                    # If a.defaultValue, then it's not going to use an Optional,
-                    # so doesn't need to be const just due to being optional.
-                    # This also covers variadic arguments.
+                if a.canHaveMissingValue():
+                    # This will need an Optional or it's a variadic;
+                    # in both cases it should be const.
                     return True
                 if a.type.isUnion():
                     return True
                 if a.type.isSpiderMonkeyInterface():
                     return True
                 return False
             if needsConst(a):
                 arg = CGWrapper(arg, pre="Constify(", post=")")
@@ -6345,17 +6344,17 @@ def wrapTypeIntoCurrentCompartment(type,
                     "arguments: %s" % type)
 
 
 def wrapArgIntoCurrentCompartment(arg, value, isMember=True):
     """
     As wrapTypeIntoCurrentCompartment but handles things being optional
     """
     origValue = value
-    isOptional = arg.optional and not arg.defaultValue
+    isOptional = arg.canHaveMissingValue()
     if isOptional:
         value = value + ".Value()"
     wrap = wrapTypeIntoCurrentCompartment(arg.type, value, isMember)
     if wrap and isOptional:
         wrap = CGIfWrapper(wrap, "%s.WasPassed()" % origValue)
     return wrap
 
 
@@ -6852,18 +6851,17 @@ class CGMethodCall(CGThing):
                 else:
                     failureCode = None
                 type = distinguishingType(signature)
                 # The argument at index distinguishingIndex can't possibly be
                 # unset here, because we've already checked that argc is large
                 # enough that we can examine this argument.  But note that we
                 # still want to claim that optional arguments are optional, in
                 # case undefined was passed in.
-                argIsOptional = (distinguishingArgument(signature).optional and
-                                 not distinguishingArgument(signature).defaultValue)
+                argIsOptional = distinguishingArgument(signature).canHaveMissingValue()
                 testCode = instantiateJSToNativeConversion(
                     getJSToNativeConversionInfo(type, descriptor,
                                                 failureCode=failureCode,
                                                 isDefinitelyObject=isDefinitelyObject,
                                                 isNullOrUndefined=isNullOrUndefined,
                                                 isOptional=argIsOptional,
                                                 sourceDescription=(argDesc % (distinguishingIndex + 1))),
                     {
@@ -7139,16 +7137,19 @@ class FakeArgument():
             self.enforceRange = False
             self.clamp = False
 
         self.identifier = FakeIdentifier(name)
 
     def allowTreatNonCallableAsNull(self):
         return self._allowTreatNonCallableAsNull
 
+    def canHaveMissingValue(self):
+        return False
+
 
 class CGSetterCall(CGPerSignatureCall):
     """
     A class to generate a native object setter call for a particular IDL
     setter.
     """
     def __init__(self, argType, nativeMethodName, descriptor, attr):
         CGPerSignatureCall.__init__(self, None,
@@ -12521,18 +12522,17 @@ class CGNativeMember(ClassMethod):
             decl = CGTemplatedType("Optional", decl)
             ref = True
         return (decl, ref)
 
     def getArg(self, arg):
         """
         Get the full argument declaration for an argument
         """
-        decl, ref = self.getArgType(arg.type,
-                                    arg.optional and not arg.defaultValue,
+        decl, ref = self.getArgType(arg.type, arg.canHaveMissingValue(),
                                     "Variadic" if arg.variadic else False)
         if ref:
             decl = CGWrapper(decl, pre="const ", post="&")
 
         return Argument(decl.define(), arg.identifier.name)
 
     def arguments(self):
         return self.member.signatures()[0][1]
@@ -13601,17 +13601,17 @@ class CallbackMember(CGNativeMember):
     def getArgConversion(self, i, arg):
         argval = arg.identifier.name
 
         if arg.variadic:
             argval = argval + "[idx]"
             jsvalIndex = "%d + idx" % i
         else:
             jsvalIndex = "%d" % i
-            if arg.optional and not arg.defaultValue:
+            if arg.canHaveMissingValue():
                 argval += ".Value()"
         if arg.type.isDOMString():
             # XPConnect string-to-JS conversion wants to mutate the string.  So
             # let's give it a string it can mutate
             # XXXbz if we try to do a sequence of strings, this will kinda fail.
             result = "mutableStr"
             prepend = "nsString mutableStr(%s);\n" % argval
         else:
@@ -13644,17 +13644,17 @@ class CallbackMember(CGNativeMember):
                 """
                 for (uint32_t idx = 0; idx < ${arg}.Length(); ++idx) {
                   $*{conversion}
                 }
                 break;
                 """,
                 arg=arg.identifier.name,
                 conversion=conversion)
-        elif arg.optional and not arg.defaultValue:
+        elif arg.canHaveMissingValue():
             conversion = fill(
                 """
                 if (${argName}.WasPassed()) {
                   $*{conversion}
                 } else if (argc == ${iPlus1}) {
                   // This is our current trailing argument; reduce argc
                   --argc;
                 } else {
@@ -14378,17 +14378,17 @@ class CGEventMethod(CGNativeMember):
 
 
     def getArgs(self, returnType, argList):
         args = [self.getArg(arg) for arg in argList]
         return args
 
     def getArg(self, arg):
         decl, ref = self.getArgType(arg.type,
-                                    arg.optional and not arg.defaultValue,
+                                    arg.canHaveMissingValue(),
                                     "Variadic" if arg.variadic else False)
         if ref:
             decl = CGWrapper(decl, pre="const ", post="&")
 
         name = arg.identifier.name
         name = "a" + name[0].upper() + name[1:]
         return Argument(decl.define(), name)
 
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -3469,16 +3469,19 @@ class IDLArgument(IDLObjectWithIdentifie
         return self._allowTreatNonCallableAsNull
 
     def _getDependentObjects(self):
         deps = set([self.type])
         if self.defaultValue:
             deps.add(self.defaultValue)
         return deps
 
+    def canHaveMissingValue(self):
+        return self.optional and not self.defaultValue
+
 class IDLCallbackType(IDLType, IDLObjectWithScope):
     def __init__(self, location, parentScope, identifier, returnType, arguments):
         assert isinstance(returnType, IDLType)
 
         IDLType.__init__(self, location, identifier.name)
 
         self._returnType = returnType
         # Clone the list