Introduce trait Castable

This trait is used to hold onto the downcast and upcast functions of all
castable IDL interfaces. A castable IDL interface is one which either derives
from or is derived by other interfaces.

The deriving relation is represented by implementations of marker trait
DerivedFrom<T: Castable> generated in InheritTypes.

/^[ ]*use dom::bindings::codegen::InheritTypes::.*(Base|Cast|Derived)/ {
    /::[a-zA-Z]+(Base|Cast|Derived);/d
    s/([{ ])[a-zA-Z]+(Base|Cast|Derived), /\1/g
    s/([{ ])[a-zA-Z]+(Base|Cast|Derived), /\1/g
    s/, [a-zA-Z]+(Base|Cast|Derived)([},])/\2/g
    s/, [a-zA-Z]+(Base|Cast|Derived)([},])/\2/g
    /\{([a-zA-Z]+(Base|Cast|Derived))?\};$/d
    s/\{([a-zA-Z_]+)\};$/\1;/
}

s/([a-zA-Z]+)Cast::from_ref\(\&?\**([a-zA-Z_]+)(\.r\(\))?\)/\2.upcast::<\1>()/g
s/([a-zA-Z]+)Cast::from_ref\(\&?\**([a-zA-Z_]+)(\.[a-zA-Z_]+\(\))?\)/\2\3.upcast::<\1>()/g
s/\(([a-zA-Z]+)Cast::from_ref\)/\(Castable::upcast::<\1>\)/g

s/([a-zA-Z]+)Cast::from_root/Root::upcast::<\1>/g

s/([a-zA-Z]+)Cast::from_layout_js\(\&([a-zA-Z_.]+)\)/\2.upcast::<\1>()/g

s/([a-zA-Z]+)Cast::to_ref\(\&?\**([a-zA-Z_]+)(\.r\(\))?\)/\2.downcast::<\1>()/g
s/([a-zA-Z]+)Cast::to_ref\(\&?\**([a-zA-Z_]+)(\.[a-zA-Z_]+\(\))?\)/\2\3.downcast::<\1>()/g
s/\(([a-zA-Z]+)Cast::to_ref\)/\(Castable::downcast::<\1>\)/g

s/([a-zA-Z]+)Cast::to_root/Root::downcast::<\1>/g

s/([a-zA-Z]+)Cast::to_layout_js\(&?([a-zA-Z_.]+(\(\))?)\)/\2.downcast::<\1>()/g

s/\.is_document\(\)/.is::<Document>()/g
s/\.is_htmlanchorelement\(\)/.is::<HTMLAnchorElement>()/g
s/\.is_htmlappletelement\(\)/.is::<HTMLAppletElement>()/g
s/\.is_htmlareaelement\(\)/.is::<HTMLAreaElement>()/g
s/\.is_htmlbodyelement\(\)/.is::<HTMLBodyElement>()/g
s/\.is_htmlembedelement\(\)/.is::<HTMLEmbedElement>()/g
s/\.is_htmlfieldsetelement\(\)/.is::<HTMLFieldSetElement>()/g
s/\.is_htmlformelement\(\)/.is::<HTMLFormElement>()/g
s/\.is_htmlframesetelement\(\)/.is::<HTMLFrameSetElement>()/g
s/\.is_htmlhtmlelement\(\)/.is::<HTMLHtmlElement>()/g
s/\.is_htmlimageelement\(\)/.is::<HTMLImageElement>()/g
s/\.is_htmllegendelement\(\)/.is::<HTMLLegendElement>()/g
s/\.is_htmloptgroupelement\(\)/.is::<HTMLOptGroupElement>()/g
s/\.is_htmloptionelement\(\)/.is::<HTMLOptionElement>()/g
s/\.is_htmlscriptelement\(\)/.is::<HTMLScriptElement>()/g
s/\.is_htmltabledatacellelement\(\)/.is::<HTMLTableDataCellElement>()/g
s/\.is_htmltableheadercellelement\(\)/.is::<HTMLTableHeaderCellElement>()/g
s/\.is_htmltablerowelement\(\)/.is::<HTMLTableRowElement>()/g
s/\.is_htmltablesectionelement\(\)/.is::<HTMLTableSectionElement>()/g
s/\.is_htmltitleelement\(\)/.is::<HTMLTitleElement>()/g
This commit is contained in:
Anthony Ramine 2015-10-06 17:21:44 +02:00
parent bd363b009d
commit 13ea3ac413
82 changed files with 1124 additions and 1148 deletions

