mirror of
https://github.com/servo/servo
synced 2026-04-27 18:07:52 +02:00
Assert that DOM structs have the correct first field
DOM structs embed their parent type as their first field. This
introduces a `.parent()` method to the DOM struct that returns its first
field, and codegens a type assert that ensures that `.parent()` returns
the parent struct.
This generates:
On `#[dom_struct]`:
```rust
impl HasParent for Type {
type Parent = ParentType;
fn as_parent(&self) -> ParentType {
&self.first_field
}
}
```
In the codegen files:
```rust
impl Type {
fn __assert_parent_type(&self) {
let _: &ParentType = self.as_parent();
}
}
````
This commit is contained in:
@@ -2116,6 +2116,10 @@ class CGDOMJSClass(CGThing):
|
||||
self.descriptor = descriptor
|
||||
|
||||
def define(self):
|
||||
parentName = self.descriptor.getParentName()
|
||||
if not parentName:
|
||||
parentName = "::dom::bindings::reflector::Reflector"
|
||||
|
||||
args = {
|
||||
"domClass": DOMClass(self.descriptor),
|
||||
"enumerateHook": "None",
|
||||
@@ -2161,7 +2165,51 @@ static Class: DOMJSClass = DOMJSClass {
|
||||
reserved: [0 as *mut _; 3],
|
||||
},
|
||||
dom_class: %(domClass)s
|
||||
};""" % args
|
||||
};
|
||||
""" % args
|
||||
|
||||
|
||||
class CGAssertInheritance(CGThing):
|
||||
"""
|
||||
Generate a type assertion for inheritance
|
||||
"""
|
||||
def __init__(self, descriptor):
|
||||
CGThing.__init__(self)
|
||||
self.descriptor = descriptor
|
||||
|
||||
def define(self):
|
||||
parent = self.descriptor.interface.parent
|
||||
parentName = ""
|
||||
if parent:
|
||||
parentName = parent.identifier.name
|
||||
else:
|
||||
parentName = "::dom::bindings::reflector::Reflector"
|
||||
|
||||
selfName = self.descriptor.interface.identifier.name
|
||||
|
||||
if selfName == "PaintRenderingContext2D":
|
||||
# PaintRenderingContext2D embeds a CanvasRenderingContext2D
|
||||
# instead of a Reflector as an optimization,
|
||||
# but this is fine since CanvasRenderingContext2D
|
||||
# also has a reflector
|
||||
#
|
||||
# FIXME *RenderingContext2D should use Inline
|
||||
parentName = "::dom::canvasrenderingcontext2d::CanvasRenderingContext2D"
|
||||
args = {
|
||||
"parentName": parentName,
|
||||
"selfName": selfName,
|
||||
}
|
||||
|
||||
return """\
|
||||
impl %(selfName)s {
|
||||
fn __assert_parent_type(&self) {
|
||||
use dom::bindings::inheritance::HasParent;
|
||||
// If this type assertion fails, make sure the first field of your
|
||||
// DOM struct is of the correct type -- it must be the parent class.
|
||||
let _: &%(parentName)s = self.as_parent();
|
||||
}
|
||||
}
|
||||
""" % args
|
||||
|
||||
|
||||
def str_to_const_array(s):
|
||||
@@ -6011,6 +6059,8 @@ class CGDescriptor(CGThing):
|
||||
pass
|
||||
else:
|
||||
cgThings.append(CGDOMJSClass(descriptor))
|
||||
if not descriptor.interface.isIteratorInterface():
|
||||
cgThings.append(CGAssertInheritance(descriptor))
|
||||
pass
|
||||
|
||||
if descriptor.isGlobal():
|
||||
|
||||
Reference in New Issue
Block a user