diff options
Diffstat (limited to 'components/script/dom/bindings/codegen/CodegenRust.py')
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 105 |
1 files changed, 79 insertions, 26 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 8a66a99cb38..00df29230c3 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -4,6 +4,8 @@ # Common codegen classes. +from collections import defaultdict + import operator import re import string @@ -1722,23 +1724,20 @@ class CGNamespace(CGWrapper): return CGNamespace(namespaces[0], inner, public=public) -def EventTargetEnum(desc): +def DOMClassTypeId(desc): protochain = desc.prototypeChain - if protochain[0] != "EventTarget" or desc.interface.getExtendedAttribute("Abstract"): - return "None" - inner = "" - name = desc.interface.identifier.name - if desc.interface.getUserData("hasConcreteDescendant", False): - inner = "(::dom::%s::%sTypeId::%s)" % (name.lower(), name, name) - prev_proto = "" - for proto in reversed(protochain): - if prev_proto != "": - inner = "(::dom::%s::%sTypeId::%s%s)" % (proto.lower(), proto, prev_proto, inner) - prev_proto = proto - if inner == "": - return "None" - return "Some%s" % inner + if desc.hasDescendants(): + if desc.interface.getExtendedAttribute("Abstract"): + return "::dom::bindings::codegen::InheritTypes::TopTypeId::Abstract" + name = desc.interface.identifier.name + inner = "(::dom::bindings::codegen::InheritTypes::%sTypeId::%s)" % (name, name) + elif len(protochain) == 1: + return "::dom::bindings::codegen::InheritTypes::TopTypeId::Alone" + reversed_protochain = list(reversed(protochain)) + for (child, parent) in zip(reversed_protochain, reversed_protochain[1:]): + inner = "(::dom::bindings::codegen::InheritTypes::%sTypeId::%s%s)" % (parent, child, inner) + return "::dom::bindings::codegen::InheritTypes::TopTypeId::%s%s" % (protochain[0], inner) def DOMClass(descriptor): @@ -1754,7 +1753,7 @@ DOMClass { interface_chain: [ %s ], native_hooks: &sNativePropertyHooks, type_id: %s, -}""" % (prototypeChainString, EventTargetEnum(descriptor)) +}""" % (prototypeChainString, DOMClassTypeId(descriptor)) class CGDOMJSClass(CGThing): @@ -5815,23 +5814,29 @@ class GlobalGenRoots(): def InheritTypes(config): descriptors = config.getDescriptors(register=True, isCallback=False) - allprotos = [CGGeneric("use dom::types::*;\n"), - CGGeneric("use dom::bindings::js::{JS, LayoutJS, Root};\n"), - CGGeneric("use dom::bindings::trace::JSTraceable;\n"), - CGGeneric("use dom::bindings::utils::Reflectable;\n"), - CGGeneric("use js::jsapi::JSTracer;\n\n"), - CGGeneric("use std::mem;\n\n")] + imports = [CGGeneric("use dom::types::*;\n"), + CGGeneric("use dom::bindings::conversions::get_dom_class;\n"), + CGGeneric("use dom::bindings::js::{JS, LayoutJS, Root};\n"), + CGGeneric("use dom::bindings::trace::JSTraceable;\n"), + CGGeneric("use dom::bindings::utils::Reflectable;\n"), + CGGeneric("use js::jsapi::JSTracer;\n\n"), + CGGeneric("use std::mem;\n\n")] + allprotos = [] + topTypes = [] + hierarchy = defaultdict(list) for descriptor in descriptors: name = descriptor.name chain = descriptor.prototypeChain - upcast = (descriptor.interface.getUserData("hasConcreteDescendant", False) or - descriptor.interface.getUserData("hasProxyDescendant", False)) + upcast = descriptor.hasDescendants() downcast = len(chain) != 1 if upcast or downcast: # Define a dummy structure to hold the cast functions. allprotos.append(CGGeneric("pub struct %sCast;\n\n" % name)) + if upcast and not downcast: + topTypes.append(name) + if upcast: # Define a `FooBase` trait for subclasses to implement, as well as the # `FooCast::from_*` methods that use it. @@ -5872,6 +5877,7 @@ impl %(name)sCast { allprotos.append(CGGeneric("\n")) if downcast: + hierarchy[descriptor.getParentName()].append(name) # Define a `FooDerived` trait for superclasses to implement, # as well as the `FooCast::to_*` methods that use it. allprotos.append(CGGeneric("""\ @@ -5922,7 +5928,7 @@ impl %(name)sCast { 'baseName': baseName, 'derivedTrait': name + 'Derived', 'methodName': 'is_' + name.lower(), - 'parentName': config.getDescriptor(baseName).prototypeChain[-2], + 'parentName': config.getDescriptor(baseName).getParentName(), } allprotos.append(CGGeneric("""\ impl %(derivedTrait)s for %(baseName)s { @@ -5934,7 +5940,54 @@ impl %(derivedTrait)s for %(baseName)s { """ % args)) - curr = CGList(allprotos) + typeIdCode = [] + topTypeVariants = [ + ("ID used by abstract interfaces.", "Abstract"), + ("ID used by interfaces that are not castable.", "Alone"), + ] + topTypeVariants += [ + ("ID used by interfaces that derive from %s." % name, "%s(%sTypeId)" % (name, name)) + for name in topTypes + ] + topTypeVariantsAsStrings = [CGGeneric("/// %s\n%s," % variant) for variant in topTypeVariants] + typeIdCode.append(CGWrapper(CGIndenter(CGList(topTypeVariantsAsStrings, "\n"), 4), + pre="#[derive(Clone, Copy, Debug)]\npub enum TopTypeId {\n", + post="\n}\n\n")) + + def type_id_variant(name): + # If `name` is present in the hierarchy keys', that means some other interfaces + # derive from it and this enum variant should have an argument with its own + # TypeId enum. + return "%s(%sTypeId)" % (name, name) if name in hierarchy else name + + for base, derived in hierarchy.iteritems(): + variants = [] + if not config.getInterface(base).getExtendedAttribute("Abstract"): + variants.append(CGGeneric(base)) + variants += [CGGeneric(type_id_variant(name)) for name in derived] + derives = "Clone, Copy, Debug" + if base != 'EventTarget' and base != 'HTMLElement': + derives += ", PartialEq" + typeIdCode.append(CGWrapper(CGIndenter(CGList(variants, ",\n"), 4), + pre="#[derive(%s)]\npub enum %sTypeId {\n" % (derives, base), + post="\n}\n\n")) + if base in topTypes: + typeIdCode.append(CGGeneric("""\ +impl %(base)s { + pub fn type_id(&self) -> &'static %(base)sTypeId { + let domclass = unsafe { + get_dom_class(self.reflector().get_jsobject().get()).unwrap() + }; + match domclass.type_id { + TopTypeId::%(base)s(ref type_id) => type_id, + _ => unreachable!(), + } + } +} + +""" % {'base': base})) + + curr = CGList(imports + typeIdCode + allprotos) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) return curr |