mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
script: Improve dirty propagation and fix script-layout synchronization.
This fixes race conditions whereby layout and script could be running simultaneously.
This commit is contained in:
parent
1bc2c8a639
commit
d101c1dd91
8 changed files with 220 additions and 257 deletions
|
@ -49,7 +49,7 @@ use dom::mouseevent::MouseEvent;
|
|||
use dom::keyboardevent::KeyboardEvent;
|
||||
use dom::messageevent::MessageEvent;
|
||||
use dom::node::{Node, ElementNodeTypeId, DocumentNodeTypeId, NodeHelpers};
|
||||
use dom::node::{CloneChildren, DoNotCloneChildren};
|
||||
use dom::node::{CloneChildren, DoNotCloneChildren, NodeDamage, OtherNodeDamage};
|
||||
use dom::nodelist::NodeList;
|
||||
use dom::text::Text;
|
||||
use dom::processinginstruction::ProcessingInstruction;
|
||||
|
@ -176,10 +176,8 @@ pub trait DocumentHelpers<'a> {
|
|||
fn set_quirks_mode(self, mode: QuirksMode);
|
||||
fn set_last_modified(self, value: DOMString);
|
||||
fn set_encoding_name(self, name: DOMString);
|
||||
fn content_changed(self, node: JSRef<Node>);
|
||||
fn content_and_heritage_changed(self, node: JSRef<Node>);
|
||||
fn reflow(self);
|
||||
fn wait_until_safe_to_modify_dom(self);
|
||||
fn content_changed(self, node: JSRef<Node>, damage: NodeDamage);
|
||||
fn content_and_heritage_changed(self, node: JSRef<Node>, damage: NodeDamage);
|
||||
fn unregister_named_element(self, to_unregister: JSRef<Element>, id: Atom);
|
||||
fn register_named_element(self, element: JSRef<Element>, id: Atom);
|
||||
fn load_anchor_href(self, href: DOMString);
|
||||
|
@ -190,6 +188,7 @@ pub trait DocumentHelpers<'a> {
|
|||
fn request_focus(self, elem: JSRef<Element>);
|
||||
fn commit_focus_transaction(self);
|
||||
fn send_title_to_compositor(self);
|
||||
fn dirty_all_nodes(self);
|
||||
}
|
||||
|
||||
impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
||||
|
@ -228,24 +227,14 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
|||
*self.encoding_name.borrow_mut() = name;
|
||||
}
|
||||
|
||||
fn content_changed(self, node: JSRef<Node>) {
|
||||
debug!("content_changed on {}", node.debug_str());
|
||||
node.dirty();
|
||||
self.reflow();
|
||||
fn content_changed(self, node: JSRef<Node>, damage: NodeDamage) {
|
||||
node.dirty(damage);
|
||||
}
|
||||
|
||||
fn content_and_heritage_changed(self, node: JSRef<Node>) {
|
||||
fn content_and_heritage_changed(self, node: JSRef<Node>, damage: NodeDamage) {
|
||||
debug!("content_and_heritage_changed on {}", node.debug_str());
|
||||
node.force_dirty_ancestors();
|
||||
self.reflow();
|
||||
}
|
||||
|
||||
fn reflow(self) {
|
||||
self.window.root().reflow();
|
||||
}
|
||||
|
||||
fn wait_until_safe_to_modify_dom(self) {
|
||||
self.window.root().wait_until_safe_to_modify_dom();
|
||||
node.force_dirty_ancestors(damage);
|
||||
node.dirty(damage);
|
||||
}
|
||||
|
||||
/// Remove any existing association between the provided id and any elements in this document.
|
||||
|
@ -376,6 +365,13 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
|||
let window = self.window().root();
|
||||
window.page().send_title_to_compositor();
|
||||
}
|
||||
|
||||
fn dirty_all_nodes(self) {
|
||||
let root: JSRef<Node> = NodeCast::from_ref(self);
|
||||
for node in root.traverse_preorder() {
|
||||
node.dirty(OtherNodeDamage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(PartialEq)]
|
||||
|
|
|
@ -33,8 +33,9 @@ use dom::htmlcollection::HTMLCollection;
|
|||
use dom::htmlinputelement::{HTMLInputElement, RawLayoutHTMLInputElementHelpers};
|
||||
use dom::htmlserializer::serialize;
|
||||
use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementHelpers};
|
||||
use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node, CLICK_IN_PROGRESS};
|
||||
use dom::node::{window_from_node, LayoutNodeHelpers};
|
||||
use dom::node::{CLICK_IN_PROGRESS, ElementNodeTypeId, Node, NodeHelpers, NodeIterator};
|
||||
use dom::node::{document_from_node, window_from_node, LayoutNodeHelpers, NodeStyleDamaged};
|
||||
use dom::node::{OtherNodeDamage};
|
||||
use dom::nodelist::NodeList;
|
||||
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
||||
use devtools_traits::AttrInfo;
|
||||
|
@ -441,7 +442,6 @@ pub trait AttributeHandlers {
|
|||
value: DOMString) -> AttrValue;
|
||||
|
||||
fn remove_attribute(self, namespace: Namespace, name: &str);
|
||||
fn notify_content_changed(self);
|
||||
fn has_class(&self, name: &Atom) -> bool;
|
||||
|
||||
fn set_atomic_attribute(self, name: &Atom, value: DOMString);
|
||||
|
@ -500,9 +500,6 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
|||
assert!(name.as_slice() == name.as_slice().to_ascii_lower().as_slice());
|
||||
assert!(!name.as_slice().contains(":"));
|
||||
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.wait_until_safe_to_modify_dom();
|
||||
|
||||
self.do_set_attribute(name.clone(), value, name.clone(),
|
||||
ns!(""), None, |attr| *attr.local_name() == *name);
|
||||
}
|
||||
|
@ -548,28 +545,26 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
|
|||
match idx {
|
||||
None => (),
|
||||
Some(idx) => {
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.wait_until_safe_to_modify_dom();
|
||||
|
||||
if namespace == ns!("") {
|
||||
let attr = (*self.attrs.borrow())[idx].root();
|
||||
vtable_for(&NodeCast::from_ref(self)).before_remove_attr(*attr);
|
||||
}
|
||||
|
||||
self.attrs.borrow_mut().remove(idx);
|
||||
self.notify_content_changed();
|
||||
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
if node.is_in_doc() {
|
||||
let document = document_from_node(self).root();
|
||||
if local_name == atom!("style") {
|
||||
document.content_changed(node, NodeStyleDamaged);
|
||||
} else {
|
||||
document.content_changed(node, OtherNodeDamage);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn notify_content_changed(self) {
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
if node.is_in_doc() {
|
||||
let document = document_from_node(self).root();
|
||||
document.content_changed(node);
|
||||
}
|
||||
}
|
||||
|
||||
fn has_class(&self, name: &Atom) -> bool {
|
||||
self.get_attribute(ns!(""), &atom!("class")).root().map(|attr| {
|
||||
attr.value().tokens().map(|tokens| {
|
||||
|
@ -755,11 +750,6 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
|||
fn SetAttribute(self,
|
||||
name: DOMString,
|
||||
value: DOMString) -> ErrorResult {
|
||||
{
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.wait_until_safe_to_modify_dom();
|
||||
}
|
||||
|
||||
// Step 1.
|
||||
match xml_name_type(name.as_slice()) {
|
||||
InvalidXMLName => return Err(InvalidCharacter),
|
||||
|
@ -787,11 +777,6 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
|
|||
namespace_url: Option<DOMString>,
|
||||
name: DOMString,
|
||||
value: DOMString) -> ErrorResult {
|
||||
{
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
node.wait_until_safe_to_modify_dom();
|
||||
}
|
||||
|
||||
// Step 1.
|
||||
let namespace = namespace::from_domstring(namespace_url);
|
||||
|
||||
|
@ -999,25 +984,48 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
|
|||
|
||||
match attr.local_name() {
|
||||
&atom!("style") => {
|
||||
// Modifying the `style` attribute might change style.
|
||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||
let doc = document_from_node(*self).root();
|
||||
let base_url = doc.url().clone();
|
||||
let value = attr.value();
|
||||
let style = Some(style::parse_style_attribute(value.as_slice(), &base_url));
|
||||
*self.style_attribute.borrow_mut() = style;
|
||||
}
|
||||
&atom!("id") => {
|
||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||
let value = attr.value();
|
||||
if node.is_in_doc() && !value.as_slice().is_empty() {
|
||||
let doc = document_from_node(*self).root();
|
||||
let value = Atom::from_slice(value.as_slice());
|
||||
doc.register_named_element(*self, value);
|
||||
|
||||
if node.is_in_doc() {
|
||||
doc.content_changed(node, NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
&atom!("class") => {
|
||||
// Modifying a class can change style.
|
||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||
if node.is_in_doc() {
|
||||
let document = document_from_node(*self).root();
|
||||
document.content_changed(node, NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
&atom!("id") => {
|
||||
// Modifying an ID might change style.
|
||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||
let value = attr.value();
|
||||
if node.is_in_doc() {
|
||||
let doc = document_from_node(*self).root();
|
||||
if !value.as_slice().is_empty() {
|
||||
let value = Atom::from_slice(value.as_slice());
|
||||
doc.register_named_element(*self, value);
|
||||
}
|
||||
doc.content_changed(node, NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Modifying any other attribute might change arbitrary things.
|
||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||
if node.is_in_doc() {
|
||||
let document = document_from_node(*self).root();
|
||||
document.content_changed(node, OtherNodeDamage);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
self.notify_content_changed();
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, attr: JSRef<Attr>) {
|
||||
|
@ -1028,21 +1036,45 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
|
|||
|
||||
match attr.local_name() {
|
||||
&atom!("style") => {
|
||||
// Modifying the `style` attribute might change style.
|
||||
*self.style_attribute.borrow_mut() = None;
|
||||
}
|
||||
&atom!("id") => {
|
||||
|
||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||
let value = attr.value();
|
||||
if node.is_in_doc() && !value.as_slice().is_empty() {
|
||||
if node.is_in_doc() {
|
||||
let doc = document_from_node(*self).root();
|
||||
let value = Atom::from_slice(value.as_slice());
|
||||
doc.unregister_named_element(*self, value);
|
||||
doc.content_changed(node, NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
&atom!("id") => {
|
||||
// Modifying an ID can change style.
|
||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||
let value = attr.value();
|
||||
if node.is_in_doc() {
|
||||
let doc = document_from_node(*self).root();
|
||||
if !value.as_slice().is_empty() {
|
||||
let value = Atom::from_slice(value.as_slice());
|
||||
doc.unregister_named_element(*self, value);
|
||||
}
|
||||
doc.content_changed(node, NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
&atom!("class") => {
|
||||
// Modifying a class can change style.
|
||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||
if node.is_in_doc() {
|
||||
let document = document_from_node(*self).root();
|
||||
document.content_changed(node, NodeStyleDamaged);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Modifying any other attribute might change arbitrary things.
|
||||
let node: JSRef<Node> = NodeCast::from_ref(*self);
|
||||
if node.is_in_doc() {
|
||||
let doc = document_from_node(*self).root();
|
||||
doc.content_changed(node, OtherNodeDamage);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
|
||||
self.notify_content_changed();
|
||||
}
|
||||
|
||||
fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
|
||||
|
|
|
@ -26,8 +26,10 @@ use dom::event::{Event, Bubbles, NotCancelable, EventHelpers};
|
|||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::keyboardevent::KeyboardEvent;
|
||||
use dom::htmlformelement::{InputElement, FormControl, HTMLFormElement, HTMLFormElementHelpers, NotFromFormSubmitMethod};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId, document_from_node, window_from_node};
|
||||
use dom::htmlformelement::{InputElement, FormControl, HTMLFormElement, HTMLFormElementHelpers};
|
||||
use dom::htmlformelement::{NotFromFormSubmitMethod};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId, OtherNodeDamage};
|
||||
use dom::node::{document_from_node, window_from_node};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
use textinput::{Single, TextInput, TriggerDefaultAction, DispatchInput, Nothing};
|
||||
|
||||
|
@ -312,7 +314,7 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> {
|
|||
fn force_relayout(self) {
|
||||
let doc = document_from_node(self).root();
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
doc.content_changed(node)
|
||||
doc.content_changed(node, OtherNodeDamage)
|
||||
}
|
||||
|
||||
fn radio_group_updated(self, group: Option<&str>) {
|
||||
|
|
|
@ -20,7 +20,8 @@ use dom::event::Event;
|
|||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::keyboardevent::KeyboardEvent;
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, ElementNodeTypeId, document_from_node};
|
||||
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, OtherNodeDamage, ElementNodeTypeId};
|
||||
use dom::node::{document_from_node};
|
||||
use textinput::{Multiple, TextInput, TriggerDefaultAction, DispatchInput, Nothing};
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
|
||||
|
@ -163,7 +164,7 @@ impl<'a> PrivateHTMLTextAreaElementHelpers for JSRef<'a, HTMLTextAreaElement> {
|
|||
fn force_relayout(self) {
|
||||
let doc = document_from_node(self).root();
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
doc.content_changed(node)
|
||||
doc.content_changed(node, OtherNodeDamage)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -287,20 +287,15 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
|
|||
|
||||
let parent = self.parent_node().root();
|
||||
parent.map(|parent| vtable_for(&*parent).child_inserted(self));
|
||||
|
||||
document.content_and_heritage_changed(self);
|
||||
document.content_and_heritage_changed(self, OtherNodeDamage);
|
||||
}
|
||||
|
||||
// http://dom.spec.whatwg.org/#node-is-removed
|
||||
fn node_removed(self, parent_in_doc: bool) {
|
||||
assert!(self.parent_node().is_none());
|
||||
let document = document_from_node(self).root();
|
||||
|
||||
for node in self.traverse_preorder() {
|
||||
vtable_for(&node).unbind_from_tree(parent_in_doc);
|
||||
}
|
||||
|
||||
document.content_changed(self);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -311,9 +306,6 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
|
|||
///
|
||||
/// Fails unless `new_child` is disconnected from the tree.
|
||||
fn add_child(self, new_child: JSRef<Node>, before: Option<JSRef<Node>>) {
|
||||
let doc = self.owner_doc().root();
|
||||
doc.wait_until_safe_to_modify_dom();
|
||||
|
||||
assert!(new_child.parent_node().is_none());
|
||||
assert!(new_child.prev_sibling().is_none());
|
||||
assert!(new_child.next_sibling().is_none());
|
||||
|
@ -354,9 +346,6 @@ impl<'a> PrivateNodeHelpers for JSRef<'a, Node> {
|
|||
///
|
||||
/// Fails unless `child` is a child of this node.
|
||||
fn remove_child(self, child: JSRef<Node>) {
|
||||
let doc = self.owner_doc().root();
|
||||
doc.wait_until_safe_to_modify_dom();
|
||||
|
||||
assert!(child.parent_node().root().root_ref() == Some(self));
|
||||
|
||||
match child.prev_sibling.get().root() {
|
||||
|
@ -428,8 +417,6 @@ pub trait NodeHelpers<'a> {
|
|||
fn set_owner_doc(self, document: JSRef<Document>);
|
||||
fn is_in_html_doc(self) -> bool;
|
||||
|
||||
fn wait_until_safe_to_modify_dom(self);
|
||||
|
||||
fn is_element(self) -> bool;
|
||||
fn is_document(self) -> bool;
|
||||
fn is_doctype(self) -> bool;
|
||||
|
@ -460,10 +447,11 @@ pub trait NodeHelpers<'a> {
|
|||
fn get_has_dirty_descendants(self) -> bool;
|
||||
fn set_has_dirty_descendants(self, state: bool);
|
||||
|
||||
/// Marks the given node as `IS_DIRTY`, its siblings as `IS_DIRTY` (to deal
|
||||
/// with sibling selectors), its ancestors as `HAS_DIRTY_DESCENDANTS`, and its
|
||||
/// descendants as `IS_DIRTY`.
|
||||
fn dirty(self);
|
||||
/// Marks the given node as `IS_DIRTY`, its siblings as `HAS_DIRTY_SIBLINGS` (to deal with
|
||||
/// sibling selectors), its ancestors as `HAS_DIRTY_DESCENDANTS`, and its descendants as
|
||||
/// `IS_DIRTY`. If anything more than the node's style was damaged, this method also sets the
|
||||
/// `HAS_CHANGED` flag.
|
||||
fn dirty(self, damage: NodeDamage);
|
||||
|
||||
/// Similar to `dirty`, but will always walk the ancestors to mark them dirty,
|
||||
/// too. This is useful when a node is reparented. The node will frequently
|
||||
|
@ -471,9 +459,9 @@ pub trait NodeHelpers<'a> {
|
|||
/// still need to be marked as `HAS_DIRTY_DESCENDANTS`.
|
||||
///
|
||||
/// See #4170
|
||||
fn force_dirty_ancestors(self);
|
||||
fn force_dirty_ancestors(self, damage: NodeDamage);
|
||||
|
||||
fn dirty_impl(self, force_ancestors: bool);
|
||||
fn dirty_impl(self, damage: NodeDamage, force_ancestors: bool);
|
||||
|
||||
fn dump(self);
|
||||
fn dump_indent(self, indent: uint);
|
||||
|
@ -656,17 +644,20 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
|||
self.set_flag(HAS_DIRTY_DESCENDANTS, state)
|
||||
}
|
||||
|
||||
fn force_dirty_ancestors(self) {
|
||||
self.dirty_impl(true)
|
||||
fn force_dirty_ancestors(self, damage: NodeDamage) {
|
||||
self.dirty_impl(damage, true)
|
||||
}
|
||||
|
||||
fn dirty(self) {
|
||||
self.dirty_impl(false)
|
||||
fn dirty(self, damage: NodeDamage) {
|
||||
self.dirty_impl(damage, false)
|
||||
}
|
||||
|
||||
fn dirty_impl(self, force_ancestors: bool) {
|
||||
fn dirty_impl(self, damage: NodeDamage, force_ancestors: bool) {
|
||||
// 1. Dirty self.
|
||||
self.set_has_changed(true);
|
||||
match damage {
|
||||
NodeStyleDamaged => {}
|
||||
OtherNodeDamage => self.set_has_changed(true),
|
||||
}
|
||||
|
||||
if self.get_is_dirty() && !force_ancestors {
|
||||
return
|
||||
|
@ -830,11 +821,6 @@ impl<'a> NodeHelpers<'a> for JSRef<'a, Node> {
|
|||
.peekable()
|
||||
}
|
||||
|
||||
fn wait_until_safe_to_modify_dom(self) {
|
||||
let document = self.owner_doc().root();
|
||||
document.wait_until_safe_to_modify_dom();
|
||||
}
|
||||
|
||||
fn remove_self(self) {
|
||||
match self.parent_node().root() {
|
||||
Some(parent) => parent.remove_child(self),
|
||||
|
@ -1826,14 +1812,12 @@ impl<'a> NodeMethods for JSRef<'a, Node> {
|
|||
CommentNodeTypeId |
|
||||
TextNodeTypeId |
|
||||
ProcessingInstructionNodeTypeId => {
|
||||
self.wait_until_safe_to_modify_dom();
|
||||
|
||||
let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(self).unwrap();
|
||||
characterdata.set_data(value);
|
||||
|
||||
// Notify the document that the content of this node is different
|
||||
let document = self.owner_doc().root();
|
||||
document.content_changed(self);
|
||||
document.content_changed(self, OtherNodeDamage);
|
||||
}
|
||||
DoctypeNodeTypeId |
|
||||
DocumentNodeTypeId => {}
|
||||
|
@ -2366,3 +2350,13 @@ impl<'a> DisabledStateHelpers for JSRef<'a, Node> {
|
|||
self.set_enabled_state(!has_disabled_attrib);
|
||||
}
|
||||
}
|
||||
|
||||
/// A summary of the changes that happened to a node.
|
||||
#[deriving(Clone, PartialEq)]
|
||||
pub enum NodeDamage {
|
||||
/// The node's `style` attribute changed.
|
||||
NodeStyleDamaged,
|
||||
/// Other parts of a node changed; attributes, text content, etc.
|
||||
OtherNodeDamage,
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ use dom::navigator::Navigator;
|
|||
use dom::performance::Performance;
|
||||
use dom::screen::Screen;
|
||||
use dom::storage::Storage;
|
||||
use layout_interface::NoQuery;
|
||||
use layout_interface::{NoQuery, ReflowForDisplay, ReflowGoal, ReflowQueryType};
|
||||
use page::Page;
|
||||
use script_task::{ExitWindowMsg, ScriptChan, TriggerLoadMsg, TriggerFragmentMsg};
|
||||
use script_task::FromWindow;
|
||||
|
@ -299,9 +299,7 @@ impl Reflectable for Window {
|
|||
}
|
||||
|
||||
pub trait WindowHelpers {
|
||||
fn reflow(self);
|
||||
fn flush_layout(self);
|
||||
fn wait_until_safe_to_modify_dom(self);
|
||||
fn flush_layout(self, goal: ReflowGoal, query: ReflowQueryType);
|
||||
fn init_browser_context(self, doc: JSRef<Document>);
|
||||
fn load_url(self, href: DOMString);
|
||||
fn handle_fire_timer(self, timer_id: TimerId);
|
||||
|
@ -334,18 +332,8 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
})
|
||||
}
|
||||
|
||||
fn reflow(self) {
|
||||
self.page().damage();
|
||||
}
|
||||
|
||||
fn flush_layout(self) {
|
||||
self.page().flush_layout(NoQuery);
|
||||
}
|
||||
|
||||
fn wait_until_safe_to_modify_dom(self) {
|
||||
// FIXME: This disables concurrent layout while we are modifying the DOM, since
|
||||
// our current architecture is entirely unsafe in the presence of races.
|
||||
self.page().join_layout();
|
||||
fn flush_layout(self, goal: ReflowGoal, query: ReflowQueryType) {
|
||||
self.page().flush_layout(goal, query);
|
||||
}
|
||||
|
||||
fn init_browser_context(self, doc: JSRef<Document>) {
|
||||
|
@ -369,7 +357,7 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
|
||||
fn handle_fire_timer(self, timer_id: TimerId) {
|
||||
self.timers.fire_timer(timer_id, self.clone());
|
||||
self.flush_layout();
|
||||
self.flush_layout(ReflowForDisplay, NoQuery);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue