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

Implement a safe, mostly-sound rooting rooting strategy. #2101

Merged
merged 16 commits into from May 3, 2014
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -697,6 +697,7 @@ do
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-android-ndk=${CFG_ANDROID_NDK_PATH}"
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-android-toolchain=${CFG_ANDROID_CROSS_PATH}"
fi
CONFIGURE_ARGS="${CONFIGURE_ARGS} --enable-gczeal"
;;
support/skia/skia)
# Right now the skia configure script actually ignores --enable-debug and the
@@ -45,7 +45,6 @@ use layout::wrapper::{Before, BeforeBlock, After, AfterBlock, Normal};

use gfx::display_list::OpaqueNode;
use gfx::font_context::FontContext;
use script::dom::bindings::codegen::InheritTypes::TextCast;
use script::dom::bindings::js::JS;
use script::dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId};
use script::dom::element::{HTMLObjectElementTypeId};
@@ -1064,8 +1063,8 @@ impl<'ln> NodeUtils for ThreadSafeLayoutNode<'ln> {
match self.type_id() {
Some(TextNodeTypeId) => {
unsafe {
let text: JS<Text> = TextCast::to(self.get_jsmanaged()).unwrap();
if !is_whitespace(text.get().characterdata.data) {
let text: JS<Text> = self.get_jsmanaged().transmute_copy();
if !is_whitespace((*text.unsafe_get()).characterdata.data) {
return false
}

@@ -37,10 +37,11 @@ use script::dom::bindings::codegen::InheritTypes::{HTMLIFrameElementDerived};
use script::dom::bindings::codegen::InheritTypes::{HTMLImageElementDerived, TextDerived};
use script::dom::bindings::js::JS;
use script::dom::element::{Element, HTMLAreaElementTypeId, HTMLAnchorElementTypeId};
use script::dom::element::{HTMLLinkElementTypeId};
use script::dom::element::{HTMLLinkElementTypeId, LayoutElementHelpers, RawLayoutElementHelpers};
use script::dom::htmliframeelement::HTMLIFrameElement;
use script::dom::htmlimageelement::HTMLImageElement;
use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, Node, NodeTypeId, NodeHelpers};
use script::dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers};
use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, Node, NodeTypeId};
use script::dom::node::{LayoutNodeHelpers, RawLayoutNodeHelpers};
use script::dom::text::Text;
use servo_msg::constellation_msg::{PipelineId, SubpageId};
use servo_util::namespace;
@@ -95,7 +96,7 @@ pub trait TLayoutNode {
fail!("not an image!")
}
let image_element: JS<HTMLImageElement> = self.get_jsmanaged().transmute_copy();
(*image_element.unsafe_get()).image().as_ref().map(|url| (*url).clone())
image_element.image().as_ref().map(|url| (*url).clone())
}
}

@@ -163,7 +164,9 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {
}

fn type_id(&self) -> Option<NodeTypeId> {
Some(self.node.type_id())
unsafe {
Some(self.node.type_id_for_layout())
}
}

unsafe fn get_jsmanaged<'a>(&'a self) -> &'a JS<Node> {
@@ -172,7 +175,7 @@ impl<'ln> TLayoutNode for LayoutNode<'ln> {

fn first_child(&self) -> Option<LayoutNode<'ln>> {
unsafe {
self.get().first_child_ref().map(|node| self.new_with_this_lifetime(node))
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node))
}
}

@@ -221,28 +224,29 @@ impl<'ln> LayoutNode<'ln> {
impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
fn parent_node(&self) -> Option<LayoutNode<'ln>> {
unsafe {
self.get().parent_node_ref().map(|node| self.new_with_this_lifetime(node))
self.node.parent_node_ref().map(|node| self.new_with_this_lifetime(node))
}
}

fn prev_sibling(&self) -> Option<LayoutNode<'ln>> {
unsafe {
self.get().prev_sibling_ref().map(|node| self.new_with_this_lifetime(node))
self.node.prev_sibling_ref().map(|node| self.new_with_this_lifetime(node))
}
}