View file

@ -11,9 +11,7 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::Bindings::HTMLInputElementBinding;
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, HTMLInputElementCast};
use dom::bindings::codegen::InheritTypes::{KeyboardEventCast, NodeCast};
use dom::bindings::conversions::Castable;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, LayoutJS, Root, RootedReference};
use dom::document::Document;
@ -21,6 +19,7 @@ use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE, RawLayoutElemen
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
use dom::htmlelement::HTMLElement;
use dom::htmlfieldsetelement::HTMLFieldSetElement;
use dom::htmlformelement::{FormControl, FormDatum, FormSubmitter, HTMLFormElement};
use dom::htmlformelement::{ResetFrom, SubmittedFrom};
use dom::keyboardevent::KeyboardEvent;
@ -165,7 +164,7 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> {
#[allow(unsafe_code)]
unsafe fn get_raw_attr_value(input: LayoutJS<HTMLInputElement>) -> Option<String> {
let elem = ElementCast::from_layout_js(&input);
let elem = input.upcast::<Element>();
(*elem.unsafe_get()).get_attr_val_for_layout(&ns!(""), &atom!("value"))
.map(|s| s.to_owned())
}
@ -354,13 +353,13 @@ fn broadcast_radio_checked(broadcaster: &HTMLInputElement, group: Option<&Atom>)
//TODO: if not in document, use root ancestor instead of document
let owner = broadcaster.form_owner();
let doc = document_from_node(broadcaster);
let doc_node = NodeCast::from_ref(doc.r());
let doc_node = doc.upcast::<Node>();
// This function is a workaround for lifetime constraint difficulties.
fn do_broadcast(doc_node: &Node, broadcaster: &HTMLInputElement,
owner: Option<&HTMLFormElement>, group: Option<&Atom>) {
let iter = doc_node.query_selector_iter("input[type=radio]".to_owned())
.unwrap().filter_map(HTMLInputElementCast::to_root)
let iter = doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap()
.filter_map(Root::downcast::<HTMLInputElement>)
.filter(|r| in_same_group(r.r(), owner, group) && broadcaster != r.r());
for ref r in iter {
if r.r().Checked() {
@ -389,7 +388,7 @@ fn in_same_group(other: &HTMLInputElement, owner: Option<&HTMLFormElement>,
impl HTMLInputElement {
fn force_relayout(&self) {
let doc = document_from_node(self);
let node = NodeCast::from_ref(self);
let node = self.upcast::<Node>();
doc.r().content_changed(node, NodeDamage::OtherNodeDamage)
}
@ -440,7 +439,7 @@ impl HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#radio-button-group
fn get_radio_group_name(&self) -> Option<Atom> {
//TODO: determine form owner
let elem = ElementCast::from_ref(self);
let elem = self.upcast::<Element>();
elem.get_attribute(&ns!(""), &atom!("name"))
.map(|name| name.value().as_atom().clone())
}
@ -469,7 +468,7 @@ impl HTMLInputElement {
fn mutable(&self) -> bool {
// https://html.spec.whatwg.org/multipage/#the-input-element:concept-fe-mutable
// https://html.spec.whatwg.org/multipage/#the-readonly-attribute:concept-fe-mutable
let el = ElementCast::from_ref(self);
let el = self.upcast::<Element>();
!(el.get_disabled_state() || self.ReadOnly())
}
@ -492,7 +491,7 @@ impl HTMLInputElement {
impl VirtualMethods for HTMLInputElement {
fn super_type(&self) -> Option<&VirtualMethods> {
let htmlelement: &HTMLElement = HTMLElementCast::from_ref(self);
let htmlelement: &HTMLElement = self.upcast::<HTMLElement>();
Some(htmlelement as &VirtualMethods)
}
@ -508,7 +507,7 @@ impl VirtualMethods for HTMLInputElement {
},
AttributeMutation::Removed => false,
};
let el = ElementCast::from_ref(self);
let el = self.upcast::<Element>();
el.set_disabled_state(disabled_state);
el.set_enabled_state(!disabled_state);
el.check_ancestors_disabled_state_for_form_control();
@ -593,7 +592,7 @@ impl VirtualMethods for HTMLInputElement {
s.bind_to_tree(tree_in_doc);
}
let el = ElementCast::from_ref(self);
let el = self.upcast::<Element>();
el.check_ancestors_disabled_state_for_form_control();
}
@ -602,9 +601,9 @@ impl VirtualMethods for HTMLInputElement {
s.unbind_from_tree(tree_in_doc);
}
let node = NodeCast::from_ref(self);
let el = ElementCast::from_ref(self);
if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) {
let node = self.upcast::<Node>();
let el = self.upcast::<Element>();
if node.ancestors().any(|ancestor| ancestor.is::<HTMLFieldSetElement>()) {
el.check_ancestors_disabled_state_for_form_control();
} else {
el.check_disabled_attribute();
@ -628,11 +627,11 @@ impl VirtualMethods for HTMLInputElement {
//TODO: set the editing position for text inputs
let doc = document_from_node(self);
doc.r().request_focus(ElementCast::from_ref(self));
doc.r().request_focus(self.upcast::<Element>());
} else if &*event.Type() == "keydown" && !event.DefaultPrevented() &&
(self.input_type.get() == InputType::InputText ||
self.input_type.get() == InputType::InputPassword) {
let keyevent: Option<&KeyboardEvent> = KeyboardEventCast::to_ref(event);
let keyevent: Option<&KeyboardEvent> = event.downcast::<KeyboardEvent>();
keyevent.map(|keyevent| {
// This can't be inlined, as holding on to textinput.borrow_mut()
// during self.implicit_submission will cause a panic.
@ -663,7 +662,7 @@ impl FormControl for HTMLInputElement {}
impl Activatable for HTMLInputElement {
fn as_element(&self) -> &Element {
ElementCast::from_ref(self)
self.upcast::<Element>()
}
fn is_instance_activatable(&self) -> bool {
@ -708,11 +707,12 @@ impl Activatable for HTMLInputElement {
//TODO: if not in document, use root ancestor instead of document
let owner = self.form_owner();
let doc = document_from_node(self);
let doc_node = NodeCast::from_ref(doc.r());
let doc_node = doc.upcast::<Node>();
let group = self.get_radio_group_name();;
// Safe since we only manipulate the DOM tree after finding an element
let checked_member = doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_root)
.filter_map(Root::downcast::<HTMLInputElement>)
.find(|r| {
in_same_group(r.r(), owner.r(), group.as_ref()) &&
r.r().Checked()
@ -813,14 +813,14 @@ impl Activatable for HTMLInputElement {
"input".to_owned(),
EventBubbles::Bubbles,
EventCancelable::NotCancelable);
let target = EventTargetCast::from_ref(self);
let target = self.upcast::<EventTarget>();
event.r().fire(target);
let event = Event::new(GlobalRef::Window(win.r()),
"change".to_owned(),
EventBubbles::Bubbles,
EventCancelable::NotCancelable);
let target = EventTargetCast::from_ref(self);
let target = self.upcast::<EventTarget>();
event.r().fire(target);
}
},
@ -832,20 +832,20 @@ impl Activatable for HTMLInputElement {
#[allow(unsafe_code)]
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) {
let doc = document_from_node(self);
let node = NodeCast::from_ref(doc.r());
let node = doc.upcast::<Node>();
let owner = self.form_owner();
let form = match owner {
None => return,
Some(ref f) => f
};
let elem = ElementCast::from_ref(self);
let elem = self.upcast::<Element>();
if elem.click_in_progress() {
return;
}
let submit_button;
submit_button = node.query_selector_iter("input[type=submit]".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_root)
.filter_map(Root::downcast::<HTMLInputElement>)
.find(|r| r.r().form_owner() == owner);
match submit_button {
Some(ref button) => {
@ -855,7 +855,7 @@ impl Activatable for HTMLInputElement {
}
None => {
let inputs = node.query_selector_iter("input".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_root)
.filter_map(Root::downcast::<HTMLInputElement>)
.filter(|input| {
input.r().form_owner() == owner && match &*input.r().Type() {
"text" | "search" | "url" | "tel" |