Bug 721569 - Implement nullable types. r=khuey
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Mon, 12 Mar 2012 21:44:51 -0700
changeset 91698 c7f4e6a7f6274b1fbdcb6f6b60f3d58eb767df46
parent 91697 4d64d2d31843f0f9b7b2385c6b100eb6a636e18b
child 91699 95a8eba120fef6f01ba4c02115a9ae2c0413cceb
push id783
push userlsblakk@mozilla.com
push dateTue, 24 Apr 2012 17:33:42 +0000
treeherdermozilla-beta@11faed19f136 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs721569
milestone13.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 721569 - Implement nullable types. r=khuey
dom/interfaces/storage/nsIDOMStorageEvent.idl
dom/src/storage/nsDOMStorage.cpp
js/xpconnect/src/dictionary_helper_gen.py
xpcom/idl-parser/xpidl.py
--- a/dom/interfaces/storage/nsIDOMStorageEvent.idl
+++ b/dom/interfaces/storage/nsIDOMStorageEvent.idl
@@ -93,13 +93,13 @@ interface nsIDOMStorageEvent : nsIDOMEve
                         in DOMString newValueArg,
                         in DOMString urlArg,
                         in nsIDOMStorage storageAreaArg);
 };
 
 dictionary StorageEventInit : EventInit
 {
   DOMString key;
-  DOMString oldValue;
-  DOMString newValue;
+  DOMString? oldValue;
+  DOMString? newValue;
   DOMString url;
   nsIDOMStorage storageArea;
 };
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -2391,18 +2391,16 @@ NS_IMETHODIMP nsDOMStorageEvent::InitSto
   return NS_OK;
 }
 
 nsresult
 nsDOMStorageEvent::InitFromCtor(const nsAString& aType,
                                 JSContext* aCx, jsval* aVal)
 {
   mozilla::dom::StorageEventInit d;
-  d.oldValue.SetIsVoid(true);
-  d.newValue.SetIsVoid(true);
   nsresult rv = d.Init(aCx, aVal);
   NS_ENSURE_SUCCESS(rv, rv);
   return InitStorageEvent(aType, d.bubbles, d.cancelable, d.key, d.oldValue,
                           d.newValue, d.url, d.storageArea);
 }
 
 // Obsolete globalStorage event
 
--- a/js/xpconnect/src/dictionary_helper_gen.py
+++ b/js/xpconnect/src/dictionary_helper_gen.py
@@ -335,17 +335,20 @@ def write_getter(a, iface, fd):
         fd.write("    aDict.%s = b;\n" % a.name)
     elif realtype.count("PRInt32"):
         fd.write("    NS_ENSURE_STATE(JS_ValueToECMAInt32(aCx, v, &aDict.%s));\n" % a.name)
     elif realtype.count("PRUint16"):
         fd.write("    uint32_t u;\n")
         fd.write("    NS_ENSURE_STATE(JS_ValueToECMAUint32(aCx, v, &u));\n")
         fd.write("    aDict.%s = u;\n" % a.name)
     elif realtype.count("nsAString"):
-        fd.write("    xpc_qsDOMString d(aCx, v, &v, xpc_qsDOMString::eStringify, xpc_qsDOMString::eStringify);\n")
+        if a.nullable:
+            fd.write("    xpc_qsDOMString d(aCx, v, &v, xpc_qsDOMString::eNull, xpc_qsDOMString::eNull);\n")
+        else:
+            fd.write("    xpc_qsDOMString d(aCx, v, &v, xpc_qsDOMString::eStringify, xpc_qsDOMString::eStringify);\n")
         fd.write("    NS_ENSURE_STATE(d.IsValid());\n")
         fd.write("    aDict.%s = d;\n" % a.name)
     elif realtype.count("nsIVariant"):
         fd.write("    nsCOMPtr<nsIVariant> d(already_AddRefed<nsIVariant>(XPCVariant::newVariant(ccx, v)));\n")
         fd.write("    NS_ENSURE_STATE(d);\n")
         fd.write("    aDict.%s = d;\n" % a.name)
     elif realtype.endswith('*'):
         fd.write("    %s d;\n" % realtype)
@@ -373,17 +376,25 @@ def write_cpp(iface, fd):
             fd.write(",\n")
 
     for i in range(len(attributes)):
         fd.write("  %s(%s)" % (attributes[i].name, init_value(attributes[i])))
         if i < (len(attributes) - 1):
             fd.write(",")
         fd.write("\n")
 
-    fd.write("  {}\n\n")
+    fd.write("{")
+    hasnullable = False
+    for i in range(len(attributes)):
+        if attributes[i].nullable:
+            hasnullable = True
+            fd.write("\n  %s.SetIsVoid(true);" % attributes[i].name)
+    if hasnullable:
+        fd.write("\n")
+    fd.write("}\n\n")
     fd.write("%s::~%s() {}\n\n" % (iface.name, iface.name))
 
     fd.write("static nsresult\n%s_InitInternal(%s& aDict, JSContext* aCx, JSObject* aObj)\n" %
              (iface.name, iface.name))
     fd.write("{\n")
     if iface.base is not None:
         fd.write("  nsresult rv = %s_InitInternal(aDict, aCx, aObj);\n" %
                  iface.base)