fn next_sibling(&self) -> Option<LayoutNode<'ln>> {
unsafe {
self.get().next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
self.node.next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
}
}

/// If this is an element, accesses the element data. Fails if this is not an element node.
#[inline]
fn as_element(&self) -> LayoutElement<'ln> {
unsafe {
assert!(self.node.is_element_for_layout());
let elem: JS<Element> = self.node.transmute_copy();
let element = elem.get();
let element = &*elem.unsafe_get();
LayoutElement {
element: cast::transmute_region(element),
}
@@ -258,16 +262,17 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
}

fn match_attr(&self, attr: &AttrSelector, test: |&str| -> bool) -> bool {
let element = self.as_element();
let name = unsafe {
if element.element.html_element_in_html_document_for_layout() {
let element: JS<Element> = self.node.transmute_copy();
if element.html_element_in_html_document_for_layout() {
attr.lower_name.as_slice()
} else {
attr.name.as_slice()
}
};
match attr.namespace {
SpecificNamespace(ref ns) => {
let element = self.as_element();
element.get_attr(ns, name)
.map_or(false, |attr| test(attr))
},
@@ -459,7 +464,7 @@ impl<'ln> TLayoutNode for ThreadSafeLayoutNode<'ln> {
}

unsafe {
self.get().first_child_ref().map(|node| self.new_with_this_lifetime(node))
self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node))
}
}

@@ -509,10 +514,10 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
/// Returns the next sibling of this node. Unsafe and private because this can lead to races.
unsafe fn next_sibling(&self) -> Option<ThreadSafeLayoutNode<'ln>> {
if self.pseudo == Before || self.pseudo == BeforeBlock {
return self.get().first_child_ref().map(|node| self.new_with_this_lifetime(node))
return self.get_jsmanaged().first_child_ref().map(|node| self.new_with_this_lifetime(node))
}

self.node.get().next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
self.get_jsmanaged().next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
}

