diff options
Diffstat (limited to 'xpcom/idl-parser/xpidl')
-rw-r--r-- | xpcom/idl-parser/xpidl/fixtures/xpctest.d.json | 56 | ||||
-rw-r--r-- | xpcom/idl-parser/xpidl/header.py | 2 | ||||
-rw-r--r-- | xpcom/idl-parser/xpidl/jsonxpt.py | 55 | ||||
-rwxr-xr-x | xpcom/idl-parser/xpidl/runtests.py | 2 | ||||
-rw-r--r-- | xpcom/idl-parser/xpidl/rust.py | 4 | ||||
-rw-r--r-- | xpcom/idl-parser/xpidl/typescript.py | 2 | ||||
-rwxr-xr-x | xpcom/idl-parser/xpidl/xpidl.py | 65 |
7 files changed, 71 insertions, 115 deletions
diff --git a/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json b/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json index fb3cb7e6b7..087a323dd4 100644 --- a/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json +++ b/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json @@ -95,14 +95,6 @@ [ "PRTime", "i64" - ], - [ - "char16_t", - "u16" - ], - [ - "nsresult", - "u32" ] ] }, @@ -259,14 +251,6 @@ [ "PRTime", "i64" - ], - [ - "char16_t", - "u16" - ], - [ - "nsresult", - "u32" ] ] }, @@ -373,14 +357,6 @@ [ "PRTime", "i64" - ], - [ - "char16_t", - "u16" - ], - [ - "nsresult", - "u32" ] ] }, @@ -434,14 +410,6 @@ [ "PRTime", "i64" - ], - [ - "char16_t", - "u16" - ], - [ - "nsresult", - "u32" ] ] }, @@ -1223,14 +1191,6 @@ [ "PRTime", "i64" - ], - [ - "char16_t", - "u16" - ], - [ - "nsresult", - "u32" ] ] }, @@ -1301,14 +1261,6 @@ [ "PRTime", "i64" - ], - [ - "char16_t", - "u16" - ], - [ - "nsresult", - "u32" ] ] }, @@ -1388,14 +1340,6 @@ [ "PRTime", "i64" - ], - [ - "char16_t", - "u16" - ], - [ - "nsresult", - "u32" ] ] } diff --git a/xpcom/idl-parser/xpidl/header.py b/xpcom/idl-parser/xpidl/header.py index 7f6c65dfc0..ed179b1bad 100644 --- a/xpcom/idl-parser/xpidl/header.py +++ b/xpcom/idl-parser/xpidl/header.py @@ -339,8 +339,6 @@ def print_header(idl, fd, filename, relpath): write_interface(p, fd) continue if p.kind == "typedef": - if p.substitute: - continue printComments(fd, p.doccomments, "") fd.write("typedef %s %s;\n\n" % (p.realtype.nativeType("in"), p.name)) diff --git a/xpcom/idl-parser/xpidl/jsonxpt.py b/xpcom/idl-parser/xpidl/jsonxpt.py index 342188f645..4a7fea7bf5 100644 --- a/xpcom/idl-parser/xpidl/jsonxpt.py +++ b/xpcom/idl-parser/xpidl/jsonxpt.py @@ -17,6 +17,7 @@ TypeMap = { # builtins "boolean": "TD_BOOL", "void": "TD_VOID", + "int8_t": "TD_INT8", "int16_t": "TD_INT16", "int32_t": "TD_INT32", "int64_t": "TD_INT64", @@ -24,19 +25,14 @@ TypeMap = { "uint16_t": "TD_UINT16", "uint32_t": "TD_UINT32", "uint64_t": "TD_UINT64", - "octet": "TD_UINT8", - "short": "TD_INT16", - "long": "TD_INT32", - "long long": "TD_INT64", - "unsigned short": "TD_UINT16", - "unsigned long": "TD_UINT32", - "unsigned long long": "TD_UINT64", + "nsresult": "TD_UINT32", "float": "TD_FLOAT", "double": "TD_DOUBLE", "char": "TD_CHAR", "string": "TD_PSTRING", "wchar": "TD_WCHAR", "wstring": "TD_PWSTRING", + "char16_t": "TD_UINT16", # special types "nsid": "TD_NSID", "astring": "TD_ASTRING", @@ -51,7 +47,7 @@ def flags(*flags): return [flag for flag, cond in flags if cond] -def get_type(type, calltype, iid_is=None, size_is=None): +def get_type(type, calltype, iid_is=None, size_is=None, needs_scriptable=None): while isinstance(type, xpidl.Typedef): type = type.realtype @@ -67,7 +63,7 @@ def get_type(type, calltype, iid_is=None, size_is=None): # This allows Arrays of InterfaceIs types to work. return { "tag": "TD_ARRAY", - "element": get_type(type.type, calltype, iid_is), + "element": get_type(type.type, calltype, iid_is, None, needs_scriptable), } if isinstance(type, xpidl.LegacyArray): @@ -76,10 +72,12 @@ def get_type(type, calltype, iid_is=None, size_is=None): return { "tag": "TD_LEGACY_ARRAY", "size_is": size_is, - "element": get_type(type.type, calltype, iid_is), + "element": get_type(type.type, calltype, iid_is, None, needs_scriptable), } if isinstance(type, xpidl.Interface) or isinstance(type, xpidl.Forward): + if isinstance(needs_scriptable, set): + needs_scriptable.add(type.name) return { "tag": "TD_INTERFACE_TYPE", "name": type.name, @@ -136,7 +134,7 @@ def mk_method(method, params, getter=0, setter=0, optargc=0, hasretval=0, symbol "flags": flags( ("getter", getter), ("setter", setter), - ("hidden", method.noscript or method.notxpcom), + ("hidden", not method.isScriptable()), ("optargc", optargc), ("jscontext", method.implicit_jscontext), ("hasretval", hasretval), @@ -167,6 +165,9 @@ def build_interface(iface): consts = [] methods = [] + # Interfaces referenced from scriptable members need to be [scriptable]. + needs_scriptable = set() + def build_const(c): consts.append( { @@ -186,7 +187,7 @@ def build_interface(iface): } ) - def build_method(m): + def build_method(m, needs_scriptable=None): params = [] for p in m.params: params.append( @@ -196,6 +197,7 @@ def build_interface(iface): p.paramtype, iid_is=attr_param_idx(p, m, "iid_is"), size_is=attr_param_idx(p, m, "size_is"), + needs_scriptable=needs_scriptable, ), in_=p.paramtype.count("in"), out=p.paramtype.count("out"), @@ -206,33 +208,36 @@ def build_interface(iface): hasretval = len(m.params) > 0 and m.params[-1].retval if not m.notxpcom and m.realtype.name != "void": hasretval = True - params.append(mk_param(get_type(m.realtype, "out"), out=1)) + type = get_type(m.realtype, "out", needs_scriptable=needs_scriptable) + params.append(mk_param(type, out=1)) methods.append( mk_method(m, params, optargc=m.optional_argc, hasretval=hasretval) ) - def build_attr(a): + def build_attr(a, needs_scriptable=None): assert a.realtype.name != "void" + # Write the getter getter_params = [] if not a.notxpcom: - getter_params.append(mk_param(get_type(a.realtype, "out"), out=1)) + type = get_type(a.realtype, "out", needs_scriptable=needs_scriptable) + getter_params.append(mk_param(type, out=1)) methods.append(mk_method(a, getter_params, getter=1, hasretval=1)) # And maybe the setter if not a.readonly: - param = mk_param(get_type(a.realtype, "in"), in_=1) - methods.append(mk_method(a, [param], setter=1)) + type = get_type(a.realtype, "in", needs_scriptable=needs_scriptable) + methods.append(mk_method(a, [mk_param(type, in_=1)], setter=1)) for member in iface.members: if isinstance(member, xpidl.ConstMember): build_const(member) elif isinstance(member, xpidl.Attribute): - build_attr(member) + build_attr(member, member.isScriptable() and needs_scriptable) elif isinstance(member, xpidl.Method): - build_method(member) + build_method(member, member.isScriptable() and needs_scriptable) elif isinstance(member, xpidl.CEnum): build_cenum(member) elif isinstance(member, xpidl.CDATA): @@ -240,12 +245,24 @@ def build_interface(iface): else: raise Exception("Unexpected interface member: %s" % member) + for ref in set(needs_scriptable): + p = iface.idl.getName(xpidl.TypeId(ref), None) + if isinstance(p, xpidl.Interface): + needs_scriptable.remove(ref) + if not p.attributes.scriptable: + raise Exception( + f"Scriptable member in {iface.name} references non-scriptable {ref}. " + "The interface must be marked as [scriptable], " + "or the referencing member with [noscript]." + ) + return { "name": iface.name, "uuid": iface.attributes.uuid, "methods": methods, "consts": consts, "parent": iface.base, + "needs_scriptable": sorted(needs_scriptable), "flags": flags( ("function", iface.attributes.function), ("builtinclass", iface.attributes.builtinclass), diff --git a/xpcom/idl-parser/xpidl/runtests.py b/xpcom/idl-parser/xpidl/runtests.py index b889d40010..940f845b9b 100755 --- a/xpcom/idl-parser/xpidl/runtests.py +++ b/xpcom/idl-parser/xpidl/runtests.py @@ -102,7 +102,7 @@ void bar(); self.assertEqual(xpidl.TypeId("long"), m.params[2].type) self.assertEqual("in", m.params[2].paramtype) self.assertTrue(isinstance(m.params[2].realtype, xpidl.LegacyArray)) - self.assertEqual("long", m.params[2].realtype.type.name) + self.assertEqual("int32_t", m.params[2].realtype.type.name) def testAttribute(self): i = self.p.parse( diff --git a/xpcom/idl-parser/xpidl/rust.py b/xpcom/idl-parser/xpidl/rust.py index 5d906d85ea..71ad5e98c8 100644 --- a/xpcom/idl-parser/xpidl/rust.py +++ b/xpcom/idl-parser/xpidl/rust.py @@ -363,10 +363,6 @@ def print_rust_bindings(idl, fd, relpath): if p.kind == "typedef": try: - # Skip bool and C++ stdint typedefs marked with [substitute]. - if p.substitute: - continue - if printdoccomments: fd.write( "/// `typedef %s %s;`\n///\n" diff --git a/xpcom/idl-parser/xpidl/typescript.py b/xpcom/idl-parser/xpidl/typescript.py index 614a328edf..9c374141d1 100644 --- a/xpcom/idl-parser/xpidl/typescript.py +++ b/xpcom/idl-parser/xpidl/typescript.py @@ -68,7 +68,7 @@ def ts_interface(iface): def ts_typedefs(idl): for p in idl.getNames(): - if isinstance(p, xpidl.Typedef) and not p.substitute: + if isinstance(p, xpidl.Typedef): try: yield (p.name, p.realtype.tsType()) except xpidl.TSNoncompat: diff --git a/xpcom/idl-parser/xpidl/xpidl.py b/xpcom/idl-parser/xpidl/xpidl.py index 19d042d1b0..11b5d05e58 100755 --- a/xpcom/idl-parser/xpidl/xpidl.py +++ b/xpcom/idl-parser/xpidl/xpidl.py @@ -184,19 +184,26 @@ class Builtin(object): builtinNames = [ Builtin("boolean", "bool", "bool", "boolean"), Builtin("void", "void", "libc::c_void", "void"), - Builtin("octet", "uint8_t", "u8", "u8", False, True), - Builtin("short", "int16_t", "i16", "i16", True, True), - Builtin("long", "int32_t", "i32", "i32", True, True), - Builtin("long long", "int64_t", "i64", "i64", True, True), - Builtin("unsigned short", "uint16_t", "u16", "u16", False, True), - Builtin("unsigned long", "uint32_t", "u32", "u32", False, True), - Builtin("unsigned long long", "uint64_t", "u64", "u64", False, True), + Builtin("int8_t", "int8_t", "i8", "i8", True, True), + Builtin("int16_t", "int16_t", "i16", "i16", True, True), + Builtin("int32_t", "int32_t", "i32", "i32", True, True), + Builtin("int64_t", "int64_t", "i64", "i64", True, True), + Builtin("uint8_t", "uint8_t", "u8", "u8", False, True), + Builtin("uint16_t", "uint16_t", "u16", "u16", False, True), + Builtin("uint32_t", "uint32_t", "u32", "u32", False, True), + Builtin("uint64_t", "uint64_t", "u64", "u64", False, True), + Builtin("nsresult", "nsresult", "nserror::nsresult", "nsresult"), Builtin("float", "float", "libc::c_float", "float"), Builtin("double", "double", "libc::c_double", "double"), Builtin("char", "char", "libc::c_char", "string"), Builtin("string", "char *", "*const libc::c_char", "string"), Builtin("wchar", "char16_t", "u16", "string"), Builtin("wstring", "char16_t *", "*const u16", "string"), + # NOTE: char16_t is the same type as `wchar` in C++, however it is reflected + # into JS as an integer, allowing it to be used in constants. + # This inconsistency sucks, but reflects existing usage so unfortunately + # isn't very easy to change. + Builtin("char16_t", "char16_t", "u16", "u16", False, True), # As seen in mfbt/RefCountType.h, this type has special handling to # maintain binary compatibility with MSCOM's IUnknown that cannot be # expressed in XPIDL. @@ -208,10 +215,24 @@ builtinNames = [ ), ] +# Allow using more C-style names for the basic integer types. +builtinAlias = [ + ("octet", "uint8_t"), + ("unsigned short", "uint16_t"), + ("unsigned long", "uint32_t"), + ("unsigned long long", "uint64_t"), + ("short", "int16_t"), + ("long", "int32_t"), + ("long long", "int64_t"), +] + builtinMap = {} for b in builtinNames: builtinMap[b.name] = b +for alias, name in builtinAlias: + builtinMap[alias] = builtinMap[name] + class Location(object): _line = None @@ -486,14 +507,6 @@ class Typedef(object): self.location = location self.doccomments = doccomments - # C++ stdint types and the bool typedef from nsrootidl.idl are marked - # with [substitute], and emit as the underlying builtin type directly. - self.substitute = False - for name, value, aloc in attlist: - if name != "substitute" or value is not None: - raise IDLError(f"Unexpected attribute {name}({value})", aloc) - self.substitute = True - def __eq__(self, other): return self.name == other.name and self.type == other.type @@ -505,24 +518,12 @@ class Typedef(object): raise IDLError("Unsupported typedef target type", self.location) def nativeType(self, calltype): - if self.substitute: - return self.realtype.nativeType(calltype) - return "%s %s" % (self.name, "*" if "out" in calltype else "") def rustType(self, calltype): - if self.substitute: - return self.realtype.rustType(calltype) - - if self.name == "nsresult": - return "%s::nserror::nsresult" % ("*mut " if "out" in calltype else "") - return "%s%s" % ("*mut " if "out" in calltype else "", self.name) def tsType(self): - if self.substitute: - return self.realtype.tsType() - return self.name def __str__(self): @@ -1081,7 +1082,7 @@ class ConstMember(object): basetype = basetype.realtype if not isinstance(basetype, Builtin) or not basetype.maybeConst: raise IDLError( - "const may only be a short or long type, not %s" % self.type, + "const may only be an integer type, not %s" % self.type.name, self.location, ) @@ -1440,9 +1441,9 @@ class Method(object): "size_is parameter of an input must also be an input", p.location, ) - if getBuiltinOrNativeTypeName(size_param.realtype) != "unsigned long": + if getBuiltinOrNativeTypeName(size_param.realtype) != "uint32_t": raise IDLError( - "size_is parameter must have type 'unsigned long'", + "size_is parameter must have type 'uint32_t'", p.location, ) if p.iid_is: @@ -1688,8 +1689,8 @@ TypeId = namedtuple("TypeId", "name params") # Make str(TypeId) produce a nicer value -TypeId.__str__ = ( - lambda self: "%s<%s>" % (self.name, ", ".join(str(p) for p in self.params)) +TypeId.__str__ = lambda self: ( + "%s<%s>" % (self.name, ", ".join(str(p) for p in self.params)) if self.params is not None else self.name ) |