summaryrefslogtreecommitdiffstats
path: root/xpcom/idl-parser/xpidl
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/idl-parser/xpidl')
-rw-r--r--xpcom/idl-parser/xpidl/fixtures/xpctest.d.json56
-rw-r--r--xpcom/idl-parser/xpidl/header.py2
-rw-r--r--xpcom/idl-parser/xpidl/jsonxpt.py55
-rwxr-xr-xxpcom/idl-parser/xpidl/runtests.py2
-rw-r--r--xpcom/idl-parser/xpidl/rust.py4
-rw-r--r--xpcom/idl-parser/xpidl/typescript.py2
-rwxr-xr-xxpcom/idl-parser/xpidl/xpidl.py65
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
)