mirror of
https://github.com/servo/servo.git
synced 2025-06-23 16:44:33 +01:00
auto merge of #983 : saneyuki/servo/getid, r=jdm
This has not implemented these features yet: * Update hashmap which is used for `getElementById()` when updating element attributes. * Keep node order in tree. However, this has the quality of that we can use this method for testcases.
This commit is contained in:
commit
90baad3fff
5 changed files with 134 additions and 6 deletions
|
@ -26,6 +26,8 @@ use js::jsapi::{JSTRACE_OBJECT, JSTracer, JS_CallTracer};
|
|||
use js::glue::RUST_OBJECT_TO_JSVAL;
|
||||
use servo_util::tree::TreeNodeRef;
|
||||
|
||||
use std::hashmap::HashMap;
|
||||
|
||||
use std::cast;
|
||||
use std::ptr;
|
||||
use std::str::eq_slice;
|
||||
|
@ -93,6 +95,9 @@ impl AbstractDocument {
|
|||
}));
|
||||
self.with_mut_base(|document| {
|
||||
document.root = Some(root);
|
||||
// Register elements having "id" attribute to the owner doc.
|
||||
document.register_nodes_with_id(&root);
|
||||
|
||||
document.content_changed();
|
||||
});
|
||||
}
|
||||
|
@ -109,7 +114,8 @@ pub struct Document {
|
|||
reflector_: Reflector,
|
||||
window: Option<@mut Window>,
|
||||
doctype: DocumentType,
|
||||
title: ~str
|
||||
title: ~str,
|
||||
idmap: HashMap<~str, AbstractNode<ScriptView>>
|
||||
}
|
||||
|
||||
impl Document {
|
||||
|
@ -120,7 +126,8 @@ impl Document {
|
|||
reflector_: Reflector::new(),
|
||||
window: window,
|
||||
doctype: doctype,
|
||||
title: ~""
|
||||
title: ~"",
|
||||
idmap: HashMap::new()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,8 +271,11 @@ impl Document {
|
|||
HTMLCollection::new(~[], cx, scope)
|
||||
}
|
||||
|
||||
pub fn GetElementById(&self, _id: &DOMString) -> Option<AbstractNode<ScriptView>> {
|
||||
None
|
||||
pub fn GetElementById(&self, id: &DOMString) -> Option<AbstractNode<ScriptView>> {
|
||||
let key: &~str = &null_str_as_empty(id);
|
||||
// TODO: "in tree order, within the context object's tree"
|
||||
// http://dom.spec.whatwg.org/#dom-document-getelementbyid.
|
||||
self.idmap.find_equiv(key).map(|node| **node)
|
||||
}
|
||||
|
||||
pub fn CreateElement(&self, abstract_self: AbstractDocument, local_name: &DOMString) -> Fallible<AbstractNode<ScriptView>> {
|
||||
|
@ -518,6 +528,41 @@ impl Document {
|
|||
window.wait_until_safe_to_modify_dom();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register_nodes_with_id(&mut self, root: &AbstractNode<ScriptView>) {
|
||||
foreach_ided_elements(root, |id: &~str, abstract_node: &AbstractNode<ScriptView>| {
|
||||
// TODO: "in tree order, within the context object's tree"
|
||||
// http://dom.spec.whatwg.org/#dom-document-getelementbyid.
|
||||
self.idmap.find_or_insert(id.clone(), *abstract_node);
|
||||
});
|
||||
}
|
||||
|
||||
pub fn unregister_nodes_with_id(&mut self, root: &AbstractNode<ScriptView>) {
|
||||
foreach_ided_elements(root, |id: &~str, _| {
|
||||
// TODO: "in tree order, within the context object's tree"
|
||||
// http://dom.spec.whatwg.org/#dom-document-getelementbyid.
|
||||
self.idmap.pop(id);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn foreach_ided_elements(root: &AbstractNode<ScriptView>,
|
||||
callback: &fn(&~str, &AbstractNode<ScriptView>)) {
|
||||
for node in root.traverse_preorder() {
|
||||
if !node.is_element() {
|
||||
loop;
|
||||
}
|
||||
|
||||
do node.with_imm_element |element| {
|
||||
match element.get_attr("id") {
|
||||
Some(id) => {
|
||||
callback(&id.to_str(), &node);
|
||||
}
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Traceable for Document {
|
||||
|
|
|
@ -170,6 +170,9 @@ impl<'self> Element {
|
|||
null_str_as_empty_ref(raw_value)));
|
||||
}
|
||||
|
||||
// TODO: update owner document's id hashmap for `document.getElementById()`
|
||||
// if `name` == "id".
|
||||
|
||||
//XXXjdm We really need something like a vtable so we can call AfterSetAttr.
|
||||
// This hardcoding is awful.
|
||||
match abstract_self.type_id() {
|
||||
|
|
|
@ -461,7 +461,7 @@ impl Node<ScriptView> {
|
|||
node
|
||||
}
|
||||
|
||||
pub fn add_to_doc(&mut self, doc: AbstractDocument) {
|
||||
pub fn add_to_doc(&mut self, abstract_self: AbstractNode<ScriptView>, doc: AbstractDocument) {
|
||||
let old_doc = self.owner_doc;
|
||||
self.owner_doc = doc;
|
||||
let mut cur_node = self.first_child;
|
||||
|
@ -474,6 +474,16 @@ impl Node<ScriptView> {
|
|||
cur_node = cur_node.unwrap().next_sibling();
|
||||
}
|
||||
|
||||
// Unregister elements having "id' from the old doc.
|
||||
do old_doc.with_mut_base |old_doc| {
|
||||
old_doc.unregister_nodes_with_id(&abstract_self);
|
||||
}
|
||||
|
||||
// Register elements having "id" attribute to the owner doc.
|
||||
do doc.with_mut_base |doc| {
|
||||
doc.register_nodes_with_id(&abstract_self);
|
||||
}
|
||||
|
||||
// Signal the old document that it needs to update its display
|
||||
if old_doc != doc {
|
||||
do old_doc.with_base |old_doc| {
|
||||
|
@ -756,7 +766,7 @@ impl Node<ScriptView> {
|
|||
node.parent_node().map(|parent| parent.remove_child(node));
|
||||
abstract_self.add_child(node);
|
||||
do node.with_mut_base |node| {
|
||||
node.add_to_doc(self.owner_doc);
|
||||
node.add_to_doc(abstract_self, self.owner_doc);
|
||||
}
|
||||
Ok(node)
|
||||
}
|
||||
|
@ -782,6 +792,12 @@ impl Node<ScriptView> {
|
|||
|
||||
self.wait_until_safe_to_modify_dom();
|
||||
|
||||
// Unregister elements having "id' from the owner doc.
|
||||
// This need be called before target nodes are removed from tree.
|
||||
do self.owner_doc.with_mut_base |doc| {
|
||||
doc.unregister_nodes_with_id(&abstract_self);
|
||||
}
|
||||
|
||||
abstract_self.remove_child(node);
|
||||
// Signal the document that it needs to update its display.
|
||||
do self.owner_doc.with_base |document| {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue