mirror of
https://github.com/servo/servo.git
synced 2025-06-21 15:49:04 +01:00
Don't require passing a root element to Document::new (needed for issue #888).
This commit is contained in:
parent
f13438d012
commit
c93d13b0da
4 changed files with 183 additions and 127 deletions
|
@ -76,6 +76,12 @@ impl AbstractDocument {
|
||||||
_ => fail!("attempt to downcast a non-HTMLDocument to HTMLDocument")
|
_ => fail!("attempt to downcast a non-HTMLDocument to HTMLDocument")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_root(&mut self, root: AbstractNode<ScriptView>) {
|
||||||
|
self.with_mut_base(|document| {
|
||||||
|
document.set_root(root);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum DocumentType {
|
pub enum DocumentType {
|
||||||
|
@ -85,7 +91,7 @@ pub enum DocumentType {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Document {
|
pub struct Document {
|
||||||
root: AbstractNode<ScriptView>,
|
root: Option<AbstractNode<ScriptView>>,
|
||||||
wrapper: WrapperCache,
|
wrapper: WrapperCache,
|
||||||
window: Option<@mut Window>,
|
window: Option<@mut Window>,
|
||||||
doctype: DocumentType,
|
doctype: DocumentType,
|
||||||
|
@ -94,9 +100,9 @@ pub struct Document {
|
||||||
|
|
||||||
impl Document {
|
impl Document {
|
||||||
#[fixed_stack_segment]
|
#[fixed_stack_segment]
|
||||||
pub fn new(root: AbstractNode<ScriptView>, window: Option<@mut Window>, doctype: DocumentType) -> Document {
|
pub fn new(window: Option<@mut Window>, doctype: DocumentType) -> Document {
|
||||||
Document {
|
Document {
|
||||||
root: root,
|
root: None,
|
||||||
wrapper: WrapperCache::new(),
|
wrapper: WrapperCache::new(),
|
||||||
window: window,
|
window: window,
|
||||||
doctype: doctype,
|
doctype: doctype,
|
||||||
|
@ -104,14 +110,22 @@ impl Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_root(&mut self, root: AbstractNode<ScriptView>) {
|
||||||
|
self.root = Some(root);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn Constructor(owner: @mut Window) -> Fallible<AbstractDocument> {
|
pub fn Constructor(owner: @mut Window) -> Fallible<AbstractDocument> {
|
||||||
|
let cx = owner.page.js_info.get_ref().js_compartment.cx.ptr;
|
||||||
|
|
||||||
|
let mut document = AbstractDocument::as_abstract(cx, @mut Document::new(None, XML));
|
||||||
|
|
||||||
let root = @HTMLHtmlElement {
|
let root = @HTMLHtmlElement {
|
||||||
htmlelement: HTMLElement::new(HTMLHtmlElementTypeId, ~"html")
|
htmlelement: HTMLElement::new(HTMLHtmlElementTypeId, ~"html")
|
||||||
};
|
};
|
||||||
|
|
||||||
let cx = owner.page.js_info.get_ref().js_compartment.cx.ptr;
|
|
||||||
let root = unsafe { Node::as_abstract_node(cx, root) };
|
let root = unsafe { Node::as_abstract_node(cx, root) };
|
||||||
Ok(AbstractDocument::as_abstract(cx, @mut Document::new(root, None, XML)))
|
document.set_root(root);
|
||||||
|
|
||||||
|
Ok(document)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +222,7 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetDocumentElement(&self) -> Option<AbstractNode<ScriptView>> {
|
pub fn GetDocumentElement(&self) -> Option<AbstractNode<ScriptView>> {
|
||||||
Some(self.root)
|
self.root
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_cx(&self) -> *JSContext {
|
fn get_cx(&self) -> *JSContext {
|
||||||
|
@ -288,7 +302,10 @@ impl Document {
|
||||||
fail!("no SVG document yet")
|
fail!("no SVG document yet")
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let _ = for node in self.root.traverse_preorder() {
|
match self.root {
|
||||||
|
None => {},
|
||||||
|
Some(root) => {
|
||||||
|
let _ = for node in root.traverse_preorder() {
|
||||||
if node.type_id() != ElementNodeTypeId(HTMLTitleElementTypeId) {
|
if node.type_id() != ElementNodeTypeId(HTMLTitleElementTypeId) {
|
||||||
loop;
|
loop;
|
||||||
}
|
}
|
||||||
|
@ -304,6 +321,8 @@ impl Document {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let v: ~[&str] = title.word_iter().collect();
|
let v: ~[&str] = title.word_iter().collect();
|
||||||
title = v.connect(" ");
|
title = v.connect(" ");
|
||||||
title = title.trim().to_owned();
|
title = title.trim().to_owned();
|
||||||
|
@ -317,7 +336,10 @@ impl Document {
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let (_scope, cx) = self.get_scope_and_cx();
|
let (_scope, cx) = self.get_scope_and_cx();
|
||||||
let _ = for node in self.root.traverse_preorder() {
|
match self.root {
|
||||||
|
None => {},
|
||||||
|
Some(root) => {
|
||||||
|
let _ = for node in root.traverse_preorder() {
|
||||||
if node.type_id() != ElementNodeTypeId(HTMLHeadElementTypeId) {
|
if node.type_id() != ElementNodeTypeId(HTMLHeadElementTypeId) {
|
||||||
loop;
|
loop;
|
||||||
}
|
}
|
||||||
|
@ -347,6 +369,8 @@ impl Document {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +464,10 @@ impl Document {
|
||||||
|
|
||||||
pub fn createHTMLCollection(&self, callback: &fn(elem: &Element) -> bool) -> @mut HTMLCollection {
|
pub fn createHTMLCollection(&self, callback: &fn(elem: &Element) -> bool) -> @mut HTMLCollection {
|
||||||
let mut elements = ~[];
|
let mut elements = ~[];
|
||||||
let _ = for child in self.root.traverse_preorder() {
|
match self.root {
|
||||||
|
None => {},
|
||||||
|
Some(root) => {
|
||||||
|
let _ = for child in root.traverse_preorder() {
|
||||||
if child.is_element() {
|
if child.is_element() {
|
||||||
do child.with_imm_element |elem| {
|
do child.with_imm_element |elem| {
|
||||||
if callback(elem) {
|
if callback(elem) {
|
||||||
|
@ -449,6 +476,8 @@ impl Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
let (scope, cx) = self.get_scope_and_cx();
|
let (scope, cx) = self.get_scope_and_cx();
|
||||||
HTMLCollection::new(elements, cx, scope)
|
HTMLCollection::new(elements, cx, scope)
|
||||||
}
|
}
|
||||||
|
@ -469,13 +498,16 @@ impl Document {
|
||||||
impl Traceable for Document {
|
impl Traceable for Document {
|
||||||
#[fixed_stack_segment]
|
#[fixed_stack_segment]
|
||||||
fn trace(&self, tracer: *mut JSTracer) {
|
fn trace(&self, tracer: *mut JSTracer) {
|
||||||
|
match self.root {
|
||||||
|
None => {},
|
||||||
|
Some(root) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
(*tracer).debugPrinter = ptr::null();
|
(*tracer).debugPrinter = ptr::null();
|
||||||
(*tracer).debugPrintIndex = -1;
|
(*tracer).debugPrintIndex = -1;
|
||||||
do "root".to_c_str().with_ref |name| {
|
do "root".to_c_str().with_ref |name| {
|
||||||
(*tracer).debugPrintArg = name as *libc::c_void;
|
(*tracer).debugPrintArg = name as *libc::c_void;
|
||||||
debug!("tracing root node");
|
debug!("tracing root node");
|
||||||
do self.root.with_base |node| {
|
do root.with_base |node| {
|
||||||
JS_CallTracer(tracer as *JSTracer,
|
JS_CallTracer(tracer as *JSTracer,
|
||||||
node.wrapper.wrapper,
|
node.wrapper.wrapper,
|
||||||
JSTRACE_OBJECT as u32);
|
JSTRACE_OBJECT as u32);
|
||||||
|
@ -484,3 +516,5 @@ impl Traceable for Document {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -41,26 +41,26 @@ impl DOMParser {
|
||||||
_s: &DOMString,
|
_s: &DOMString,
|
||||||
ty: DOMParserBinding::SupportedType)
|
ty: DOMParserBinding::SupportedType)
|
||||||
-> Fallible<AbstractDocument> {
|
-> Fallible<AbstractDocument> {
|
||||||
unsafe {
|
|
||||||
let root = @HTMLHtmlElement {
|
|
||||||
htmlelement: HTMLElement::new(HTMLHtmlElementTypeId, ~"html")
|
|
||||||
};
|
|
||||||
|
|
||||||
let root = Node::as_abstract_node((*self.owner.page).js_info.get_ref().js_compartment.cx.ptr, root);
|
|
||||||
let cx = (*self.owner.page).js_info.get_ref().js_compartment.cx.ptr;
|
let cx = (*self.owner.page).js_info.get_ref().js_compartment.cx.ptr;
|
||||||
|
let mut document = match ty {
|
||||||
match ty {
|
|
||||||
Text_html => {
|
Text_html => {
|
||||||
Ok(HTMLDocument::new(root, None))
|
HTMLDocument::new(None)
|
||||||
}
|
}
|
||||||
Text_xml => {
|
Text_xml => {
|
||||||
Ok(AbstractDocument::as_abstract(cx, @mut Document::new(root, None, XML)))
|
AbstractDocument::as_abstract(cx, @mut Document::new(None, XML))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
fail!("unsupported document type")
|
fail!("unsupported document type")
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
let root = @HTMLHtmlElement {
|
||||||
|
htmlelement: HTMLElement::new(HTMLHtmlElementTypeId, ~"html")
|
||||||
|
};
|
||||||
|
let root = unsafe { Node::as_abstract_node(cx, root) };
|
||||||
|
document.set_root(root);
|
||||||
|
|
||||||
|
Ok(document)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ pub struct HTMLDocument {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLDocument {
|
impl HTMLDocument {
|
||||||
pub fn new(root: AbstractNode<ScriptView>, window: Option<@mut Window>) -> AbstractDocument {
|
pub fn new(window: Option<@mut Window>) -> AbstractDocument {
|
||||||
let doc = @mut HTMLDocument {
|
let doc = @mut HTMLDocument {
|
||||||
parent: Document::new(root, window, HTML)
|
parent: Document::new(window, HTML)
|
||||||
};
|
};
|
||||||
|
|
||||||
let compartment = window.get_ref().page.js_info.get_ref().js_compartment;
|
let compartment = window.get_ref().page.js_info.get_ref().js_compartment;
|
||||||
|
@ -70,8 +70,11 @@ impl HTMLDocument {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn GetHead(&self) -> Option<AbstractNode<ScriptView>> {
|
pub fn GetHead(&self) -> Option<AbstractNode<ScriptView>> {
|
||||||
|
match self.parent.root {
|
||||||
|
None => None,
|
||||||
|
Some(root) => {
|
||||||
let mut headNode: Option<AbstractNode<ScriptView>> = None;
|
let mut headNode: Option<AbstractNode<ScriptView>> = None;
|
||||||
let _ = for child in self.parent.root.traverse_preorder() {
|
let _ = for child in root.traverse_preorder() {
|
||||||
if child.type_id() == ElementNodeTypeId(HTMLHeadElementTypeId) {
|
if child.type_id() == ElementNodeTypeId(HTMLHeadElementTypeId) {
|
||||||
headNode = Some(child);
|
headNode = Some(child);
|
||||||
break;
|
break;
|
||||||
|
@ -79,6 +82,8 @@ impl HTMLDocument {
|
||||||
};
|
};
|
||||||
headNode
|
headNode
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn Images(&self) -> @mut HTMLCollection {
|
pub fn Images(&self) -> @mut HTMLCollection {
|
||||||
self.parent.createHTMLCollection(|elem| eq_slice(elem.tag_name, "img"))
|
self.parent.createHTMLCollection(|elem| eq_slice(elem.tag_name, "img"))
|
||||||
|
|
|
@ -217,21 +217,27 @@ impl<'self> Iterator<@mut Page> for PageTreeIterator<'self> {
|
||||||
impl Page {
|
impl Page {
|
||||||
/// Adds the given damage.
|
/// Adds the given damage.
|
||||||
fn damage(&mut self, level: DocumentDamageLevel) {
|
fn damage(&mut self, level: DocumentDamageLevel) {
|
||||||
|
let root = do self.frame.get_ref().document.with_base |doc| { doc.root };
|
||||||
|
match root {
|
||||||
|
None => {},
|
||||||
|
Some(root) => {
|
||||||
match self.damage {
|
match self.damage {
|
||||||
None => {}
|
None => {}
|
||||||
Some(ref mut damage) => {
|
Some(ref mut damage) => {
|
||||||
// FIXME(pcwalton): This is wrong. We should trace up to the nearest ancestor.
|
// FIXME(pcwalton): This is wrong. We should trace up to the nearest ancestor.
|
||||||
damage.root = do self.frame.get_ref().document.with_base |doc| { doc.root };
|
damage.root = root;
|
||||||
damage.level.add(level);
|
damage.level.add(level);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.damage = Some(DocumentDamage {
|
self.damage = Some(DocumentDamage {
|
||||||
root: do self.frame.get_ref().document.with_base |doc| { doc.root },
|
root: root,
|
||||||
level: level,
|
level: level,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Sends a ping to layout and waits for the response. The response will arrive when the
|
/// Sends a ping to layout and waits for the response. The response will arrive when the
|
||||||
/// layout task has finished any pending request messages.
|
/// layout task has finished any pending request messages.
|
||||||
|
@ -269,7 +275,17 @@ impl Page {
|
||||||
///
|
///
|
||||||
/// This function fails if there is no root frame.
|
/// This function fails if there is no root frame.
|
||||||
fn reflow(&mut self, goal: ReflowGoal, script_chan: ScriptChan, compositor: @ScriptListener) {
|
fn reflow(&mut self, goal: ReflowGoal, script_chan: ScriptChan, compositor: @ScriptListener) {
|
||||||
|
let root = match self.frame {
|
||||||
|
None => fail!(~"Tried to relayout with no root frame!"),
|
||||||
|
Some(ref frame) => {
|
||||||
|
do frame.document.with_base |doc| {
|
||||||
|
doc.root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match root {
|
||||||
|
None => {},
|
||||||
|
Some(root) => {
|
||||||
debug!("script: performing reflow for goal %?", goal);
|
debug!("script: performing reflow for goal %?", goal);
|
||||||
|
|
||||||
// Now, join the layout so that they will see the latest changes we have made.
|
// Now, join the layout so that they will see the latest changes we have made.
|
||||||
|
@ -284,12 +300,9 @@ impl Page {
|
||||||
|
|
||||||
self.last_reflow_id += 1;
|
self.last_reflow_id += 1;
|
||||||
|
|
||||||
match self.frame {
|
|
||||||
None => fail!(~"Tried to relayout with no root frame!"),
|
|
||||||
Some(ref frame) => {
|
|
||||||
// Send new document and relevant styles to layout.
|
// Send new document and relevant styles to layout.
|
||||||
let reflow = ~Reflow {
|
let reflow = ~Reflow {
|
||||||
document_root: do frame.document.with_base |doc| { doc.root },
|
document_root: root,
|
||||||
url: self.url.get_ref().first().clone(),
|
url: self.url.get_ref().first().clone(),
|
||||||
goal: goal,
|
goal: goal,
|
||||||
window_size: self.window_size.get(),
|
window_size: self.window_size.get(),
|
||||||
|
@ -299,12 +312,12 @@ impl Page {
|
||||||
id: self.last_reflow_id,
|
id: self.last_reflow_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.layout_chan.send(ReflowMsg(reflow))
|
self.layout_chan.send(ReflowMsg(reflow));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug!("script: layout forked")
|
debug!("script: layout forked")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Reflows the entire document.
|
/// Reflows the entire document.
|
||||||
///
|
///
|
||||||
|
@ -709,9 +722,10 @@ impl ScriptTask {
|
||||||
page.next_subpage_id.clone(),
|
page.next_subpage_id.clone(),
|
||||||
self.constellation_chan.clone());
|
self.constellation_chan.clone());
|
||||||
|
|
||||||
let HtmlParserResult {root, discovery_port, url: final_url} = html_parsing_result;
|
let mut document = HTMLDocument::new(Some(window));
|
||||||
|
|
||||||
let document = HTMLDocument::new(root, Some(window));
|
let HtmlParserResult {root, discovery_port, url: final_url} = html_parsing_result;
|
||||||
|
document.set_root(root);
|
||||||
|
|
||||||
// Create the root frame.
|
// Create the root frame.
|
||||||
page.frame = Some(Frame {
|
page.frame = Some(Frame {
|
||||||
|
@ -817,8 +831,11 @@ impl ScriptTask {
|
||||||
let root = do page.frame.expect("root frame is None").document.with_base |doc| {
|
let root = do page.frame.expect("root frame is None").document.with_base |doc| {
|
||||||
doc.root
|
doc.root
|
||||||
};
|
};
|
||||||
|
if root.is_none() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let (port, chan) = comm::stream();
|
let (port, chan) = comm::stream();
|
||||||
match page.query_layout(HitTestQuery(root, point, chan), port) {
|
match page.query_layout(HitTestQuery(root.unwrap(), point, chan), port) {
|
||||||
Ok(node) => match node {
|
Ok(node) => match node {
|
||||||
HitTestResponse(node) => {
|
HitTestResponse(node) => {
|
||||||
debug!("clicked on %s", node.debug_str());
|
debug!("clicked on %s", node.debug_str());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue