Bug 742206 part 3. Implement type conversions for Date in WebIDL. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 02 May 2013 14:38:20 -0400
changeset 141590 3a8c503744ea5f2a14893e4ea385812c7f28c90b
parent 141589 c4013f62540efc1c95fd7351006ecbb76b0a06a8
child 141591 2f0d5fc274edbc5a8d3f95af11398a58267bf216
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs742206
milestone23.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 742206 part 3. Implement type conversions for Date in WebIDL. r=smaug
dom/bindings/Codegen.py
dom/bindings/Errors.msg
dom/bindings/test/TestBindingHeader.h
dom/bindings/test/TestCodeGen.webidl
dom/bindings/test/TestExampleGen.webidl
dom/bindings/test/TestJSImplGen.webidl
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2507,17 +2507,17 @@ def getJSToNativeConversionTemplate(type
         return handleDefault(template, codeToSetNull)
 
     # A helper function for wrapping up the template body for
     # possibly-nullable objecty stuff
     def wrapObjectTemplate(templateBody, type, codeToSetNull, failureCode=None):
         if isNullOrUndefined:
             assert type.nullable()
             # Just ignore templateBody and set ourselves to null.
-            # Note that wedon't have to worry about default values
+            # Note that we don't have to worry about default values
             # here either, since we already examined this value.
             return "%s;" % codeToSetNull
 
         if not isDefinitelyObject:
             # Handle the non-object cases by wrapping up the whole
             # thing in an if cascade.
             templateBody = (
                 "if (${val}.isObject()) {\n" +
@@ -3299,16 +3299,43 @@ for (uint32_t i = 0; i < length; ++i) {
         return (template, declType, None, False)
 
     if type.isVoid():
         assert not isOptional
         # This one only happens for return values, and its easy: Just
         # ignore the jsval.
         return ("", None, None, False)
 
+    if type.isDate():
+        assert not isEnforceRange and not isClamp
+
+        declType = CGGeneric("Date")
+        if type.nullable():
+            declType = CGTemplatedType("Nullable", declType)
+            dateVal = "${declName}.SetValue()"
+        else:
+            dateVal = "${declName}"
+
+        if failureCode is None:
+            notDate = ("ThrowErrorMessage(cx, MSG_NOT_DATE);\n"
+                       "%s" % exceptionCode)
+        else:
+            notDate = failureCode
+
+        conversion = (
+            "if (!JS_ObjectIsDate(cx, &${val}.toObject()) ||\n"
+            "    !%s.SetTimeStamp(cx, &${val}.toObject())) {\n"
+            "%s\n"
+            "}" %
+            (dateVal, CGIndenter(CGGeneric(notDate)).define()))
+
+        conversion = wrapObjectTemplate(conversion, type,
+                                        "${declName}.SetNull()")
+        return (conversion, declType, None, isOptional)
+
     if not type.isPrimitive():
         raise TypeError("Need conversion for argument type '%s'" % str(type))
 
     typeName = builtinNames[type.tag()]
 
     conversionBehavior = "eDefault"
     if isEnforceRange:
         assert type.isInteger()
@@ -3804,31 +3831,34 @@ if (!returnArray) {
     if type.isUnion():
         if type.nullable():
             prefix = "%s->"
         else:
             prefix = "%s."
         return (wrapAndSetPtr((prefix % result) +
                               "ToJSVal(cx, ${obj}, ${jsvalPtr})"), False)
 
-    if not (type.isPrimitive() or type.isDictionary()):
+    if not (type.isPrimitive() or type.isDictionary() or type.isDate()):
         raise TypeError("Need to learn to wrap %s" % type)
 
     if type.nullable():
         (recTemplate, recInfal) = getWrapTemplateForType(type.inner, descriptorProvider,
                                                          "%s.Value()" % result, successCode,
                                                          isCreator, exceptionCode)
         return ("if (%s.IsNull()) {\n" % result +
                 CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
                 "}\n" + recTemplate, recInfal)
 
     if type.isDictionary():
         return (wrapAndSetPtr("%s.ToObject(cx, ${obj}, ${jsvalPtr})" % result),
                 False)
 
+    if type.isDate():
+        return (wrapAndSetPtr("%s.ToDateObject(cx, ${jsvalPtr})" % result),
+                False)
 
     tag = type.tag()
 
     if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
                IDLType.Tags.uint16, IDLType.Tags.int32]:
         return (setValue("INT_TO_JSVAL(int32_t(%s))" % result), True)
 
     elif tag in [IDLType.Tags.int64, IDLType.Tags.uint64,
@@ -3985,16 +4015,21 @@ def getRetvalDeclarationForType(returnTy
             CGDictionary.makeDictionaryName(returnType.unroll().inner,
                                             descriptorProvider.workers) +
             "Initializer")
         if nullable:
             result = CGTemplatedType("Nullable", result)
         return result, True
     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
     raise TypeError("Don't know how to declare return value for %s" %
                     returnType)
 
 def isResultAlreadyAddRefed(descriptor, extendedAttributes):
     # Default to already_AddRefed on the main thread, raw pointer in workers
     return not descriptor.workers and not 'resultNotAddRefed' in extendedAttributes
 
 def needCx(returnType, arguments, extendedAttributes, descriptorProvider):
@@ -5228,16 +5263,18 @@ class CGMemberJITInfo(CGThing):
             u = t.unroll();
             if u.hasNullableType:
                 # Might be null or not
                 return "JSVAL_TYPE_UNKNOWN"
             return reduce(CGMemberJITInfo.getSingleReturnType,
                           u.flatMemberTypes, "")
         if t.isDictionary():
             return "JSVAL_TYPE_OBJECT"
+        if t.isDate():
+            return "JSVAL_TYPE_OBJECT"
         if not t.isPrimitive():
             raise TypeError("No idea what type " + str(t) + " is.")
         tag = t.tag()
         if tag in [IDLType.Tags.int8, IDLType.Tags.uint8,
                    IDLType.Tags.int16, IDLType.Tags.uint16,
                    IDLType.Tags.int32, IDLType.Tags.bool]:
             return "JSVAL_TYPE_INT32"
         if tag in [IDLType.Tags.int64, IDLType.Tags.uint64,
@@ -8036,16 +8073,22 @@ class CGNativeMember(ClassMethod):
                 returnCode = ("if (${declName}.IsNull()) {\n"
                               "  retval.SetNull();\n"
                               "} else {\n"
                               "  retval.SetValue().SwapElements(${declName}.Value());\n"
                               "}")
             else:
                 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};")
         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.isString():
             args.append(Argument("nsString&", "retval"))
@@ -8181,16 +8224,19 @@ class CGNativeMember(ClassMethod):
                 declType = "%s&"
             return (declType % "JSObject"), False, False
 
         if type.isDictionary():
             typeName = CGDictionary.makeDictionaryName(type.inner,
                                                        self.descriptor.workers)
             return typeName, True, True
 
+        if type.isDate():
+            return "Date", False, True
+
         assert type.isPrimitive()
 
         return builtinNames[type.tag()], False, True
 
     def getArgType(self, type, optional, variadic, isMember):
         """
         Get the type of an argument declaration.  Returns the type CGThing, and
         whether this should be a const ref.
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -32,8 +32,9 @@ MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 
 MSG_DEF(MSG_NOT_SEQUENCE, 0, "object can not be converted to a sequence")
 MSG_DEF(MSG_NOT_DICTIONARY, 0, "value can not be converted to a dictionary")
 MSG_DEF(MSG_INVALID_ARG, 2, "argument {0} is not valid for any of the {1}-argument overloads")
 MSG_DEF(MSG_GLOBAL_NOT_NATIVE, 0, "global is not a native object")
 MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, "The given encoding '{0}' is not supported.")
 MSG_DEF(MSG_DOM_ENCODING_NOT_UTF, 0, "The encoding must be utf-8, utf-16, or utf-16be.")
 MSG_DEF(MSG_NOT_FINITE, 0, "Floating-point value is not finite.")
 MSG_DEF(MSG_INVALID_VERSION, 0, "0 (Zero) is not a valid database version.")
+MSG_DEF(MSG_NOT_DATE, 0, "Value is not a date.")
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -464,16 +464,27 @@ public:
   //void PassUnionWithInterfaces(const TestInterfaceOrTestExternalInterface& arg);
   //void PassUnionWithInterfacesAndNullable(const TestInterfaceOrNullOrTestExternalInterface& arg);
   void PassUnionWithArrayBuffer(const ArrayBufferOrLong&);
   void PassUnionWithString(JSContext*, const StringOrObject&);
   //void PassUnionWithEnum(JSContext*, const TestEnumOrObject&);
   //void PassUnionWithCallback(JSContext*, const TestCallbackOrLong&);
   void PassUnionWithObject(JSContext*, const ObjectOrLong&);
 
+  // Date types
+  void PassDate(Date);
+  void PassNullableDate(const Nullable<Date>&);
+  void PassOptionalDate(const Optional<Date>&);
+  void PassOptionalNullableDate(const Optional<Nullable<Date> >&);
+  void PassOptionalNullableDateWithDefaultValue(const Nullable<Date>&);
+  void PassDateSequence(const Sequence<Date>&);
+  void PassNullableDateSequence(const Sequence<Nullable<Date> >&);
+  Date ReceiveDate();
+  Nullable<Date> ReceiveNullableDate();
+
   // binaryNames tests
   void MethodRenamedTo();
   void MethodRenamedTo(int8_t);
   int8_t AttributeGetterRenamedTo();
   int8_t AttributeRenamedTo();
   void SetAttributeRenamedTo(int8_t);
 
   // Dictionary tests
@@ -500,16 +511,17 @@ public:
   static void SetStaticAttribute(const GlobalObject&, bool);
 
   // Overload resolution tests
   bool Overload1(TestInterface&);
   TestInterface* Overload1(const nsAString&, TestInterface&);
   void Overload2(TestInterface&);
   void Overload2(JSContext*, const Dict&);
   void Overload2(const nsAString&);
+  void Overload2(Date);
   void Overload3(TestInterface&);
   void Overload3(const TestCallback&);
   void Overload3(const nsAString&);
   void Overload4(TestInterface&);
   void Overload4(TestCallbackInterface&);
   void Overload4(const nsAString&);
 
   // Variadic handling
@@ -712,16 +724,24 @@ private:
 
   // Make sure unions are always const
   void PassUnion(JSContext*, ObjectOrLong& arg) MOZ_DELETE;
   void PassUnionWithNullable(JSContext*, ObjectOrNullOrLong& arg) MOZ_DELETE;
   void PassNullableUnion(JSContext*, Nullable<ObjectOrLong>&) MOZ_DELETE;
   void PassOptionalUnion(JSContext*, Optional<ObjectOrLong>&) MOZ_DELETE;
   void PassOptionalNullableUnion(JSContext*, Optional<Nullable<ObjectOrLong> >&) MOZ_DELETE;
   void PassOptionalNullableUnionWithDefaultValue(JSContext*, Nullable<ObjectOrLong>&) MOZ_DELETE;
+
+  // Make sure various date stuff is const as needed
+  void PassNullableDate(Nullable<Date>&) MOZ_DELETE;
+  void PassOptionalDate(Optional<Date>&) MOZ_DELETE;
+  void PassOptionalNullableDate(Optional<Nullable<Date> >&) MOZ_DELETE;
+  void PassOptionalNullableDateWithDefaultValue(Nullable<Date>&) MOZ_DELETE;
+  void PassDateSequence(Sequence<Date>&) MOZ_DELETE;
+  void PassNullableDateSequence(Sequence<Nullable<Date> >&) MOZ_DELETE;
 };
 
 class TestIndexedGetterInterface : public nsISupports,
                                    public nsWrapperCache
 {
 public:
   NS_DECL_ISUPPORTS
 
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -423,16 +423,27 @@ interface TestInterface {
   void passUnionWithString((DOMString or object) arg);
   //void passUnionWithEnum((TestEnum or object) arg);
   // Trying to use a callback in a union won't include the test
   // headers, unfortunately, so won't compile.
   //void passUnionWithCallback((TestCallback or long) arg);
   void passUnionWithObject((object or long) arg);
   //void passUnionWithDict((Dict or long) arg);
 
+  // Date types
+  void passDate(Date arg);
+  void passNullableDate(Date? arg);
+  void passOptionalDate(optional Date arg);
+  void passOptionalNullableDate(optional Date? arg);
+  void passOptionalNullableDateWithDefaultValue(optional Date? arg = null);
+  void passDateSequence(sequence<Date> arg);
+  void passNullableDateSequence(sequence<Date?> arg);
+  Date receiveDate();
+  Date? receiveNullableDate();
+
   // binaryNames tests
   void methodRenamedFrom();
   void methodRenamedFrom(byte argument);
   readonly attribute byte attributeGetterRenamedFrom;
   attribute byte attributeRenamedFrom;
 
   void passDictionary(optional Dict x);
   Dict receiveDictionary();
@@ -463,16 +474,17 @@ interface TestInterface {
 
   // Overload resolution tests
   //void overload1(DOMString... strs);
   boolean overload1(TestInterface arg);
   TestInterface overload1(DOMString strs, TestInterface arg);
   void overload2(TestInterface arg);
   void overload2(optional Dict arg);
   void overload2(DOMString arg);
+  void overload2(Date arg);
   void overload3(TestInterface arg);
   void overload3(TestCallback arg);
   void overload3(DOMString arg);
   void overload4(TestInterface arg);
   void overload4(TestCallbackInterface arg);
   void overload4(DOMString arg);
 
   // Variadic handling
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -317,16 +317,27 @@ interface TestExampleInterface {
   void passUnionWithString((DOMString or object) arg);
   //void passUnionWithEnum((TestEnum or object) arg);
   // Trying to use a callback in a union won't include the test
   // headers, unfortunately, so won't compile.
   //  void passUnionWithCallback((TestCallback or long) arg);
   void passUnionWithObject((object or long) arg);
   //void passUnionWithDict((Dict or long) arg);
 
+  // Date types
+  void passDate(Date arg);
+  void passNullableDate(Date? arg);
+  void passOptionalDate(optional Date arg);
+  void passOptionalNullableDate(optional Date? arg);
+  void passOptionalNullableDateWithDefaultValue(optional Date? arg = null);
+  void passDateSequence(sequence<Date> arg);
+  void passNullableDateSequence(sequence<Date?> arg);
+  Date receiveDate();
+  Date? receiveNullableDate();
+
   // binaryNames tests
   void methodRenamedFrom();
   void methodRenamedFrom(byte argument);
   readonly attribute byte attributeGetterRenamedFrom;
   attribute byte attributeRenamedFrom;
 
   void passDictionary(optional Dict x);
   //UNSUPPORTED  Dict receiveDictionary();
@@ -357,16 +368,17 @@ interface TestExampleInterface {
 
   // Overload resolution tests
   //void overload1(DOMString... strs);
   boolean overload1(TestInterface arg);
   TestInterface overload1(DOMString strs, TestInterface arg);
   void overload2(TestInterface arg);
   void overload2(optional Dict arg);
   void overload2(DOMString arg);
+  void overload2(Date arg);
   void overload3(TestInterface arg);
   void overload3(TestCallback arg);
   void overload3(DOMString arg);
   void overload4(TestInterface arg);
   void overload4(TestCallbackInterface arg);
   void overload4(DOMString arg);
 
   // Variadic handling
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -340,16 +340,27 @@ interface TestJSImplInterface {
   void passUnionWithString((DOMString or object) arg);
   //void passUnionWithEnum((MyTestEnum or object) arg);
   // Trying to use a callback in a union won't include the test
   // headers, unfortunately, so won't compile.
   //  void passUnionWithCallback((MyTestCallback or long) arg);
   void passUnionWithObject((object or long) arg);
   //void passUnionWithDict((Dict or long) arg);
 
+  // Date types
+  void passDate(Date arg);
+  void passNullableDate(Date? arg);
+  void passOptionalDate(optional Date arg);
+  void passOptionalNullableDate(optional Date? arg);
+  void passOptionalNullableDateWithDefaultValue(optional Date? arg = null);
+  void passDateSequence(sequence<Date> arg);
+  void passNullableDateSequence(sequence<Date?> arg);
+  Date receiveDate();
+  Date? receiveNullableDate();
+
   // 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
@@ -385,16 +396,17 @@ interface TestJSImplInterface {
 
   // Overload resolution tests
   //void overload1(DOMString... strs);
   boolean overload1(TestJSImplInterface arg);
   TestJSImplInterface overload1(DOMString strs, TestJSImplInterface arg);
   void overload2(TestJSImplInterface arg);
   void overload2(optional Dict arg);
   void overload2(DOMString arg);
+  void overload2(Date arg);
   void overload3(TestJSImplInterface arg);
   void overload3(MyTestCallback arg);
   void overload3(DOMString arg);
   void overload4(TestJSImplInterface arg);
   void overload4(TestCallbackInterface arg);
   void overload4(DOMString arg);
 
   // Variadic handling