--- a/xpcom/idl-parser/xpidl.py
+++ b/xpcom/idl-parser/xpidl.py
@@ -735,23 +735,25 @@ class Attribute(object):
     notxpcom = False
     readonly = False
     implicit_jscontext = False
     nostdcall = False
     binaryname = None
     null = None
     undefined = None
     deprecated = False
+    nullable = False
     defvalue = None
 
-    def __init__(self, type, name, attlist, readonly, defvalue, location, doccomments):
+    def __init__(self, type, name, attlist, readonly, nullable, defvalue, location, doccomments):
         self.type = type
         self.name = name
         self.attlist = attlist
         self.readonly = readonly
+        self.nullable = nullable
         self.defvalue = defvalue
         self.location = location
         self.doccomments = doccomments
 
         for name, value, aloc in attlist:
             if name == 'binaryname':
                 if value is None:
                     raise IDLError("binaryname attribute requires a value",
@@ -803,16 +805,20 @@ class Attribute(object):
         if (self.null is not None and
             getBuiltinOrNativeTypeName(self.realtype) != '[domstring]'):
             raise IDLError("'Null' attribute can only be used on DOMString",
                            self.location)
         if (self.undefined is not None and
             getBuiltinOrNativeTypeName(self.realtype) != '[domstring]'):
             raise IDLError("'Undefined' attribute can only be used on DOMString",
                            self.location)
+        if (self.nullable and
+            getBuiltinOrNativeTypeName(self.realtype) != '[domstring]'):
+            raise IDLError("Nullable types (T?) is supported only for DOMString",
+                           self.location)
 
     def toIDL(self):
         attribs = attlistToIDL(self.attlist)
         readonly = self.readonly and 'readonly ' or ''
         return "%s%sattribute %s %s;" % (attribs, readonly, self.type, self.name)
         
     def isScriptable(self):
         if not self.iface.attributes.scriptable: return False
@@ -1105,17 +1111,17 @@ class IDLParser(object):
 
     hexchar = r'[a-fA-F0-9]'
 
     t_NUMBER = r'-?\d+'
     t_HEXNUM = r'0x%s+' % hexchar
     t_LSHIFT = r'<<'
     t_RSHIFT=  r'>>'
 
-    literals = '"(){}[],;:=|+-*'
+    literals = '"(){}[],;:=|+-*?'
 
     t_ignore = ' \t'
 
     def t_multilinecomment(self, t):
         r'/\*(?s).*?\*/'
         t.lexer.lineno += t.value.count('\n')
         if t.value.startswith("/**"):
             self._doccomments.append(t.value)
@@ -1387,16 +1393,17 @@ class IDLParser(object):
             doccomments = p[2]
         else:
             doccomments = p.slice[3].doccomments
 
         p[0] = Attribute(type=p[4],
                          name=p[5],
                          attlist=p[1]['attlist'],
                          readonly=p[2] is not None,
+                         nullable=False,
                          defvalue=None,
                          location=self.getLocation(p, 3),
                          doccomments=doccomments)
 
     def p_member_method(self, p):
         """member : attributes IDENTIFIER IDENTIFIER '(' paramlist ')' raises ';'"""
         if 'doccomments' in p[1]:
             doccomments = p[1]['doccomments']
@@ -1480,30 +1487,39 @@ class IDLParser(object):
         p[0] = []
 
     def p_dictmembers_continue(self, p):
         """dictmembers : dictmember dictmembers"""
         p[0] = list(p[2])
         p[0].insert(0, p[1])
 
     def p_dictmember(self, p):
-        """dictmember : attributes IDENTIFIER IDENTIFIER optdefvalue ';'"""
+        """dictmember : attributes IDENTIFIER optnullable IDENTIFIER optdefvalue ';'"""
         if 'doccomments' in p[1]:
             doccomments = p[1]['doccomments']
         else:
             doccomments = p.slice[2].doccomments
 
         p[0] = Attribute(type=p[2],
-                         name=p[3],
+                         name=p[4],
                          attlist=p[1]['attlist'],
                          readonly=False,
-                         defvalue=p[4],
+                         nullable=p[3] is not None,
+                         defvalue=p[5],
                          location=self.getLocation(p, 1),
                          doccomments=doccomments)
 
+    def p_optnullable(self, p):
+        """optnullable : '?'
+                       | """
+        if len(p) > 1:
+            p[0] = p[1]
+        else:
+            p[0] = None
+
     def p_optdefvalue(self, p):
         """optdefvalue : '=' STRING
                        | """
         if len(p) > 1:
             p[0] = p[2]
         else:
             p[0] = None