WebIDL codegen: Add support for dictionary inheritance.

This commit is contained in:
Josh Matthews 2013-07-10 16:37:05 -04:00
parent 0d39bd1ba9
commit f2ab39376a

View file

@ -2066,7 +2066,7 @@ class CGNativePropertyHooks(CGThing):
parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::NativeHooks" parentHooks = ("&" + toBindingNamespace(parent.identifier.name) + "::NativeHooks"
if parent else '0 as *NativePropertyHooks') if parent else '0 as *NativePropertyHooks')
return """ return """
static NativeHooks: NativePropertyHooks = NativePropertyHooks { resolve_own_property: /*%s*/ 0 as *u8, resolve_property: ResolveProperty, enumerate_own_properties: /*%s*/ 0 as *u8, enumerate_properties: /*EnumerateProperties*/ 0 as *u8, proto_hooks: %s }; static NativeHooks: NativePropertyHooks = NativePropertyHooks { resolve_own_property: /*%s*/ 0 as *u8, resolve_property: ResolveProperty, enumerate_own_properties: /*%s*/ 0 as *u8, enumerate_properties: /*EnumerateProperties*/ 0 as *u8, proto_hooks: /*%s*/ 0 as *NativePropertyHooks };
""" % (resolveOwnProperty, enumerateOwnProperties, parentHooks) """ % (resolveOwnProperty, enumerateOwnProperties, parentHooks)
# We'll want to insert the indent at the beginnings of lines, but we # We'll want to insert the indent at the beginnings of lines, but we
@ -2722,11 +2722,11 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
A method for getting a per-interface object (a prototype object or interface A method for getting a per-interface object (a prototype object or interface
constructor object). constructor object).
""" """
def __init__(self, descriptor, name, idPrefix=""): def __init__(self, descriptor, name, idPrefix="", pub=False):
args = [Argument('*JSContext', 'aCx'), Argument('*JSObject', 'aGlobal'), args = [Argument('*JSContext', 'aCx'), Argument('*JSObject', 'aGlobal'),
Argument('*JSObject', 'aReceiver')] Argument('*JSObject', 'aReceiver')]
CGAbstractMethod.__init__(self, descriptor, name, CGAbstractMethod.__init__(self, descriptor, name,
'*JSObject', args, inline=True) '*JSObject', args, inline=True, pub=pub)
self.id = idPrefix + "id::" + self.descriptor.name self.id = idPrefix + "id::" + self.descriptor.name
def definition_body(self): def definition_body(self):
return """ return """
@ -2758,7 +2758,7 @@ class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
""" """
def __init__(self, descriptor): def __init__(self, descriptor):
CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject", CGGetPerInterfaceObject.__init__(self, descriptor, "GetProtoObject",
"prototypes::") "prototypes::", pub=True)
def definition_body(self): def definition_body(self):
return """ return """
/* Get the interface prototype object for this class. This will create the /* Get the interface prototype object for this class. This will create the
@ -3988,7 +3988,8 @@ class CGDictionary(CGThing):
return "" return ""
d = self.dictionary d = self.dictionary
if d.parent: if d.parent:
inheritance = ": public %s " % self.makeClassName(d.parent) #XXXjdm inheritance = " parent: %s::%s,\n" % (self.makeModuleName(d.parent),
self.makeClassName(d.parent))
else: else:
inheritance = "" inheritance = ""
memberDecls = [" %s: %s," % memberDecls = [" %s: %s," %
@ -3996,7 +3997,8 @@ class CGDictionary(CGThing):
for m in self.memberInfo] for m in self.memberInfo]
return (string.Template( return (string.Template(
"pub struct ${selfName} {\n" + #XXXjdm deal with inheritance "pub struct ${selfName} {\n" +
"${inheritance}" +
"\n".join(memberDecls) + "\n" + "\n".join(memberDecls) + "\n" +
# NOTE: jsids are per-runtime, so don't use them in workers # NOTE: jsids are per-runtime, so don't use them in workers
"\n".join(" //static jsid " + "\n".join(" //static jsid " +
@ -4011,13 +4013,13 @@ class CGDictionary(CGThing):
d = self.dictionary d = self.dictionary
if d.parent: if d.parent:
initParent = ("// Per spec, we init the parent's members first\n" initParent = ("// Per spec, we init the parent's members first\n"
"if (!%s::Init(cx, val)) {\n" "if self.parent.Init(cx, val) == 0 {\n"
" return false;\n" " return 0;\n"
"}\n" % self.makeClassName(d.parent)) "}\n")
else: else:
initParent = "" initParent = ""
memberInits = [CGIndenter(self.getMemberConversion(m)).define() memberInits = [CGIndenter(self.getMemberConversion(m), indentLevel=6).define()
for m in self.memberInfo] for m in self.memberInfo]
idinit = [CGGeneric('!InternJSString(cx, %s, "%s")' % idinit = [CGGeneric('!InternJSString(cx, %s, "%s")' %
(m.identifier.name + "_id", m.identifier.name)) (m.identifier.name + "_id", m.identifier.name))
@ -4049,24 +4051,25 @@ class CGDictionary(CGThing):
for m in d.members) + "\n" for m in d.members) + "\n"
"\n" "\n"
"impl ${selfName} {\n" "impl ${selfName} {\n"
"fn new() -> ${selfName} {\n" " pub fn new() -> ${selfName} {\n"
" ${selfName} {\n" + " ${selfName} {\n" +
((" parent: %s::%s::new(),\n" % (self.makeModuleName(d.parent),
self.makeClassName(d.parent))) if d.parent else "") +
"\n".join(" %s: %s," % (m[0].identifier.name, defaultValue(self.getMemberType(m))) for m in self.memberInfo) + "\n" "\n".join(" %s: %s," % (m[0].identifier.name, defaultValue(self.getMemberType(m))) for m in self.memberInfo) + "\n"
" }\n" " }\n"
"}\n" " }\n"
"\n" "\n"
"fn InitIds(cx: *JSContext) -> bool {\n" " pub fn InitIds(&mut self, cx: *JSContext) -> bool {\n"
" //MOZ_ASSERT(!initedIds);\n" " //MOZ_ASSERT(!initedIds);\n"
"/*${idInit}\n" " /*${idInit}\n"
" initedIds = true;*/ //XXXjdm\n" " initedIds = true;*/ //XXXjdm\n"
" return true;\n" " return true;\n"
"}\n" " }\n"
"\n" if not self.workers else "") + "\n" if not self.workers else "") +
"fn Init(&mut self, cx: *JSContext, val: JSVal) -> JSBool\n" " pub fn Init(&mut self, cx: *JSContext, val: JSVal) -> JSBool {\n"
"{\n"
" unsafe {\n" + " unsafe {\n" +
# NOTE: jsids are per-runtime, so don't use them in workers # NOTE: jsids are per-runtime, so don't use them in workers
(" if (!initedIds && !${selfName}::InitIds(cx)) {\n" (" if (!initedIds && !self.InitIds(cx)) {\n"
" return 0;\n" " return 0;\n"
" }\n" if not self.workers else "") + " }\n" if not self.workers else "") +
"${initParent}" "${initParent}"
@ -4081,10 +4084,10 @@ class CGDictionary(CGThing):
"${initMembers}\n" "${initMembers}\n"
" return 1;\n" " return 1;\n"
" }\n" " }\n"
"}\n" " }\n"
"}").substitute({ "}").substitute({
"selfName": self.makeClassName(d), "selfName": self.makeClassName(d),
"initParent": CGIndenter(CGGeneric(initParent)).define(), "initParent": CGIndenter(CGGeneric(initParent), indentLevel=6).define(),
"initMembers": "\n\n".join(memberInits), "initMembers": "\n\n".join(memberInits),
"idInit": CGIndenter(idinit).define(), "idInit": CGIndenter(idinit).define(),
"isMainThread": toStringBool(not self.workers) "isMainThread": toStringBool(not self.workers)
@ -4098,6 +4101,15 @@ class CGDictionary(CGThing):
def makeClassName(self, dictionary): def makeClassName(self, dictionary):
return self.makeDictionaryName(dictionary, self.workers) return self.makeDictionaryName(dictionary, self.workers)
@staticmethod
def makeModuleName(dictionary):
name = dictionary.identifier.name
if name.endswith('Init'):
return toBindingNamespace(name.replace('Init', ''))
#XXXjdm This breaks on the test webidl files, sigh.
#raise TypeError("No idea how to find this dictionary's definition: " + name)
return "/* uh oh */ %s" % name
def getMemberType(self, memberInfo): def getMemberType(self, memberInfo):
(member, (templateBody, declType, (member, (templateBody, declType,
holderType, dealWithOptional, initialValue)) = memberInfo holderType, dealWithOptional, initialValue)) = memberInfo