/// Returns an iterator over this node's children.
@@ -527,7 +532,8 @@ impl<'ln> ThreadSafeLayoutNode<'ln> {
#[inline]
pub fn as_element(&self) -> ThreadSafeLayoutElement {
unsafe {
let elem: JS<Element> = self.node.get_jsmanaged().transmute_copy();
assert!(self.get_jsmanaged().is_element_for_layout());
let elem: JS<Element> = self.get_jsmanaged().transmute_copy();
let element = elem.unsafe_get();
// FIXME(pcwalton): Workaround until Rust gets multiple lifetime parameters on
// implementations.
@@ -4,7 +4,7 @@

use dom::bindings::codegen::BindingDeclarations::AttrBinding;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::js::JS;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::Element;
use dom::node::Node;
@@ -45,33 +45,34 @@ impl Reflectable for Attr {
impl Attr {
fn new_inherited(local_name: DOMString, value: DOMString,
name: DOMString, namespace: Namespace,
prefix: Option<DOMString>, owner: JS<Element>) -> Attr {
prefix: Option<DOMString>, owner: &JSRef<Element>) -> Attr {
Attr {
reflector_: Reflector::new(),
local_name: local_name,
value: value,
name: name, //TODO: Intern attribute names
namespace: namespace,
prefix: prefix,
owner: owner,
owner: owner.unrooted(),
}
}

pub fn new(window: &JS<Window>, local_name: DOMString, value: DOMString,
pub fn new(window: &JSRef<Window>, local_name: DOMString, value: DOMString,
name: DOMString, namespace: Namespace,
prefix: Option<DOMString>, owner: JS<Element>) -> JS<Attr> {
prefix: Option<DOMString>, owner: &JSRef<Element>) -> Temporary<Attr> {
let attr = Attr::new_inherited(local_name, value, name, namespace, prefix, owner);
reflect_dom_object(~attr, window, AttrBinding::Wrap)
}

pub fn set_value(&mut self, set_type: AttrSettingType, value: DOMString) {
let node: JS<Node> = NodeCast::from(&self.owner);
let mut owner = self.owner.root();
let node: &mut JSRef<Node> = NodeCast::from_mut_ref(&mut *owner);
let namespace_is_null = self.namespace == namespace::Null;

match set_type {
ReplacedAttr => {
if namespace_is_null {
vtable_for(&node).before_remove_attr(self.local_name.clone(), self.value.clone());
vtable_for(node).before_remove_attr(self.local_name.clone(), self.value.clone());
}
}
FirstSetAttr => {}
@@ -80,7 +81,7 @@ impl Attr {
self.value = value;

if namespace_is_null {
vtable_for(&node).after_set_attr(self.local_name.clone(), self.value.clone());
vtable_for(node).after_set_attr(self.local_name.clone(), self.value.clone());
}
}

@@ -89,31 +90,40 @@ impl Attr {
}
}

impl Attr {
pub fn LocalName(&self) -> DOMString {
pub trait AttrMethods {
fn LocalName(&self) -> DOMString;
fn Value(&self) -> DOMString;
fn SetValue(&mut self, value: DOMString);
fn Name(&self) -> DOMString;
fn GetNamespaceURI(&self) -> Option<DOMString>;
fn GetPrefix(&self) -> Option<DOMString>;
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
fn LocalName(&self) -> DOMString {
self.local_name.clone()
}

pub fn Value(&self) -> DOMString {
fn Value(&self) -> DOMString {
self.value.clone()
}

pub fn SetValue(&mut self, value: DOMString) {
fn SetValue(&mut self, value: DOMString) {
self.set_value(ReplacedAttr, value);
}

pub fn Name(&self) -> DOMString {
fn Name(&self) -> DOMString {
self.name.clone()
}

pub fn GetNamespaceURI(&self) -> Option<DOMString> {
fn GetNamespaceURI(&self) -> Option<DOMString> {
match self.namespace.to_str() {
"" => None,
url => Some(url.to_owned()),
}
}

pub fn GetPrefix(&self) -> Option<DOMString> {
fn GetPrefix(&self) -> Option<DOMString> {
self.prefix.clone()
}
}
@@ -4,7 +4,7 @@

use dom::attr::Attr;
use dom::bindings::codegen::BindingDeclarations::AttrListBinding;
use dom::bindings::js::JS;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::Element;
use dom::window::Window;
@@ -17,28 +17,36 @@ pub struct AttrList {
}

impl AttrList {
pub fn new_inherited(window: JS<Window>, elem: JS<Element>) -> AttrList {
pub fn new_inherited(window: &JSRef<Window>, elem: &JSRef<Element>) -> AttrList {
AttrList {
reflector_: Reflector::new(),
window: window,
owner: elem
window: window.unrooted(),
owner: elem.unrooted(),
}
}

pub fn new(window: &JS<Window>, elem: &JS<Element>) -> JS<AttrList> {
reflect_dom_object(~AttrList::new_inherited(window.clone(), elem.clone()),
pub fn new(window: &JSRef<Window>, elem: &JSRef<Element>) -> Temporary<AttrList> {
reflect_dom_object(~AttrList::new_inherited(window, elem),
window, AttrListBinding::Wrap)
}
}

pub trait AttrListMethods {
fn Length(&self) -> u32;
fn Item(&self, index: u32) -> Option<Temporary<Attr>>;
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Temporary<Attr>>;
}

pub fn Length(&self) -> u32 {
self.owner.get().attrs.len() as u32
impl<'a> AttrListMethods for JSRef<'a, AttrList> {
fn Length(&self) -> u32 {
self.owner.root().attrs.len() as u32
}

pub fn Item(&self, index: u32) -> Option<JS<Attr>> {
self.owner.get().attrs.as_slice().get(index as uint).map(|x| x.clone())
fn Item(&self, index: u32) -> Option<Temporary<Attr>> {
self.owner.root().attrs.as_slice().get(index as uint).map(|x| Temporary::new(x.clone()))
}

pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Attr>> {
fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Temporary<Attr>> {
let item = self.Item(index);
*found = item.is_some();
item
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.