aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/CodegenRust.py
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/codegen/CodegenRust.py')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py105
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