Bug 1444991 - Part 2: Parse webidl productions in xpidl, r=mccr8

They are parsed into a WebIDL object, and lowered into C++, Rust, and XPT.

For C++ code, we generate a correctly namespaced forward declaration. In Rust,
the types are exposed as `*const c_void`, as we don't have WebIDL type
information there.

The XPT code generator needs to know the header filename in order to perform
correct codegen, so we also get that information.
This commit is contained in:
Nika Layzell 2018-04-06 18:22:14 -04:00
parent be8b24333a
commit 6969209b41
3 changed files with 73 additions and 1 deletions

View File

@ -233,6 +233,9 @@ def print_header(idl, fd, filename):
fd.write(p.data)
continue
if p.kind == 'webidl':
write_webidl(p, fd)
continue
if p.kind == 'forward':
fd.write(forward_decl % {'name': p.name})
continue
@ -246,6 +249,17 @@ def print_header(idl, fd, filename):
fd.write(footer % {'basename': idl_basename(filename)})
def write_webidl(p, fd):
path = p.native.split('::')
for seg in path[:-1]:
fd.write("namespace %s {\n" % seg)
fd.write("class %s; /* webidl %s */\n" % (path[-1], p.name))
for seg in reversed(path[:-1]):
fd.write("} // namespace %s\n" % seg)
fd.write("\n")
iface_header = r"""
/* starting interface: %(name)s */
#define %(defname)s_IID_STR "%(iid)s"

View File

@ -78,6 +78,14 @@ def get_type(type, calltype, iid_is=None, size_is=None):
'name': type.name,
}
if isinstance(type, xpidl.WebIDL):
return {
'tag': 'TD_DOMOBJECT',
'name': type.name,
'native': type.native,
'headerFile': type.headerFile,
}
if isinstance(type, xpidl.Native):
if type.specialtype:
return {

View File

@ -565,6 +565,50 @@ class Native(object):
return "native %s(%s)\n" % (self.name, self.nativename)
class WebIDL(object):
kind = 'webidl'
def __init__(self, name, location):
self.name = name
self.location = location
def __eq__(self, other):
return other.kind == 'webidl' and self.name == other.name
def resolve(self, parent):
# XXX(nika): We don't handle _every_ kind of webidl object here (as that
# would be hard). For example, we don't support nsIDOM*-defaulting
# interfaces.
# TODO: More explicit compile-time checks?
assert parent.webidlconfig is not None, \
"WebIDL declarations require passing webidlconfig to resolve."
# Resolve our native name according to the WebIDL configs.
config = parent.webidlconfig.get(self.name, {})
self.native = config.get('nativeType')
if self.native is None:
self.native = "mozilla::dom::%s" % self.name
self.headerFile = config.get('headerFile')
if self.headerFile is None:
self.headerFile = self.native.replace('::', '/') + '.h'
parent.setName(self)
def isScriptable(self):
return True # All DOM objects are script exposed.
def nativeType(self, calltype):
return "%s %s" % (self.native, calltype != 'in' and '* *' or '*')
def rustType(self, calltype):
# Just expose the type as a void* - we can't do any better.
return "%s*const libc::c_void" % (calltype != 'in' and '*mut ' or '')
def __str__(self):
return "webidl %s\n" % self.name
class Interface(object):
kind = 'interface'
@ -1165,6 +1209,7 @@ class IDLParser(object):
'readonly': 'READONLY',
'native': 'NATIVE',
'typedef': 'TYPEDEF',
'webidl': 'WEBIDL',
}
tokens = [
@ -1279,7 +1324,8 @@ class IDLParser(object):
def p_productions_interface(self, p):
"""productions : interface productions
| typedef productions
| native productions"""
| native productions
| webidl productions"""
p[0] = list(p[2])
p[0].insert(0, p[1])
@ -1303,6 +1349,10 @@ class IDLParser(object):
# mode here, to slurp up everything until the closeparen
self.lexer.begin('nativeid')
def p_webidl(self, p):
"""webidl : WEBIDL IDENTIFIER ';'"""
p[0] = WebIDL(name=p[2], location=self.getLocation(p, 2))
def p_anyident(self, p):
"""anyident : IDENTIFIER
| CONST"""