Bug 780970 - Add [infallible] attribute for XPIDL attributes. r=khuey
authorJustin Lebar <justin.lebar@gmail.com>
Wed, 22 Aug 2012 18:27:04 -0700
changeset 109098 6c7efe05324138b63abb38ed31f32d1000312026
parent 109097 08f91bc1bd99976883cd79c8be9fe68edc660287
child 109099 bd0bf4b676dabbe74111442391e93ea21d641279
push id214
push userakeybl@mozilla.com
push dateWed, 14 Nov 2012 20:38:59 +0000
treeherdermozilla-release@c8b08ec8e1aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs780970
milestone17.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 780970 - Add [infallible] attribute for XPIDL attributes. r=khuey
xpcom/idl-parser/header.py
xpcom/idl-parser/xpidl.py
--- a/xpcom/idl-parser/header.py
+++ b/xpcom/idl-parser/header.py
@@ -133,16 +133,21 @@ include = """
 #include "%(basename)s.h"
 #endif
 """
 
 jspubtd_include = """
 #include "jspubtd.h"
 """
 
+infallible_includes = """
+#include "mozilla/Assertions.h"
+#include "mozilla/Util.h"
+"""
+
 header_end = """/* For IDL files that don't want to include root IDL files. */
 #ifndef NS_NO_VTABLE
 #define NS_NO_VTABLE
 #endif
 """
 
 footer = """
 #endif /* __gen_%(basename)s_h__ */
@@ -165,16 +170,23 @@ def print_header(idl, fd, filename):
         if not foundinc:
             foundinc = True
             fd.write('\n')
         fd.write(include % {'basename': idl_basename(inc.filename)})
 
     if idl.needsJSTypes():
         fd.write(jspubtd_include)
 
+    # Include some extra files if any attributes are infallible.
+    for iface in [p for p in idl.productions if p.kind == 'interface']:
+        for attr in [m for m in iface.members if isinstance(m, xpidl.Attribute)]:
+            if attr.infallible:
+                fd.write(infallible_includes)
+                break
+
     fd.write('\n')
     fd.write(header_end)
 
     for p in idl.productions:
         if p.kind == 'include': continue
         if p.kind == 'cdata':
             fd.write(p.data)
             continue
@@ -275,16 +287,26 @@ example_tmpl = """%(returntype)s %(implc
 }
 """
 
 iface_template_epilog = """/* End of implementation class template. */
 #endif
 
 """
 
+attr_infallible_tmpl = """\
+  inline %(realtype)s%(nativename)s(%(args)s)
+  {
+    %(realtype)sresult;
+    mozilla::DebugOnly<nsresult> rv = %(nativename)s(%(argnames)s&result);
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    return result;
+  }
+"""
+
 def write_interface(iface, fd):
     if iface.namemap is None:
         raise Exception("Interface was not resolved.")
 
     def write_const_decls(g):
         fd.write("  enum {\n")
         enums = []
         for c in g:
@@ -305,16 +327,23 @@ def write_interface(iface, fd):
         fd.write("  %s = 0;\n\n" % methodAsNative(m))
                                                                            
     def write_attr_decl(a):
         printComments(fd, a.doccomments, '  ')
 
         fd.write("  /* %s */\n" % a.toIDL());
 
         fd.write("  %s = 0;\n" % attributeAsNative(a, True))
+        if a.infallible:
+            fd.write(attr_infallible_tmpl %
+                     {'realtype': a.realtype.nativeType('in'),
+                      'nativename': attributeNativeName(a, getter=True),
+                      'args': '' if not a.implicit_jscontext else 'JSContext* cx',
+                      'argnames': '' if not a.implicit_jscontext else 'cx, '})
+
         if not a.readonly:
             fd.write("  %s = 0;\n" % attributeAsNative(a, False))
         fd.write("\n")
 
     defname = iface.name.upper()
     if iface.name[0:2] == 'ns':
         defname = 'NS_' + defname[2:]
 
--- a/xpcom/idl-parser/xpidl.py
+++ b/xpcom/idl-parser/xpidl.py
@@ -710,16 +710,17 @@ class Attribute(object):
     readonly = False
     implicit_jscontext = False
     nostdcall = False
     binaryname = None
     null = None
     undefined = None
     deprecated = False
     nullable = False
+    infallible = False
     defvalue = None
 
     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
@@ -765,16 +766,18 @@ class Attribute(object):
                 elif name == 'notxpcom':
                     self.notxpcom = True
                 elif name == 'implicit_jscontext':
                     self.implicit_jscontext = True
                 elif name == 'deprecated':
                     self.deprecated = True
                 elif name == 'nostdcall':
                     self.nostdcall = True
+                elif name == 'infallible':
+                    self.infallible = True
                 else:
                     raise IDLError("Unexpected attribute '%s'" % name, aloc)
 
     def resolve(self, iface):
         self.iface = iface
         self.realtype = iface.idl.getName(self.type, self.location)
         if (self.null is not None and
             getBuiltinOrNativeTypeName(self.realtype) != '[domstring]'):
@@ -783,16 +786,25 @@ class Attribute(object):
         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)
+        if self.infallible and not self.realtype.kind == 'builtin':
+            raise IDLError('[infallible] only works on builtin types '
+                           '(numbers, bool, and raw char types)',
+                           self.location)
+        if self.infallible and not iface.attributes.builtinclass:
+            raise IDLError('[infallible] attributes are only allowed on '
+                           '[builtinclass] interfaces',
+                           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