Make get() and set() on MutNullableHeap use the correct types.

get() must always return a rooted value, because we have no way of
ensuring the value won't be invalidated. set() takes an &T because it's
convenient; there isn't any need to expose JS<T>.
This commit is contained in:
Eli Friedman 2015-10-14 17:48:28 -07:00
parent 7a08b29201
commit 57584e74c6
11 changed files with 68 additions and 67 deletions

View file

@ -315,7 +315,7 @@ impl Attr {
}
(old, new) => assert!(old == new)
}
self.owner.set(owner.map(JS::from_ref))
self.owner.set(owner);
}
pub fn owner(&self) -> Option<Root<Element>> {

View file

@ -254,16 +254,6 @@ impl<T: HeapGCValue> MutNullableHeap<T> {
ptr: UnsafeCell::new(initial)
}
}
/// Set this `MutNullableHeap` to the given value.
pub fn set(&self, val: Option<T>) {
unsafe { *self.ptr.get() = val; }
}
/// Retrieve a copy of the current optional inner value.
pub fn get(&self) -> Option<T> {
unsafe { ptr::read(self.ptr.get()) }
}
}
impl<T: Reflectable> MutNullableHeap<JS<T>> {
@ -273,10 +263,10 @@ impl<T: Reflectable> MutNullableHeap<JS<T>> {
where F: FnOnce() -> Root<T>
{
match self.get() {
Some(inner) => Root::from_rooted(inner),
Some(inner) => inner,
None => {
let inner = cb();
self.set(Some(JS::from_rooted(&inner)));
self.set(Some(&inner));
inner
},
}
@ -289,9 +279,22 @@ impl<T: Reflectable> MutNullableHeap<JS<T>> {
}
/// Get a rooted value out of this object
// FIXME(#6684)
pub fn get(&self) -> Option<Root<T>> {
unsafe {
ptr::read(self.ptr.get()).map(|o| o.root())
}
}
/// Get a rooted value out of this object
pub fn get_rooted(&self) -> Option<Root<T>> {
self.get().map(|o| o.root())
self.get()
}
/// Set this `MutNullableHeap` to the given value.
pub fn set(&self, val: Option<&T>) {
unsafe {
*self.ptr.get() = val.map(|p| JS::from_ref(p));
}
}
}

View file

@ -297,7 +297,7 @@ impl Document {
.filter_map(HTMLBaseElementCast::to_root)
.filter(|element| ElementCast::from_ref(&**element).has_attribute(&atom!("href")))
.next();
self.base_element.set(base.map(|element| JS::from_ref(&*element)));
self.base_element.set(base.as_ref().map(Root::r));
}
pub fn quirks_mode(&self) -> QuirksMode {
@ -506,7 +506,7 @@ impl Document {
/// Request that the given element receive focus once the current transaction is complete.
pub fn request_focus(&self, elem: &Element) {
if elem.is_focusable_area() {
self.possibly_focused.set(Some(JS::from_ref(elem)))
self.possibly_focused.set(Some(elem))
}
}
@ -520,7 +520,7 @@ impl Document {
node.set_focus_state(false);
}
self.focused.set(self.possibly_focused.get());
self.focused.set(self.possibly_focused.get().r());
if let Some(ref elem) = self.focused.get_rooted() {
let node = NodeCast::from_ref(elem.r());
@ -852,7 +852,7 @@ impl Document {
}
pub fn set_current_script(&self, script: Option<&HTMLScriptElement>) {
self.current_script.set(script.map(JS::from_ref));
self.current_script.set(script);
}
pub fn trigger_mozbrowser_event(&self, event: MozBrowserEvent) {
@ -959,7 +959,7 @@ impl Document {
}
pub fn set_current_parser(&self, script: Option<&ServoHTMLParser>) {
self.current_parser.set(script.map(JS::from_ref));
self.current_parser.set(script);
}
pub fn get_current_parser(&self) -> Option<Root<ServoHTMLParser>> {
@ -1119,8 +1119,7 @@ impl Document {
let new_doc = Document::new(
&*self.window(), None, doctype, None, None,
DocumentSource::NotFromParser, DocumentLoader::new(&self.loader()));
new_doc.appropriate_template_contents_owner_document.set(
Some(JS::from_ref(&*new_doc)));
new_doc.appropriate_template_contents_owner_document.set(Some(&new_doc));
new_doc
})
}

View file

@ -106,12 +106,12 @@ impl Event {
#[inline]
pub fn set_current_target(&self, val: &EventTarget) {
self.current_target.set(Some(JS::from_ref(val)));
self.current_target.set(Some(val));
}
#[inline]
pub fn set_target(&self, val: &EventTarget) {
self.target.set(Some(JS::from_ref(val)));
self.target.set(Some(val));
}
#[inline]

View file

@ -116,7 +116,7 @@ impl FileReader {
let global = fr.global.root();
let exception = DOMException::new(global.r(), error);
fr.error.set(Some(JS::from_rooted(&exception)));
fr.error.set(Some(&exception));
fr.dispatch_progress_event("error".to_owned(), 0, None);
return_on_abort!();
@ -292,7 +292,7 @@ impl FileReaderMethods for FileReader {
let global = self.global.root();
let exception = DOMException::new(global.r(), DOMErrorName::AbortError);
self.error.set(Some(JS::from_rooted(&exception)));
self.error.set(Some(&exception));
self.terminate_ongoing_reading();
// Steps 5 & 6
@ -346,7 +346,7 @@ impl FileReader {
if blob.IsClosed() {
let global = self.global.root();
let exception = DOMException::new(global.r(), DOMErrorName::InvalidStateError);
self.error.set(Some(JS::from_rooted(&exception)));
self.error.set(Some(&exception));
self.dispatch_progress_event("error".to_owned(), 0, None);
return Ok(());

View file

@ -205,6 +205,6 @@ impl MouseEventMethods for MouseEvent {
self.shift_key.set(shiftKeyArg);
self.meta_key.set(metaKeyArg);
self.button.set(buttonArg);
self.related_target.set(relatedTargetArg.map(JS::from_ref));
self.related_target.set(relatedTargetArg);
}
}

View file

@ -271,32 +271,32 @@ impl Node {
match prev_sibling {
None => {
assert!(Some(*before) == self.first_child.get_rooted().r());
self.first_child.set(Some(JS::from_ref(new_child)));
self.first_child.set(Some(new_child));
},
Some(ref prev_sibling) => {
prev_sibling.next_sibling.set(Some(JS::from_ref(new_child)));
new_child.prev_sibling.set(Some(JS::from_ref(prev_sibling.r())));
prev_sibling.next_sibling.set(Some(new_child));
new_child.prev_sibling.set(Some(prev_sibling.r()));
},
}
before.prev_sibling.set(Some(JS::from_ref(new_child)));
new_child.next_sibling.set(Some(JS::from_ref(before)));
before.prev_sibling.set(Some(new_child));
new_child.next_sibling.set(Some(before));
},
None => {
let last_child = self.GetLastChild();
match last_child {
None => self.first_child.set(Some(JS::from_ref(new_child))),
None => self.first_child.set(Some(new_child)),
Some(ref last_child) => {
assert!(last_child.next_sibling.get().is_none());
last_child.r().next_sibling.set(Some(JS::from_ref(new_child)));
new_child.prev_sibling.set(Some(JS::from_rooted(&last_child)));
last_child.r().next_sibling.set(Some(new_child));
new_child.prev_sibling.set(Some(&last_child));
}
}
self.last_child.set(Some(JS::from_ref(new_child)));
self.last_child.set(Some(new_child));
},
}
new_child.parent_node.set(Some(JS::from_ref(self)));
new_child.parent_node.set(Some(self));
let parent_in_doc = self.is_in_doc();
for node in new_child.traverse_preorder() {
@ -315,19 +315,19 @@ impl Node {
let prev_sibling = child.GetPreviousSibling();
match prev_sibling {
None => {
self.first_child.set(child.next_sibling.get());
self.first_child.set(child.next_sibling.get().r());
}
Some(ref prev_sibling) => {
prev_sibling.next_sibling.set(child.next_sibling.get());
prev_sibling.next_sibling.set(child.next_sibling.get().r());
}
}
let next_sibling = child.GetNextSibling();
match next_sibling {
None => {
self.last_child.set(child.prev_sibling.get());
self.last_child.set(child.prev_sibling.get().r());
}
Some(ref next_sibling) => {
next_sibling.prev_sibling.set(child.prev_sibling.get());
next_sibling.prev_sibling.set(child.prev_sibling.get().r());
}
}
@ -591,7 +591,7 @@ impl Node {
match self.parent_node.get() {
None => return,
Some(parent) => parent,
}.root();
};
for sibling in parent.r().children() {
sibling.r().set_has_dirty_siblings(true);
@ -660,7 +660,7 @@ impl Node {
pub fn is_parent_of(&self, child: &Node) -> bool {
match child.parent_node.get() {
Some(ref parent) => parent.root().r() == self,
Some(ref parent) => parent.r() == self,
None => false,
}
}
@ -689,7 +689,7 @@ impl Node {
// Step 2.
let parent = match parent.get() {
None => return Ok(()),
Some(ref parent) => parent.root(),
Some(parent) => parent,
};
// Step 3.
@ -702,7 +702,7 @@ impl Node {
let viable_previous_sibling = match viable_previous_sibling {
Some(ref viable_previous_sibling) => viable_previous_sibling.next_sibling.get(),
None => parent.first_child.get(),
}.map(|s| s.root());
};
// Step 6.
try!(Node::pre_insert(&node, &parent, viable_previous_sibling.r()));
@ -718,7 +718,7 @@ impl Node {
// Step 2.
let parent = match parent.get() {
None => return Ok(()),
Some(ref parent) => parent.root(),
Some(parent) => parent,
};
// Step 3.
@ -745,7 +745,7 @@ impl Node {
let doc = self.owner_doc();
let node = try!(doc.r().node_from_nodes_and_strings(nodes));
// Step 3.
parent_node.root().r().ReplaceChild(node.r(), self).map(|_| ())
parent_node.r().ReplaceChild(node.r(), self).map(|_| ())
},
}
}
@ -823,11 +823,11 @@ impl Node {
}
pub fn owner_doc(&self) -> Root<Document> {
self.owner_doc.get().unwrap().root()
self.owner_doc.get().unwrap()
}
pub fn set_owner_doc(&self, document: &Document) {
self.owner_doc.set(Some(JS::from_ref(document)));
self.owner_doc.set(Some(document));
}
pub fn is_in_html_doc(&self) -> bool {

View file

@ -127,14 +127,14 @@ impl ChildrenList {
let last_index = self.last_index.get();
if index == last_index {
// Item is last visited child, no need to update last visited.
return Some(self.last_visited.get().unwrap().root());
return Some(self.last_visited.get().unwrap());
}
let last_visited = if index - 1u32 == last_index {
// Item is last visited's next sibling.
self.last_visited.get().unwrap().root().GetNextSibling().unwrap()
self.last_visited.get().unwrap().GetNextSibling().unwrap()
} else if last_index > 0 && index == last_index - 1u32 {
// Item is last visited's previous sibling.
self.last_visited.get().unwrap().root().GetPreviousSibling().unwrap()
self.last_visited.get().unwrap().GetPreviousSibling().unwrap()
} else if index > last_index {
if index == len - 1u32 {
// Item is parent's last child, not worth updating last visited.
@ -142,7 +142,7 @@ impl ChildrenList {
}
if index <= last_index + (len - last_index) / 2u32 {
// Item is closer to the last visited child and follows it.
self.last_visited.get().unwrap().root()
self.last_visited.get().unwrap()
.inclusively_following_siblings()
.nth((index - last_index) as usize).unwrap()
} else {
@ -154,7 +154,7 @@ impl ChildrenList {
}
} else if index >= last_index / 2u32 {
// Item is closer to the last visited child and precedes it.
self.last_visited.get().unwrap().root()
self.last_visited.get().unwrap()
.inclusively_preceding_siblings()
.nth((last_index - index) as usize).unwrap()
} else {
@ -165,7 +165,7 @@ impl ChildrenList {
.nth(index as usize)
.unwrap()
};
self.last_visited.set(Some(JS::from_rooted(&last_visited)));
self.last_visited.set(Some(last_visited.r()));
self.last_index.set(index);
Some(last_visited)
}
@ -178,7 +178,7 @@ impl ChildrenList {
}
let index = list.last_index.get();
if index < len {
list.last_visited.set(Some(JS::from_ref(added[index as usize])));
list.last_visited.set(Some(added[index as usize]));
} else if index / 2u32 >= len {
// If last index is twice as large as the number of added nodes,
// updating only it means that less nodes will be traversed if
@ -187,7 +187,7 @@ impl ChildrenList {
} else {
// If last index is not twice as large but still larger,
// it's better to update it to the number of added nodes.
list.last_visited.set(Some(JS::from_ref(next)));
list.last_visited.set(Some(next));
list.last_index.set(len);
}
}
@ -198,7 +198,7 @@ impl ChildrenList {
added: &[&Node],
next: Option<&Node>) {
let index = list.last_index.get();
if removed == &*list.last_visited.get().unwrap().root() {
if removed == &*list.last_visited.get().unwrap() {
let visited = match (prev, added, next) {
(None, _, None) => {
// Such cases where parent had only one child should
@ -213,7 +213,7 @@ impl ChildrenList {
prev
},
};
list.last_visited.set(Some(JS::from_ref(visited)));
list.last_visited.set(Some(visited));
} else if added.len() != 1 {
// The replaced child isn't the last visited one, and there are
// 0 or more than 1 nodes to replace it. Special care must be
@ -250,13 +250,13 @@ impl ChildrenList {
self.last_visited.set(None);
self.last_index.set(0u32);
} else if index < len as u32 {
self.last_visited.set(Some(JS::from_ref(added[index as usize])));
self.last_visited.set(Some(added[index as usize]));
} else {
// Setting last visited to parent's last child serves no purpose,
// so the middle is arbitrarily chosen here in case the caller
// wants random access.
let middle = len / 2;
self.last_visited.set(Some(JS::from_ref(added[middle])));
self.last_visited.set(Some(added[middle]));
self.last_index.set(middle as u32);
}
},
@ -264,8 +264,7 @@ impl ChildrenList {
}
fn reset(&self) {
self.last_visited.set(
self.node.root().GetFirstChild().map(|node| JS::from_rooted(&node)));
self.last_visited.set(self.node.root().GetFirstChild().as_ref().map(Root::r));
self.last_index.set(0u32);
}
}

View file

@ -92,7 +92,7 @@ impl UIEventMethods for UIEvent {
}
event.InitEvent(type_, can_bubble, cancelable);
self.view.set(view.map(JS::from_ref));
self.view.set(view);
self.detail.set(detail);
}
}

View file

@ -86,7 +86,7 @@ impl WebGLProgram {
return Err(WebGLError::InvalidOperation);
}
shader_slot.set(Some(JS::from_ref(shader)));
shader_slot.set(Some(shader));
self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::AttachShader(self.id, shader.id()))).unwrap();

View file

@ -360,7 +360,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
if let Some(texture) = texture {
match texture.bind(target) {
Ok(_) => slot.set(Some(JS::from_ref(texture))),
Ok(_) => slot.set(Some(texture)),
Err(err) => return self.webgl_error(err),
}
} else {