Remove JS::get/get_mut to enforce sound rooting practices.

This commit is contained in:
Josh Matthews 2014-04-10 17:11:08 -04:00
parent d7b96db33c
commit dfdda0098a
13 changed files with 114 additions and 131 deletions

View file

@ -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
}

View file

@ -242,7 +242,7 @@ impl<'ln> TNode<LayoutElement<'ln>> for LayoutNode<'ln> {
fn as_element(&self) -> LayoutElement<'ln> {
unsafe {
let elem: JS<Element> = self.node.transmute_copy();
let element = elem.get();
let element = &*elem.unsafe_get();
LayoutElement {
element: cast::transmute_region(element),
}
@ -509,10 +509,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().unsafe_get()).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().unsafe_get()).next_sibling_ref().map(|node| self.new_with_this_lifetime(node))
}
/// Returns an iterator over this node's children.

View file

@ -4,7 +4,7 @@
use dom::attr::Attr;
use dom::bindings::codegen::BindingDeclarations::AttrListBinding;
use dom::bindings::js::{JS, JSRef, Unrooted};
use dom::bindings::js::{JS, JSRef, Unrooted, RootCollection};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::Element;
use dom::window::Window;
@ -31,11 +31,13 @@ impl AttrList {
}
pub fn Length(&self) -> u32 {
self.owner.get().attrs.len() as u32
let roots = RootCollection::new();
self.owner.root(&roots).attrs.len() as u32
}
pub fn Item(&self, index: u32) -> Option<Unrooted<Attr>> {
self.owner.get().attrs.as_slice().get(index as uint).map(|x| Unrooted::new(x.clone()))
let roots = RootCollection::new();
self.owner.root(&roots).attrs.as_slice().get(index as uint).map(|x| Unrooted::new(x.clone()))
}
pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Unrooted<Attr>> {

View file

@ -2243,12 +2243,7 @@ class CGCallGenerator(CGThing):
self.cgRoot.append(CGGeneric("result = result_fallible.unwrap();"))
if typeRetValNeedsRooting(returnType):
rooted_value = CGGeneric("result.root(&roots).root_ref().unrooted()")
if returnType.nullable():
rooted_value = CGWrapper(rooted_value, pre="result.map(|result| ", post=")")
rooted_value = CGWrapper(rooted_value, pre="let result = ", post=";")
self.cgRoot.append(rooted_value)
self.cgRoot.append(CGGeneric("let result = result.root(&roots);"))
def define(self):
return self.cgRoot.define()
@ -4321,7 +4316,7 @@ class CGBindingRoot(CGThing):
'js::glue::{RUST_JS_NumberValue, RUST_JSID_IS_STRING}',
'dom::types::*',
'dom::bindings',
'dom::bindings::js::{JS, JSRef, RootCollection, RootedReference, Unrooted}',
'dom::bindings::js::{JS, JSRef, RootCollection, RootedReference, Unrooted, OptionalRootable}',
'dom::bindings::utils::{CreateDOMGlobal, CreateInterfaceObjects2}',
'dom::bindings::utils::{ConstantSpec, cx_for_dom_object, Default}',
'dom::bindings::utils::{dom_object_slot, DOM_OBJECT_SLOT, DOMClass}',
@ -5320,19 +5315,6 @@ class GlobalGenRoots():
derived += [CGGeneric('\n')]
cast = [CGGeneric(string.Template('''pub trait ${castTraitName} {
#[inline(always)]
fn from<T: ${fromBound}>(derived: &JS<T>) -> JS<Self> {
unsafe { derived.clone().transmute() }
}
#[inline(always)]
fn to<T: ${toBound}+Reflectable>(base: &JS<T>) -> Option<JS<Self>> {
match base.get().${checkFn}() {
true => unsafe { Some(base.clone().transmute()) },
false => None
}
}
#[inline(always)]
fn to_ref<'a, 'b, T: ${toBound}+Reflectable>(base: &'a JSRef<'b, T>) -> Option<&'a JSRef<'b, Self>> {
match base.get().${checkFn}() {
@ -5350,19 +5332,16 @@ class GlobalGenRoots():
}
#[inline(always)]
unsafe fn to_unchecked<T: ${toBound}+Reflectable>(base: &JS<T>) -> JS<Self> {
assert!(base.get().${checkFn}());
base.clone().transmute()
}
fn from_ref<'a, 'b, T: ${fromBound}>(derived: &'a JSRef<'b, T>) -> &'a JSRef<'b, Self> {
unsafe { derived.transmute() }
}
#[inline(always)]
fn from_mut_ref<'a, 'b, T: ${fromBound}>(derived: &'a mut JSRef<'b, T>) -> &'a mut JSRef<'b, Self> {
unsafe { derived.transmute_mut() }
}
#[inline(always)]
fn from_unrooted<T: ${fromBound}+Reflectable>(derived: Unrooted<T>) -> Unrooted<Self> {
unsafe { derived.transmute() }
}

View file

@ -2,7 +2,7 @@
* 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::js::{JS, JSRef};
use dom::bindings::js::{JS, JSRef, Root};
use dom::bindings::str::ByteString;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::bindings::utils::jsstring_to_str;
@ -316,7 +316,7 @@ impl<T: Reflectable+IDLInterface> FromJSValConvertible<()> for JS<T> {
}
}
impl<T: Reflectable> ToJSValConvertible for JS<T> {
impl<'a, 'b, T: Reflectable> ToJSValConvertible for Root<'a, 'b, T> {
fn to_jsval(&self, cx: *JSContext) -> JSVal {
self.reflector().to_jsval(cx)
}

View file

@ -106,31 +106,23 @@ impl<T: Reflectable> JS<T> {
}
}
//XXXjdm This is disappointing. This only gets called from trace hooks, in theory,
// so it's safe to assume that self is rooted and thereby safe to access.
impl<T: Reflectable> Reflectable for JS<T> {
fn reflector<'a>(&'a self) -> &'a Reflector {
self.get().reflector()
unsafe {
(*self.unsafe_get()).reflector()
}
}
fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
self.get_mut().mut_reflector()
unsafe {
(*self.unsafe_get()).mut_reflector()
}
}
}
impl<T: Reflectable> JS<T> {
pub fn get<'a>(&'a self) -> &'a T {
let borrowed = self.ptr.borrow();
unsafe {
&**borrowed
}
}
pub fn get_mut<'a>(&'a mut self) -> &'a mut T {
let mut borrowed = self.ptr.borrow_mut();
unsafe {
&mut **borrowed
}
}
/// Returns an unsafe pointer to the interior of this JS object without touching the borrow
/// flags. This is the only method that be safely accessed from layout. (The fact that this
/// is unsafe is what necessitates the layout wrappers.)
@ -213,6 +205,16 @@ impl<T: Reflectable> OptionalRootable<T> for Option<Unrooted<T>> {
}
}
pub trait OptionalRootedRootable<T> {
fn root<'a, 'b>(&self, roots: &'a RootCollection) -> Option<Root<'a, 'b, T>>;
}
impl<T: Reflectable> OptionalRootedRootable<T> for Option<JS<T>> {
fn root<'a, 'b>(&self, roots: &'a RootCollection) -> Option<Root<'a, 'b, T>> {
self.as_ref().map(|inner| inner.root(roots))
}
}
pub trait ResultRootable<T,U> {
fn root<'a, 'b>(self, roots: &'a RootCollection) -> Result<Root<'a, 'b, T>, U>;
}

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::PrototypeList;
use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH;
use dom::bindings::conversions::{FromJSValConvertible, IDLInterface};
use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted};
use dom::bindings::js::{JS, JSRef, RootCollection, Unrooted, Root};
use dom::bindings::trace::Untraceable;
use dom::browsercontext;
use dom::window;
@ -602,13 +602,16 @@ pub extern fn wrap_for_same_compartment(cx: *JSContext, obj: *JSObject) -> *JSOb
pub extern fn outerize_global(_cx: *JSContext, obj: JSHandleObject) -> *JSObject {
unsafe {
let roots = RootCollection::new();
debug!("outerizing");
let obj = *obj.unnamed;
let win: JS<window::Window> =
let win: Root<window::Window> =
unwrap_jsmanaged(obj,
IDLInterface::get_prototype_id(None::<window::Window>),
IDLInterface::get_prototype_depth(None::<window::Window>)).unwrap();
win.get().browser_context.get_ref().window_proxy()
IDLInterface::get_prototype_depth(None::<window::Window>))
.unwrap()
.root(&roots);
win.deref().browser_context.get_ref().window_proxy()
}
}

View file

@ -2,7 +2,7 @@
* 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::js::{JS, JSRef};
use dom::bindings::js::{JS, JSRef, Unrooted, RootCollection};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::Reflectable;
use dom::document::Document;
@ -32,13 +32,14 @@ impl BrowserContext {
context
}
pub fn active_document(&self) -> JS<Document> {
self.history.get(self.active_index).document.clone()
pub fn active_document(&self) -> Unrooted<Document> {
Unrooted::new(self.history.get(self.active_index).document.clone())
}
pub fn active_window(&self) -> JS<Window> {
let doc = self.active_document();
doc.get().window.clone()
pub fn active_window(&self) -> Unrooted<Window> {
let roots = RootCollection::new();
let doc = self.active_document().root(&roots);
Unrooted::new(doc.deref().window.clone())
}
pub fn window_proxy(&self) -> *JSObject {
@ -47,7 +48,8 @@ impl BrowserContext {
}
pub fn create_window_proxy(&self) -> *JSObject {
let win = self.active_window();
let roots = RootCollection::new();
let win = self.active_window().root(&roots);
let page = win.get().page();
let js_info = page.js_info();

View file

@ -660,8 +660,9 @@ impl Document {
pub fn Location(&mut self, _abstract_self: &JSRef<Document>) -> Unrooted<Location> {
let roots = RootCollection::new();
let window = self.window.root(&roots);
self.window.get_mut().Location(&*window)
let mut window = self.window.root(&roots);
let window_alias = self.window.root(&roots);
window.get_mut().Location(&*window_alias)
}
pub fn Children(&self, abstract_self: &JSRef<Document>) -> Unrooted<HTMLCollection> {
@ -695,11 +696,13 @@ impl Document {
}
pub fn damage_and_reflow(&self, damage: DocumentDamageLevel) {
self.window.get().damage_and_reflow(damage);
let roots = RootCollection::new();
self.window.root(&roots).damage_and_reflow(damage);
}
pub fn wait_until_safe_to_modify_dom(&self) {
self.window.get().wait_until_safe_to_modify_dom();
let roots = RootCollection::new();
self.window.root(&roots).wait_until_safe_to_modify_dom();
}

View file

@ -61,9 +61,9 @@ impl DOMImplementation {
Name => Err(NamespaceError),
// Step 3.
QName => {
let document = self.owner.get().Document();
let document = document.root(&roots);
Ok(DocumentType::new(qname, Some(pubid), Some(sysid), &document.root_ref()))
let owner = self.owner.root(&roots);
let document = owner.deref().Document().root(&roots);
Ok(DocumentType::new(qname, Some(pubid), Some(sysid), &*document))
}
}
}

View file

@ -216,16 +216,15 @@ pub trait AttributeHandlers {
impl<'a> AttributeHandlers for JSRef<'a, Element> {
fn get_attribute(&self, namespace: Namespace, name: &str) -> Option<Unrooted<Attr>> {
let roots = RootCollection::new();
if self.get().html_element_in_html_document() {
self.get().attrs.iter().find(|attr| {
let attr = attr.get();
self.get().attrs.iter().map(|attr| attr.root(&roots)).find(|attr| {
name.to_ascii_lower() == attr.local_name && attr.namespace == namespace
}).map(|x| Unrooted::new(x.clone()))
}).map(|x| Unrooted::new_rooted(&*x))
} else {
self.get().attrs.iter().find(|attr| {
let attr = attr.get();
self.get().attrs.iter().map(|attr| attr.root(&roots)).find(|attr| {
name == attr.local_name && attr.namespace == namespace
}).map(|x| Unrooted::new(x.clone()))
}).map(|x| Unrooted::new_rooted(&*x))
}
}
@ -279,7 +278,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
}
};
self.get_mut().attrs.get_mut(idx).get_mut().set_value(set_type, value);
self.get_mut().attrs.get(idx).root(&roots).set_value(set_type, value);
}
// http://dom.spec.whatwg.org/#dom-element-setattribute
@ -369,21 +368,22 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
}
fn remove_attribute(&mut self, namespace: Namespace, name: DOMString) -> ErrorResult {
let roots = RootCollection::new();
let (_, local_name) = get_attribute_parts(name.clone());
let self_alias = self.clone();
let node: &JSRef<Node> = NodeCast::from_ref(&self_alias);
node.wait_until_safe_to_modify_dom();
let idx = self.get().attrs.iter().position(|attr| {
attr.get().local_name == local_name
let idx = self.get().attrs.iter().map(|attr| attr.root(&roots)).position(|attr| {
attr.local_name == local_name
});
match idx {
None => (),
Some(idx) => {
if namespace == namespace::Null {
let removed_raw_value = self.get().attrs.get(idx).get().Value();
let removed_raw_value = self.get().attrs.get(idx).root(&roots).Value();
vtable_for(node).before_remove_attr(local_name.clone(), removed_raw_value);
}
@ -528,11 +528,8 @@ impl Element {
} else {
name
};
abstract_self.get_attribute(Null, name)
.map(|s| {
let s = s.root(&roots);
s.deref().Value()
})
abstract_self.get_attribute(Null, name).root(&roots)
.map(|s| s.deref().Value())
}
// http://dom.spec.whatwg.org/#dom-element-getattributens
@ -541,11 +538,8 @@ impl Element {
local_name: DOMString) -> Option<DOMString> {
let roots = RootCollection::new();
let namespace = Namespace::from_str(null_str_as_empty_ref(&namespace));
abstract_self.get_attribute(namespace, local_name)
.map(|attr| {
let attr = attr.root(&roots);
attr.deref().Value()
})
abstract_self.get_attribute(namespace, local_name).root(&roots)
.map(|attr| attr.deref().Value())
}
// http://dom.spec.whatwg.org/#dom-element-setattribute
@ -747,9 +741,8 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
_ => (),
}
match self.get_attribute(Null, "id") {
match self.get_attribute(Null, "id").root(&roots) {
Some(attr) => {
let attr = attr.root(&roots);
let mut doc = document_from_node(self).root(&roots);
doc.register_named_element(self, attr.deref().Value());
}

View file

@ -11,8 +11,8 @@ use dom::bindings::codegen::InheritTypes::{CharacterDataCast, NodeBase, NodeDeri
use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, EventTargetCast};
use dom::bindings::codegen::BindingDeclarations::NodeBinding::NodeConstants;
use dom::bindings::js::{JS, JSRef, RootCollection, RootedReference, Unrooted, Root};
use dom::bindings::js::{OptionalAssignable, UnrootedPushable, OptionalRootable};
use dom::bindings::js::ResultRootable;
use dom::bindings::js::{OptionalAssignable, UnrootedPushable, OptionalRootedRootable};
use dom::bindings::js::{ResultRootable, OptionalRootable};
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::bindings::error::{ErrorResult, Fallible, NotFound, HierarchyRequest};
use dom::bindings::utils;
@ -479,27 +479,25 @@ impl<'a> NodeHelpers for JSRef<'a, Node> {
let child_node = child.get_mut();
assert!(child_node.parent_node.is_some());
match child_node.prev_sibling {
match child_node.prev_sibling.root(&roots) {
None => {
let next_sibling = child_node.next_sibling.as_ref().map(|next| next.root(&roots));
this_node.set_first_child(next_sibling.root_ref());
}
Some(ref mut prev_sibling) => {
let prev_sibling_node = prev_sibling.get_mut();
let next_sibling = child_node.next_sibling.as_ref().map(|next| next.root(&roots));
prev_sibling_node.set_next_sibling(next_sibling.root_ref());
prev_sibling.set_next_sibling(next_sibling.root_ref());
}
}
match child_node.next_sibling {
match child_node.next_sibling.root(&roots) {
None => {
let prev_sibling = child_node.prev_sibling.as_ref().map(|prev| prev.root(&roots));
this_node.set_last_child(prev_sibling.root_ref());
}
Some(ref mut next_sibling) => {
let next_sibling_node = next_sibling.get_mut();
let prev_sibling = child_node.prev_sibling.as_ref().map(|prev| prev.root(&roots));
next_sibling_node.set_prev_sibling(prev_sibling.root_ref());
next_sibling.set_prev_sibling(prev_sibling.root_ref());
}
}
@ -916,18 +914,18 @@ impl Node {
pub fn NodeName(&self, abstract_self: &JSRef<Node>) -> DOMString {
match self.type_id {
ElementNodeTypeId(..) => {
let elem: JS<Element> = ElementCast::to(&abstract_self.unrooted()).unwrap();
let elem: &JSRef<Element> = ElementCast::to_ref(abstract_self).unwrap();
elem.get().TagName()
}
TextNodeTypeId => ~"#text",
ProcessingInstructionNodeTypeId => {
let processing_instruction: JS<ProcessingInstruction> =
ProcessingInstructionCast::to(&abstract_self.unrooted()).unwrap();
let processing_instruction: &JSRef<ProcessingInstruction> =
ProcessingInstructionCast::to_ref(abstract_self).unwrap();
processing_instruction.get().Target()
}
CommentNodeTypeId => ~"#comment",
DoctypeNodeTypeId => {
let doctype: JS<DocumentType> = DocumentTypeCast::to(&abstract_self.unrooted()).unwrap();
let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(abstract_self).unwrap();
doctype.get().name.clone()
},
DocumentFragmentNodeTypeId => ~"#document-fragment",
@ -1016,7 +1014,7 @@ impl Node {
CommentNodeTypeId |
TextNodeTypeId |
ProcessingInstructionNodeTypeId => {
let chardata: JS<CharacterData> = CharacterDataCast::to(&abstract_self.unrooted()).unwrap();
let chardata: &JSRef<CharacterData> = CharacterDataCast::to_ref(abstract_self).unwrap();
Some(chardata.get().Data())
}
_ => {
@ -1091,7 +1089,7 @@ impl Node {
ProcessingInstructionNodeTypeId => {
self.wait_until_safe_to_modify_dom();
let mut characterdata: JS<CharacterData> = CharacterDataCast::to(&abstract_self.unrooted()).unwrap();
let characterdata: &mut JSRef<CharacterData> = CharacterDataCast::to_mut_ref(abstract_self).unwrap();
characterdata.get_mut().data = value.clone();
// Notify the document that the content of this node is different
@ -1482,13 +1480,12 @@ impl Node {
// FIXME: https://github.com/mozilla/servo/issues/1737
copy_elem.namespace = node_elem.namespace.clone();
let window = document.get().window.root(&roots);
for attr in node_elem.attrs.iter() {
let attr = attr.get();
for attr in node_elem.attrs.iter().map(|attr| attr.root(&roots)) {
copy_elem.attrs.push_unrooted(
Attr::new(&*window,
attr.local_name.clone(), attr.value.clone(),
attr.name.clone(), attr.namespace.clone(),
attr.prefix.clone(), &copy_elem_alias));
attr.deref().local_name.clone(), attr.deref().value.clone(),
attr.deref().name.clone(), attr.deref().namespace.clone(),
attr.deref().prefix.clone(), &copy_elem_alias));
}
},
_ => ()
@ -1703,40 +1700,41 @@ impl Node {
// http://dom.spec.whatwg.org/#dom-node-isequalnode
pub fn IsEqualNode(&self, abstract_self: &JSRef<Node>, maybe_node: Option<JSRef<Node>>) -> bool {
fn is_equal_doctype(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
let doctype: JS<DocumentType> = DocumentTypeCast::to(&node.unrooted()).unwrap();
let other_doctype: JS<DocumentType> = DocumentTypeCast::to(&other.unrooted()).unwrap();
let doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(node).unwrap();
let other_doctype: &JSRef<DocumentType> = DocumentTypeCast::to_ref(other).unwrap();
(doctype.get().name == other_doctype.get().name) &&
(doctype.get().public_id == other_doctype.get().public_id) &&
(doctype.get().system_id == other_doctype.get().system_id)
}
fn is_equal_element(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
let element: JS<Element> = ElementCast::to(&node.unrooted()).unwrap();
let other_element: JS<Element> = ElementCast::to(&other.unrooted()).unwrap();
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
// FIXME: namespace prefix
(element.get().namespace == other_element.get().namespace) &&
(element.get().local_name == other_element.get().local_name) &&
(element.get().attrs.len() == other_element.get().attrs.len())
}
fn is_equal_processinginstruction(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
let pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(&node.unrooted()).unwrap();
let other_pi: JS<ProcessingInstruction> = ProcessingInstructionCast::to(&other.unrooted()).unwrap();
let pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(node).unwrap();
let other_pi: &JSRef<ProcessingInstruction> = ProcessingInstructionCast::to_ref(other).unwrap();
(pi.get().target == other_pi.get().target) &&
(pi.get().characterdata.data == other_pi.get().characterdata.data)
}
fn is_equal_characterdata(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
let characterdata: JS<CharacterData> = CharacterDataCast::to(&node.unrooted()).unwrap();
let other_characterdata: JS<CharacterData> = CharacterDataCast::to(&other.unrooted()).unwrap();
let characterdata: &JSRef<CharacterData> = CharacterDataCast::to_ref(node).unwrap();
let other_characterdata: &JSRef<CharacterData> = CharacterDataCast::to_ref(other).unwrap();
characterdata.get().data == other_characterdata.get().data
}
fn is_equal_element_attrs(node: &JSRef<Node>, other: &JSRef<Node>) -> bool {
let element: JS<Element> = ElementCast::to(&node.unrooted()).unwrap();
let other_element: JS<Element> = ElementCast::to(&other.unrooted()).unwrap();
let roots = RootCollection::new();
let element: &JSRef<Element> = ElementCast::to_ref(node).unwrap();
let other_element: &JSRef<Element> = ElementCast::to_ref(other).unwrap();
assert!(element.get().attrs.len() == other_element.get().attrs.len());
element.get().attrs.iter().all(|attr| {
other_element.get().attrs.iter().any(|other_attr| {
(attr.get().namespace == other_attr.get().namespace) &&
(attr.get().local_name == other_attr.get().local_name) &&
(attr.get().value == other_attr.get().value)
element.get().attrs.iter().map(|attr| attr.root(&roots)).all(|attr| {
other_element.get().attrs.iter().map(|attr| attr.root(&roots)).any(|other_attr| {
(attr.namespace == other_attr.namespace) &&
(attr.local_name == other_attr.local_name) &&
(attr.value == other_attr.value)
})
})
}

View file

@ -277,7 +277,7 @@ impl Page {
let roots = RootCollection::new();
let root = match *self.frame() {
None => return,
Some(ref frame) => frame.document.get().GetDocumentElement()
Some(ref frame) => frame.document.root(&roots).GetDocumentElement()
};
match root.root(&roots) {
None => {},
@ -359,7 +359,7 @@ impl Page {
let root = match *self.frame() {
None => return,
Some(ref frame) => {
frame.document.get().GetDocumentElement()
frame.document.root(&roots).GetDocumentElement()
}
};
@ -444,7 +444,7 @@ impl Page {
pub fn hit_test(&self, point: &Point2D<f32>) -> Option<UntrustedNodeAddress> {
let roots = RootCollection::new();
let frame = self.frame();
let document = frame.get_ref().document.clone();
let document = frame.get_ref().document.root(&roots);
let root = document.get().GetDocumentElement().root(&roots);
if root.is_none() {
return None;
@ -467,7 +467,7 @@ impl Page {
pub fn get_nodes_under_mouse(&self, point: &Point2D<f32>) -> Option<Vec<UntrustedNodeAddress>> {
let roots = RootCollection::new();
let frame = self.frame();
let document = frame.get_ref().document.clone();
let document = frame.get_ref().document.root(&roots);
let root = document.get().GetDocumentElement().root(&roots);
if root.is_none() {
return None;
@ -737,11 +737,13 @@ impl ScriptTask {
/// Handles a timer that fired.
fn handle_fire_timer_msg(&self, id: PipelineId, timer_id: TimerId) {
let roots = RootCollection::new();
let mut page_tree = self.page_tree.borrow_mut();
let page = page_tree.find(id).expect("ScriptTask: received fire timer msg for a
pipeline ID not associated with this script task. This is a bug.").page();
let frame = page.frame();
let mut window = frame.get_ref().window.clone();
let mut window = frame.get_ref().window.root(&roots);
let is_interval;
match window.get().active_timers.find(&timer_id) {