diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs index 044fa055b3e..50d7de70d12 100644 --- a/src/components/main/layout/layout_task.rs +++ b/src/components/main/layout/layout_task.rs @@ -372,33 +372,42 @@ impl LayoutTask { transmute(node) }; - let response = do node.read_layout_data |layout_data| { - match (layout_data.boxes.display_list.clone(), layout_data.boxes.range) { - (Some(display_list), Some(range)) => { - let mut rect: Option> = None; - for i in range.eachi() { - rect = match rect { - Some(acc) => Some(acc.union(&display_list.get().list[i].bounds())), - None => Some(display_list.get().list[i].bounds()) + fn box_for_node(node: AbstractNode) -> Option> { + do node.read_layout_data |layout_data| { + match (layout_data.boxes.display_list.clone(), layout_data.boxes.range) { + (Some(display_list), Some(range)) => { + let mut rect: Option> = None; + for i in range.eachi() { + rect = match rect { + Some(acc) => { + Some(acc.union(&display_list.get().list[i].bounds())) + } + None => Some(display_list.get().list[i].bounds()) + } } + rect } - - match rect { - None => { - error!("no boxes for node"); - Err(()) + _ => { + let mut acc: Option> = None; + for child in node.children() { + let rect = box_for_node(child); + match rect { + None => loop, + Some(rect) => acc = match acc { + Some(acc) => Some(acc.union(&rect)), + None => Some(rect) + } + } } - Some(rect) => Ok(ContentBoxResponse(rect)) + acc } } - _ => { - error!("no display list present"); - Err(()) - } } - }; + } - reply_chan.send(response) + let rect = box_for_node(node).unwrap_or_default(Rect(Point2D(Au(0), Au(0)), + Size2D(Au(0), Au(0)))); + reply_chan.send(ContentBoxResponse(rect)) } ContentBoxesQuery(node, reply_chan) => { // FIXME: Isolate this transmutation into a single "bridge" module. @@ -406,21 +415,30 @@ impl LayoutTask { transmute(node) }; - let response = do node.read_layout_data |layout_data| { - match (layout_data.boxes.display_list.clone(), layout_data.boxes.range) { - (Some(display_list), Some(range)) => { - let mut boxes = ~[]; - for i in range.eachi() { - boxes.push(display_list.get().list[i].bounds()); + fn boxes_for_node(node: AbstractNode, + boxes: ~[Rect]) -> ~[Rect] { + let boxes = Cell::new(boxes); + do node.read_layout_data |layout_data| { + let mut boxes = boxes.take(); + match (layout_data.boxes.display_list.clone(), layout_data.boxes.range) { + (Some(display_list), Some(range)) => { + for i in range.eachi() { + boxes.push(display_list.get().list[i].bounds()); + } + } + _ => { + for child in node.children() { + boxes = boxes_for_node(child, boxes); + } } - - Ok(ContentBoxesResponse(boxes)) } - _ => Err(()), + boxes } - }; + } - reply_chan.send(response) + let mut boxes = ~[]; + boxes = boxes_for_node(node, boxes); + reply_chan.send(ContentBoxesResponse(boxes)) } HitTestQuery(_, point, reply_chan) => { let response = { diff --git a/src/components/script/dom/element.rs b/src/components/script/dom/element.rs index 000beaba1cb..0e6be05cd0b 100644 --- a/src/components/script/dom/element.rs +++ b/src/components/script/dom/element.rs @@ -265,7 +265,7 @@ impl Element { let page = win.page; let (port, chan) = comm::stream(); match unsafe {(*page).query_layout(ContentBoxesQuery(node, chan), port)} { - Ok(ContentBoxesResponse(rects)) => { + ContentBoxesResponse(rects) => { let cx = unsafe {(*page).js_info.get_ref().js_compartment.cx.ptr}; let cache = win.get_wrappercache(); let scope = cache.get_wrapper(); @@ -280,10 +280,6 @@ impl Element { }; Some((rects, cx, scope)) }, - Err(()) => { - debug!("layout query error"); - None - } } } None => { @@ -311,7 +307,7 @@ impl Element { assert!(node.is_element()); let (port, chan) = comm::stream(); match unsafe{(*page).query_layout(ContentBoxQuery(node, chan), port)} { - Ok(ContentBoxResponse(rect)) => { + ContentBoxResponse(rect) => { let cx = unsafe {(*page).js_info.get_ref().js_compartment.cx.ptr}; let cache = win.get_wrappercache(); let scope = cache.get_wrapper(); @@ -322,8 +318,7 @@ impl Element { (rect.origin.x + rect.size.width).to_f32(), cx, scope) - }, - Err(()) => fail!("error querying layout") + } } } None => fail!("no window") diff --git a/src/components/script/layout_interface.rs b/src/components/script/layout_interface.rs index b9e349bf50e..89336494959 100644 --- a/src/components/script/layout_interface.rs +++ b/src/components/script/layout_interface.rs @@ -38,9 +38,9 @@ pub enum Msg { /// Synchronous messages that script can send to layout. pub enum LayoutQuery { /// Requests the dimensions of the content box, as in the `getBoundingClientRect()` call. - ContentBoxQuery(AbstractNode, Chan>), + ContentBoxQuery(AbstractNode, Chan), /// Requests the dimensions of all the content boxes, as in the `getClientRects()` call. - ContentBoxesQuery(AbstractNode, Chan>), + ContentBoxesQuery(AbstractNode, Chan), /// Requests the node containing the point of interest HitTestQuery(AbstractNode, Point2D, Chan>), } diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 37d9caf242a..86524a3704d 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -231,8 +231,8 @@ impl Page { /// Sends the given query to layout. pub fn query_layout(&mut self, query: LayoutQuery, - response_port: Port>) - -> Result { + response_port: Port) + -> T { self.join_layout(); self.layout_chan.send(QueryMsg(query)); response_port.recv() diff --git a/src/test/html/content/test_empty_clientrect.html b/src/test/html/content/test_empty_clientrect.html new file mode 100644 index 00000000000..ecefe14a3fd --- /dev/null +++ b/src/test/html/content/test_empty_clientrect.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/test/html/content/test_empty_clientrect.js b/src/test/html/content/test_empty_clientrect.js new file mode 100644 index 00000000000..d46dbafc664 --- /dev/null +++ b/src/test/html/content/test_empty_clientrect.js @@ -0,0 +1,12 @@ +var rect = window.document.head.getBoundingClientRect(); +var rects = window.document.head.getClientRects(); +is(rect instanceof ClientRect, true); +is(rect.top, 0); +is(rect.bottom, 0); +is(rect.left, 0); +is(rect.right, 0); +is(rect.width, 0); +is(rect.height, 0); +is(rects instanceof ClientRectList, true); +is(rects.length, 0); +finish(); \ No newline at end of file