Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

script: Reflow 200 milliseconds after the `<body>` is parsed, like Gecko does. #6028

Merged
merged 2 commits into from May 26, 2015
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

script: Reflow 200 milliseconds after the `<body>` is parsed, like Gecko

does.
  • Loading branch information
pcwalton committed May 26, 2015
commit 9e34e82aec1ef7d094eda129c33a5933de42a877
@@ -148,6 +148,8 @@ pub struct Document {
loader: DOMRefCell<DocumentLoader>,
/// The current active HTML parser, to allow resuming after interruptions.
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 {
@@ -226,6 +228,9 @@ pub trait DocumentHelpers<'a> {
fn set_encoding_name(self, name: DOMString);
fn content_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 register_named_element(self, element: JSRef<Element>, id: Atom);
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) {
debug!("content_and_heritage_changed on {}", node.debug_str());
node.force_dirty_ancestors(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.
fn unregister_named_element(self,
to_unregister: JSRef<Element>,
@@ -1004,6 +1040,7 @@ impl Document {
animation_frame_list: RefCell::new(HashMap::new()),
loader: DOMRefCell::new(doc_loader),
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::HTMLBodyElementBinding::{self, HTMLBodyElementMethods};
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::js::{JSRef, Rootable, Temporary};
use dom::bindings::utils::Reflectable;
use dom::document::Document;
use dom::document::{Document, DocumentHelpers};
use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId, EventTargetHelpers};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@@ -23,6 +23,11 @@ use util::str::{self, DOMString};

use std::borrow::ToOwned;
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]
pub struct HTMLBodyElement {
@@ -32,9 +37,8 @@ pub struct HTMLBodyElement {

impl HTMLBodyElementDerived for EventTarget {
fn is_htmlbodyelement(&self) -> bool {
*self.type_id() ==
EventTargetTypeId::Node(
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement)))
*self.type_id() == EventTargetTypeId::Node(NodeTypeId::Element(ElementTypeId::HTMLElement(
HTMLElementTypeId::HTMLBodyElement)))
}
}

@@ -91,6 +95,16 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
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>) {
if let Some(ref s) = self.super_type() {
s.after_set_attr(attr);
@@ -303,6 +303,11 @@ impl<'a> PrivateServoHTMLParserHelpers for JSRef<'a, ServoHTMLParser> {
break;
}

{
let document = self.document.root();
document.r().reflow_if_reflow_timer_expired();
}

let mut pending_input = self.pending_input.borrow_mut();
if !pending_input.is_empty() {
let chunk = pending_input.remove(0);
@@ -81,6 +81,7 @@ enum WindowState {
#[derive(Debug)]
pub enum ReflowReason {
CachedPageNeededReflow,
RefreshTick,
FirstLoad,
KeyEvent,
MouseEvent,
@@ -1046,6 +1047,7 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason:

debug_msg.push_str(match *reason {
ReflowReason::CachedPageNeededReflow => "\tCachedPageNeededReflow",
ReflowReason::RefreshTick => "\tRefreshTick",
ReflowReason::FirstLoad => "\tFirstLoad",
ReflowReason::KeyEvent => "\tKeyEvent",
ReflowReason::MouseEvent => "\tMouseEvent",
@@ -1565,7 +1565,7 @@ impl ScriptTask {

// Kick off the initial reflow of the page.
debug!("kicking off initial reflow of {:?}", final_url);

document.r().disarm_reflow_timeout();
document.r().content_changed(NodeCast::from_ref(document.r()),
NodeDamage::OtherNodeDamage);
let window = window_from_node(document.r()).root();
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.