Files
tubestation/servo/components/script/page.rs
Michael Wu ae3ff6be00 servo: Merge #6150 - Upgrade to Spidermonkey 39 (from servo:smupgrade3); r=mbrubeck
> Here it is.
>
> ~~There's two major things that are unfinished here:~~
> - ~~Dealing with the unroot_must_root lint. I'm not sure about the value of this lint with the new rooting API.~~ Done.
> - ~~Updating the Cargo.locks to point to the new SM and SM binding.~~ Done.
>
> I also included my fixes for the rust update, but these will disappear in a rebase. A rust update is necessary to support calling `Drop` on `Heap<T>` correctly when `Heap<T>` is inside a `Rc<T>`. Otherwise `&self` points to the wrong location.
>
> Incremental GC is disabled here. I'm not sure how to deal with the incremental barriers so that's left for later.
>
> Generational GC works. SM doesn't work without it.
>
> The biggest change here is to the rooting API. `Root` was made movable, and `Temporary` and `JSRef` was removed. Movable `Root`s means there's no need for `Temporary`, and `JSRef`s aren't needed generally since it can be assumed that being able to obtain a reference to a dom object means it's already rooted. References have their lifetime bound to the Roots that provided them. DOM objects that haven't passed through `reflect_dom_object` don't need to be rooted, and DOM objects that have passed through `reflect_dom_object` can't be obtained without being rooted through `native_from_reflector_jsmanaged` or `JS::<T>::root()`.
>
> Support for `Heap<T>` ended up messier than I expected. It's split into two commits, but only because it's a bit difficult to fold them together. Supporting `Heap<T>` properly requires that that `Heap::<T>::set()` be called on something that won't move. I removed the Copy and Clone trait from `Heap<T>` so `Cell` can't hold `Heap<T>` - only `UnsafeCell` can hold it.
>
> `CallbackObject` is a bit tricky - I moved all callbacks into `Rc<T>` in order to make sure that the pointer inside to a `*mut JSObject` doesn't move. This is necessary for supporting `Heap<T>`.
>
> `RootedCollectionSet` is very general purpose now. Anything with `JSTraceable` can be rooted by `RootedCollectionSet`/`RootedTraceable`. Right now, `RootedTraceable` is only used to hold down dom objects before they're fully attached to their reflector. I had to make a custom mechanism to dispatch the trace call - couldn't figure out how to get trait objects working for this case.
>
> This has been tested with the following zeal settings:
>
> GC after every allocation
> JS_GC_ZEAL=2,1
>
> GC after every 100 allocations (important for catching use-after-free bugs)
> JS_GC_ZEAL=2,100
>
> Verify pre barriers
> JS_GC_ZEAL=4,1
>
> Verify post barriers
> JS_GC_ZEAL=11,1

Source-Repo: https://github.com/servo/servo
Source-Revision: e7808c526c348fea5e3b48af70b7f1a066652097
2015-06-19 16:46:55 -06:00

144 lines
3.7 KiB
Rust

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::cell::DOMRefCell;
use dom::bindings::js::{JS, Root};
use dom::document::{Document, DocumentHelpers};
use dom::node::NodeHelpers;
use dom::window::Window;
use msg::constellation_msg::PipelineId;
use std::cell::Cell;
use std::rc::Rc;
use url::Url;
/// Encapsulates a handle to a frame in a frame tree.
#[jstraceable]
pub struct Page {
/// Pipeline id associated with this page.
id: PipelineId,
/// The outermost frame containing the document and window.
frame: DOMRefCell<Option<Frame>>,
/// Cached copy of the most recent url loaded by the script, after all redirections.
/// TODO(tkuehn): this currently does not follow any particular caching policy
/// and simply caches pages forever (!).
url: Url,
/// Indicates if reflow is required when reloading.
needs_reflow: Cell<bool>,
// Child Pages.
pub children: DOMRefCell<Vec<Rc<Page>>>,
}
pub struct PageIterator {
stack: Vec<Rc<Page>>,
}
pub trait IterablePage {
fn iter(&self) -> PageIterator;
fn find(&self, id: PipelineId) -> Option<Rc<Page>>;
}
impl IterablePage for Rc<Page> {
fn iter(&self) -> PageIterator {
PageIterator {
stack: vec!(self.clone()),
}
}
fn find(&self, id: PipelineId) -> Option<Rc<Page>> {
if self.id == id { return Some(self.clone()); }
for page in self.children.borrow().iter() {
let found = page.find(id);
if found.is_some() { return found; }
}
None
}
}
impl Page {
pub fn new(id: PipelineId, url: Url) -> Page {
Page {
id: id,
frame: DOMRefCell::new(None),
url: url,
needs_reflow: Cell::new(true),
children: DOMRefCell::new(vec!()),
}
}
pub fn pipeline(&self) -> PipelineId {
self.id
}
pub fn window(&self) -> Root<Window> {
self.frame.borrow().as_ref().unwrap().window.root()
}
pub fn document(&self) -> Root<Document> {
self.frame.borrow().as_ref().unwrap().document.root()
}
// must handle root case separately
pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> {
let remove_idx = {
self.children
.borrow_mut()
.iter_mut()
.position(|page_tree| page_tree.id == id)
};
match remove_idx {
Some(idx) => Some(self.children.borrow_mut().remove(idx)),
None => {
self.children
.borrow_mut()
.iter_mut()
.filter_map(|page_tree| page_tree.remove(id))
.next()
}
}
}
}
impl Iterator for PageIterator {
type Item = Rc<Page>;
fn next(&mut self) -> Option<Rc<Page>> {
match self.stack.pop() {
Some(next) => {
for child in next.children.borrow().iter() {
self.stack.push(child.clone());
}
Some(next)
},
None => None,
}
}
}
impl Page {
pub fn set_reflow_status(&self, status: bool) -> bool {
let old = self.needs_reflow.get();
self.needs_reflow.set(status);
old
}
pub fn set_frame(&self, frame: Option<Frame>) {
*self.frame.borrow_mut() = frame;
}
}
/// Information for one frame in the browsing context.
#[jstraceable]
#[must_root]
pub struct Frame {
/// The document for this frame.
pub document: JS<Document>,
/// The window object for this frame.
pub window: JS<Window>,
}