mirror of
https://github.com/servo/servo.git
synced 2025-07-29 18:20:24 +01:00
script: Reflow 200 milliseconds after the <body>
is parsed, like Gecko
does.
This commit is contained in:
parent
8759d42559
commit
9e34e82aec
5 changed files with 65 additions and 7 deletions
|
@ -148,6 +148,8 @@ pub struct Document {
|
||||||
loader: DOMRefCell<DocumentLoader>,
|
loader: DOMRefCell<DocumentLoader>,
|
||||||
/// The current active HTML parser, to allow resuming after interruptions.
|
/// The current active HTML parser, to allow resuming after interruptions.
|
||||||
current_parser: MutNullableHeap<JS<ServoHTMLParser>>,
|
current_parser: MutNullableHeap<JS<ServoHTMLParser>>,
|
||||||
|
/// When we should kick off a reflow. This happens during parsing.
|
||||||
|
reflow_timeout: Cell<Option<u64>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DocumentDerived for EventTarget {
|
impl DocumentDerived for EventTarget {
|
||||||
|
@ -226,6 +228,9 @@ pub trait DocumentHelpers<'a> {
|
||||||
fn set_encoding_name(self, name: DOMString);
|
fn set_encoding_name(self, name: DOMString);
|
||||||
fn content_changed(self, node: JSRef<Node>, damage: NodeDamage);
|
fn content_changed(self, node: JSRef<Node>, damage: NodeDamage);
|
||||||
fn content_and_heritage_changed(self, node: JSRef<Node>, damage: NodeDamage);
|
fn content_and_heritage_changed(self, node: JSRef<Node>, damage: NodeDamage);
|
||||||
|
fn reflow_if_reflow_timer_expired(self);
|
||||||
|
fn set_reflow_timeout(self, timeout: u64);
|
||||||
|
fn disarm_reflow_timeout(self);
|
||||||
fn unregister_named_element(self, to_unregister: JSRef<Element>, id: Atom);
|
fn unregister_named_element(self, to_unregister: JSRef<Element>, id: Atom);
|
||||||
fn register_named_element(self, element: JSRef<Element>, id: Atom);
|
fn register_named_element(self, element: JSRef<Element>, id: Atom);
|
||||||
fn load_anchor_href(self, href: DOMString);
|
fn load_anchor_href(self, href: DOMString);
|
||||||
|
@ -343,11 +348,42 @@ impl<'a> DocumentHelpers<'a> for JSRef<'a, Document> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn content_and_heritage_changed(self, node: JSRef<Node>, damage: NodeDamage) {
|
fn content_and_heritage_changed(self, node: JSRef<Node>, damage: NodeDamage) {
|
||||||
debug!("content_and_heritage_changed on {}", node.debug_str());
|
|
||||||
node.force_dirty_ancestors(damage);
|
node.force_dirty_ancestors(damage);
|
||||||
node.dirty(damage);
|
node.dirty(damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reflows and disarms the timer if the reflow timer has expired.
|
||||||
|
fn reflow_if_reflow_timer_expired(self) {
|
||||||
|
if let Some(reflow_timeout) = self.reflow_timeout.get() {
|
||||||
|
if time::precise_time_ns() < reflow_timeout {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.reflow_timeout.set(None);
|
||||||
|
let window = self.window.root();
|
||||||
|
window.r().reflow(ReflowGoal::ForDisplay,
|
||||||
|
ReflowQueryType::NoQuery,
|
||||||
|
ReflowReason::RefreshTick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Schedules a reflow to be kicked off at the given `timeout` (in `time::precise_time_ns()`
|
||||||
|
/// units). This reflow happens even if the event loop is busy. This is used to display initial
|
||||||
|
/// page content during parsing.
|
||||||
|
fn set_reflow_timeout(self, timeout: u64) {
|
||||||
|
if let Some(existing_timeout) = self.reflow_timeout.get() {
|
||||||
|
if existing_timeout > timeout {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.reflow_timeout.set(Some(timeout))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disables any pending reflow timeouts.
|
||||||
|
fn disarm_reflow_timeout(self) {
|
||||||
|
self.reflow_timeout.set(None)
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove any existing association between the provided id and any elements in this document.
|
/// Remove any existing association between the provided id and any elements in this document.
|
||||||
fn unregister_named_element(self,
|
fn unregister_named_element(self,
|
||||||
to_unregister: JSRef<Element>,
|
to_unregister: JSRef<Element>,
|
||||||
|
@ -1004,6 +1040,7 @@ impl Document {
|
||||||
animation_frame_list: RefCell::new(HashMap::new()),
|
animation_frame_list: RefCell::new(HashMap::new()),
|
||||||
loader: DOMRefCell::new(doc_loader),
|
loader: DOMRefCell::new(doc_loader),
|
||||||
current_parser: Default::default(),
|
current_parser: Default::default(),
|
||||||
|
reflow_timeout: Cell::new(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,11 @@ use dom::attr::{Attr, AttrHelpers};
|
||||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
|
||||||
use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{self, HTMLBodyElementMethods};
|
use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{self, HTMLBodyElementMethods};
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::EventTargetCast;
|
use dom::bindings::codegen::InheritTypes::{EventTargetCast};
|
||||||
use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLElementCast};
|
use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLElementCast};
|
||||||
use dom::bindings::js::{JSRef, Rootable, Temporary};
|
use dom::bindings::js::{JSRef, Rootable, Temporary};
|
||||||
use dom::bindings::utils::Reflectable;
|
use dom::bindings::utils::Reflectable;
|
||||||
use dom::document::Document;
|
use dom::document::{Document, DocumentHelpers};
|
||||||
use dom::element::ElementTypeId;
|
use dom::element::ElementTypeId;
|
||||||
use dom::eventtarget::{EventTarget, EventTargetTypeId, EventTargetHelpers};
|
use dom::eventtarget::{EventTarget, EventTargetTypeId, EventTargetHelpers};
|
||||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||||
|
@ -23,6 +23,11 @@ use util::str::{self, DOMString};
|
||||||
|
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
use time;
|
||||||
|
|
||||||
|
/// How long we should wait before performing the initial reflow after `<body>` is parsed, in
|
||||||
|
/// nanoseconds.
|
||||||
|
const INITIAL_REFLOW_DELAY: u64 = 200_000_000;
|
||||||
|
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct HTMLBodyElement {
|
pub struct HTMLBodyElement {
|
||||||
|
@ -32,9 +37,8 @@ pub struct HTMLBodyElement {
|
||||||
|
|
||||||
impl HTMLBodyElementDerived for EventTarget {
|
impl HTMLBodyElementDerived for EventTarget {
|
||||||
fn is_htmlbodyelement(&self) -> bool {
|
fn is_htmlbodyelement(&self) -> bool {
|
||||||
*self.type_id() ==
|
*self.type_id() == EventTargetTypeId::Node(NodeTypeId::Element(ElementTypeId::HTMLElement(
|
||||||
EventTargetTypeId::Node(
|
HTMLElementTypeId::HTMLBodyElement)))
|
||||||
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +95,16 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
|
||||||
Some(element as &VirtualMethods)
|
Some(element as &VirtualMethods)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bind_to_tree(&self, tree_in_doc: bool) {
|
||||||
|
if let Some(ref s) = self.super_type() {
|
||||||
|
s.bind_to_tree(tree_in_doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
let window = window_from_node(*self).root();
|
||||||
|
let document = window.r().Document().root();
|
||||||
|
document.r().set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
fn after_set_attr(&self, attr: JSRef<Attr>) {
|
fn after_set_attr(&self, attr: JSRef<Attr>) {
|
||||||
if let Some(ref s) = self.super_type() {
|
if let Some(ref s) = self.super_type() {
|
||||||
s.after_set_attr(attr);
|
s.after_set_attr(attr);
|
||||||
|
|
|
@ -303,6 +303,11 @@ impl<'a> PrivateServoHTMLParserHelpers for JSRef<'a, ServoHTMLParser> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let document = self.document.root();
|
||||||
|
document.r().reflow_if_reflow_timer_expired();
|
||||||
|
}
|
||||||
|
|
||||||
let mut pending_input = self.pending_input.borrow_mut();
|
let mut pending_input = self.pending_input.borrow_mut();
|
||||||
if !pending_input.is_empty() {
|
if !pending_input.is_empty() {
|
||||||
let chunk = pending_input.remove(0);
|
let chunk = pending_input.remove(0);
|
||||||
|
|
|
@ -81,6 +81,7 @@ enum WindowState {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ReflowReason {
|
pub enum ReflowReason {
|
||||||
CachedPageNeededReflow,
|
CachedPageNeededReflow,
|
||||||
|
RefreshTick,
|
||||||
FirstLoad,
|
FirstLoad,
|
||||||
KeyEvent,
|
KeyEvent,
|
||||||
MouseEvent,
|
MouseEvent,
|
||||||
|
@ -1046,6 +1047,7 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason:
|
||||||
|
|
||||||
debug_msg.push_str(match *reason {
|
debug_msg.push_str(match *reason {
|
||||||
ReflowReason::CachedPageNeededReflow => "\tCachedPageNeededReflow",
|
ReflowReason::CachedPageNeededReflow => "\tCachedPageNeededReflow",
|
||||||
|
ReflowReason::RefreshTick => "\tRefreshTick",
|
||||||
ReflowReason::FirstLoad => "\tFirstLoad",
|
ReflowReason::FirstLoad => "\tFirstLoad",
|
||||||
ReflowReason::KeyEvent => "\tKeyEvent",
|
ReflowReason::KeyEvent => "\tKeyEvent",
|
||||||
ReflowReason::MouseEvent => "\tMouseEvent",
|
ReflowReason::MouseEvent => "\tMouseEvent",
|
||||||
|
|
|
@ -1565,7 +1565,7 @@ impl ScriptTask {
|
||||||
|
|
||||||
// Kick off the initial reflow of the page.
|
// Kick off the initial reflow of the page.
|
||||||
debug!("kicking off initial reflow of {:?}", final_url);
|
debug!("kicking off initial reflow of {:?}", final_url);
|
||||||
|
document.r().disarm_reflow_timeout();
|
||||||
document.r().content_changed(NodeCast::from_ref(document.r()),
|
document.r().content_changed(NodeCast::from_ref(document.r()),
|
||||||
NodeDamage::OtherNodeDamage);
|
NodeDamage::OtherNodeDamage);
|
||||||
let window = window_from_node(document.r()).root();
|
let window = window_from_node(document.r()).root();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue