Upgrade to SM 39

This commit is contained in:
Michael Wu 2015-04-06 19:27:56 -04:00
parent a256f39796
commit 675267b782
205 changed files with 6546 additions and 5340 deletions

View file

@ -521,6 +521,7 @@ pub struct LayoutElement<'le> {
impl<'le> LayoutElement<'le> { impl<'le> LayoutElement<'le> {
pub fn style_attribute(&self) -> &'le Option<PropertyDeclarationBlock> { pub fn style_attribute(&self) -> &'le Option<PropertyDeclarationBlock> {
use script::dom::element::ElementHelpers;
let style: &Option<PropertyDeclarationBlock> = unsafe { let style: &Option<PropertyDeclarationBlock> = unsafe {
&*self.element.style_attribute().borrow_for_layout() &*self.element.style_attribute().borrow_for_layout()
}; };
@ -536,6 +537,7 @@ impl<'le> TElement<'le> for LayoutElement<'le> {
#[inline] #[inline]
fn get_namespace(self) -> &'le Namespace { fn get_namespace(self) -> &'le Namespace {
use script::dom::element::ElementHelpers;
self.element.namespace() self.element.namespace()
} }

View file

@ -34,8 +34,7 @@ pub struct UnrootedPass;
// TODO (#3874, sort of): unwrap other types like Vec/Option/HashMap/etc // TODO (#3874, sort of): unwrap other types like Vec/Option/HashMap/etc
fn lint_unrooted_ty(cx: &Context, ty: &ast::Ty, warning: &str) { fn lint_unrooted_ty(cx: &Context, ty: &ast::Ty, warning: &str) {
match ty.node { match ty.node {
ast::TyVec(ref t) | ast::TyFixedLengthVec(ref t, _) | ast::TyVec(ref t) | ast::TyFixedLengthVec(ref t, _) =>
ast::TyPtr(ast::MutTy { ty: ref t, ..}) | ast::TyRptr(_, ast::MutTy { ty: ref t, ..}) =>
lint_unrooted_ty(cx, &**t, warning), lint_unrooted_ty(cx, &**t, warning),
ast::TyPath(..) => { ast::TyPath(..) => {
match cx.tcx.def_map.borrow()[&ty.id] { match cx.tcx.def_map.borrow()[&ty.id] {
@ -47,7 +46,7 @@ fn lint_unrooted_ty(cx: &Context, ty: &ast::Ty, warning: &str) {
_ => (), _ => (),
} }
} }
_ => (), _ => (),
}; };
} }

View file

@ -25,6 +25,9 @@ pub fn expand_reflector(cx: &mut ExtCtxt, span: Span, _: &MetaItem, annotatable:
fn reflector<'a>(&'a self) -> &'a ::dom::bindings::utils::Reflector { fn reflector<'a>(&'a self) -> &'a ::dom::bindings::utils::Reflector {
&self.$field_name &self.$field_name
} }
fn init_reflector(&mut self, obj: *mut ::js::jsapi::JSObject) {
self.$field_name.set_jsobject(obj);
}
} }
); );
impl_item.map(|it| push(Annotatable::Item(it))) impl_item.map(|it| push(Annotatable::Item(it)))
@ -37,6 +40,9 @@ pub fn expand_reflector(cx: &mut ExtCtxt, span: Span, _: &MetaItem, annotatable:
fn reflector<'a>(&'a self) -> &'a ::dom::bindings::utils::Reflector { fn reflector<'a>(&'a self) -> &'a ::dom::bindings::utils::Reflector {
self.$field_name.reflector() self.$field_name.reflector()
} }
fn init_reflector(&mut self, obj: *mut ::js::jsapi::JSObject) {
self.$field_name.init_reflector(obj);
}
} }
); );
impl_item.map(|it| push(Annotatable::Item(it))) impl_item.map(|it| push(Annotatable::Item(it)))

View file

@ -6,18 +6,19 @@ use devtools_traits::{CachedConsoleMessage, CachedConsoleMessageTypes, PAGE_ERRO
use devtools_traits::{EvaluateJSReply, NodeInfo, Modification, TimelineMarker, TimelineMarkerType}; use devtools_traits::{EvaluateJSReply, NodeInfo, Modification, TimelineMarker, TimelineMarkerType};
use dom::bindings::conversions::FromJSValConvertible; use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior; use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::js::{JSRef, OptionalRootable, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast}; use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::DOMRectBinding::{DOMRectMethods}; use dom::bindings::codegen::Bindings::DOMRectBinding::{DOMRectMethods};
use dom::bindings::codegen::Bindings::ElementBinding::{ElementMethods}; use dom::bindings::codegen::Bindings::ElementBinding::{ElementMethods};
use dom::node::{Node, NodeHelpers}; use dom::node::{Node, NodeHelpers};
use dom::window::{WindowHelpers, ScriptHelpers}; use dom::window::{WindowHelpers, ScriptHelpers};
use dom::element::Element;
use dom::document::DocumentHelpers; use dom::document::DocumentHelpers;
use page::{IterablePage, Page}; use page::{IterablePage, Page};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use script_task::{get_page, ScriptTask}; use script_task::{get_page, ScriptTask};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use std::rc::Rc; use std::rc::Rc;
@ -25,53 +26,54 @@ use std::rc::Rc;
pub fn handle_evaluate_js(page: &Rc<Page>, pipeline: PipelineId, eval: String, reply: Sender<EvaluateJSReply>){ pub fn handle_evaluate_js(page: &Rc<Page>, pipeline: PipelineId, eval: String, reply: Sender<EvaluateJSReply>){
let page = get_page(&*page, pipeline); let page = get_page(&*page, pipeline);
let window = page.window().root(); let window = page.window();
let cx = window.r().get_cx(); let cx = window.r().get_cx();
let rval = window.r().evaluate_js_on_global_with_result(&eval); let mut rval = RootedValue::new(cx, UndefinedValue());
window.r().evaluate_js_on_global_with_result(&eval, rval.handle_mut());
reply.send(if rval.is_undefined() { reply.send(if rval.ptr.is_undefined() {
EvaluateJSReply::VoidValue EvaluateJSReply::VoidValue
} else if rval.is_boolean() { } else if rval.ptr.is_boolean() {
EvaluateJSReply::BooleanValue(rval.to_boolean()) EvaluateJSReply::BooleanValue(rval.ptr.to_boolean())
} else if rval.is_double() { } else if rval.ptr.is_double() {
EvaluateJSReply::NumberValue(FromJSValConvertible::from_jsval(cx, rval, ()).unwrap()) EvaluateJSReply::NumberValue(FromJSValConvertible::from_jsval(cx, rval.handle(), ()).unwrap())
} else if rval.is_string() { } else if rval.ptr.is_string() {
//FIXME: use jsstring_to_str when jsval grows to_jsstring //FIXME: use jsstring_to_str when jsval grows to_jsstring
EvaluateJSReply::StringValue( EvaluateJSReply::StringValue(
FromJSValConvertible::from_jsval(cx, rval, StringificationBehavior::Default).unwrap()) FromJSValConvertible::from_jsval(cx, rval.handle(), StringificationBehavior::Default).unwrap())
} else if rval.is_null() { } else if rval.ptr.is_null() {
EvaluateJSReply::NullValue EvaluateJSReply::NullValue
} else { } else {
//FIXME: jsvals don't have an is_int32/is_number yet //FIXME: jsvals don't have an is_int32/is_number yet
assert!(rval.is_object()); assert!(rval.ptr.is_object());
panic!("object values unimplemented") panic!("object values unimplemented")
}).unwrap(); }).unwrap();
} }
pub fn handle_get_root_node(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) { pub fn handle_get_root_node(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
let page = get_page(&*page, pipeline); let page = get_page(&*page, pipeline);
let document = page.document().root(); let document = page.document();
let node: JSRef<Node> = NodeCast::from_ref(document.r()); let node = NodeCast::from_ref(document.r());
reply.send(node.summarize()).unwrap(); reply.send(node.summarize()).unwrap();
} }
pub fn handle_get_document_element(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) { pub fn handle_get_document_element(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
let page = get_page(&*page, pipeline); let page = get_page(&*page, pipeline);
let document = page.document().root(); let document = page.document();
let document_element = document.r().GetDocumentElement().root().unwrap(); let document_element = document.r().GetDocumentElement().unwrap();
let node: JSRef<Node> = NodeCast::from_ref(document_element.r()); let node = NodeCast::from_ref(document_element.r());
reply.send(node.summarize()).unwrap(); reply.send(node.summarize()).unwrap();
} }
fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String) -> Temporary<Node> { fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String) -> Root<Node> {
let page = get_page(&*page, pipeline); let page = get_page(&*page, pipeline);
let document = page.document().root(); let document = page.document();
let node: JSRef<Node> = NodeCast::from_ref(document.r()); let node = NodeCast::from_ref(document.r());
for candidate in node.traverse_preorder() { for candidate in node.traverse_preorder() {
if candidate.root().r().get_unique_id() == node_id { if candidate.r().get_unique_id() == node_id {
return candidate; return candidate;
} }
} }
@ -80,18 +82,17 @@ fn find_node_by_unique_id(page: &Rc<Page>, pipeline: PipelineId, node_id: String
} }
pub fn handle_get_children(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<Vec<NodeInfo>>) { pub fn handle_get_children(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<Vec<NodeInfo>>) {
let parent = find_node_by_unique_id(&*page, pipeline, node_id).root(); let parent = find_node_by_unique_id(&*page, pipeline, node_id);
let children = parent.r().children().map(|child| { let children = parent.r().children().map(|child| {
let child = child.root();
child.r().summarize() child.r().summarize()
}).collect(); }).collect();
reply.send(children).unwrap(); reply.send(children).unwrap();
} }
pub fn handle_get_layout(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<(f32, f32)>) { pub fn handle_get_layout(page: &Rc<Page>, pipeline: PipelineId, node_id: String, reply: Sender<(f32, f32)>) {
let node = find_node_by_unique_id(&*page, pipeline, node_id).root(); let node = find_node_by_unique_id(&*page, pipeline, node_id);
let elem: JSRef<Element> = ElementCast::to_ref(node.r()).expect("should be getting layout of element"); let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
let rect = elem.GetBoundingClientRect().root(); let rect = elem.GetBoundingClientRect();
let width = *rect.r().Width(); let width = *rect.r().Width();
let height = *rect.r().Height(); let height = *rect.r().Height();
reply.send((width, height)).unwrap(); reply.send((width, height)).unwrap();
@ -141,8 +142,8 @@ pub fn handle_modify_attribute(page: &Rc<Page>,
pipeline: PipelineId, pipeline: PipelineId,
node_id: String, node_id: String,
modifications: Vec<Modification>) { modifications: Vec<Modification>) {
let node = find_node_by_unique_id(&*page, pipeline, node_id).root(); let node = find_node_by_unique_id(&*page, pipeline, node_id);
let elem: JSRef<Element> = ElementCast::to_ref(node.r()).expect("should be getting layout of element"); let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
for modification in modifications.iter(){ for modification in modifications.iter(){
match modification.newValue { match modification.newValue {
@ -156,7 +157,7 @@ pub fn handle_modify_attribute(page: &Rc<Page>,
pub fn handle_wants_live_notifications(page: &Rc<Page>, pipeline_id: PipelineId, send_notifications: bool) { pub fn handle_wants_live_notifications(page: &Rc<Page>, pipeline_id: PipelineId, send_notifications: bool) {
let page = get_page(&*page, pipeline_id); let page = get_page(&*page, pipeline_id);
let window = page.window().root(); let window = page.window();
window.r().set_devtools_wants_updates(send_notifications); window.r().set_devtools_wants_updates(send_notifications);
} }
@ -167,7 +168,7 @@ pub fn handle_set_timeline_markers(page: &Rc<Page>,
for marker_type in &marker_types { for marker_type in &marker_types {
match *marker_type { match *marker_type {
TimelineMarkerType::Reflow => { TimelineMarkerType::Reflow => {
let window = page.window().root(); let window = page.window();
window.r().set_devtools_timeline_marker(TimelineMarkerType::Reflow, reply.clone()); window.r().set_devtools_timeline_marker(TimelineMarkerType::Reflow, reply.clone());
} }
TimelineMarkerType::DOMEvent => { TimelineMarkerType::DOMEvent => {
@ -180,7 +181,7 @@ pub fn handle_set_timeline_markers(page: &Rc<Page>,
pub fn handle_drop_timeline_markers(page: &Rc<Page>, pub fn handle_drop_timeline_markers(page: &Rc<Page>,
script_task: &ScriptTask, script_task: &ScriptTask,
marker_types: Vec<TimelineMarkerType>) { marker_types: Vec<TimelineMarkerType>) {
let window = page.window().root(); let window = page.window();
for marker_type in &marker_types { for marker_type in &marker_types {
match *marker_type { match *marker_type {
TimelineMarkerType::Reflow => { TimelineMarkerType::Reflow => {
@ -195,6 +196,6 @@ pub fn handle_drop_timeline_markers(page: &Rc<Page>,
pub fn handle_request_animation_frame(page: &Rc<Page>, id: PipelineId, callback: Box<Fn(f64, )>) { pub fn handle_request_animation_frame(page: &Rc<Page>, id: PipelineId, callback: Box<Fn(f64, )>) {
let page = page.find(id).expect("There is no such page"); let page = page.find(id).expect("There is no such page");
let doc = page.document().root(); let doc = page.document();
doc.r().request_animation_frame(callback); doc.r().request_animation_frame(callback);
} }

View file

@ -4,7 +4,6 @@
use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast}; use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast};
use dom::bindings::js::{JSRef, Temporary, OptionalRootable, Rootable};
use dom::element::{Element, ActivationElementHelpers}; use dom::element::{Element, ActivationElementHelpers};
use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable}; use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
@ -15,7 +14,7 @@ use std::borrow::ToOwned;
/// Trait for elements with defined activation behavior /// Trait for elements with defined activation behavior
pub trait Activatable { pub trait Activatable {
fn as_element(&self) -> Temporary<Element>; fn as_element<'a>(&'a self) -> &'a Element;
// Is this particular instance of the element activatable? // Is this particular instance of the element activatable?
fn is_instance_activatable(&self) -> bool; fn is_instance_activatable(&self) -> bool;
@ -27,32 +26,32 @@ pub trait Activatable {
fn canceled_activation(&self); fn canceled_activation(&self);
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps // https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
fn activation_behavior(&self, event: JSRef<Event>, target: JSRef<EventTarget>); fn activation_behavior(&self, event: &Event, target: &EventTarget);
// https://html.spec.whatwg.org/multipage/#implicit-submission // https://html.spec.whatwg.org/multipage/#implicit-submission
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool); fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool);
// https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps // https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps
fn synthetic_click_activation(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) { fn synthetic_click_activation(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) {
let element = self.as_element().root(); let element = self.as_element();
// Step 1 // Step 1
if element.r().click_in_progress() { if element.click_in_progress() {
return; return;
} }
// Step 2 // Step 2
element.r().set_click_in_progress(true); element.set_click_in_progress(true);
// Step 3 // Step 3
self.pre_click_activation(); self.pre_click_activation();
// Step 4 // Step 4
// https://html.spec.whatwg.org/multipage/#fire-a-synthetic-mouse-event // https://html.spec.whatwg.org/multipage/#fire-a-synthetic-mouse-event
let win = window_from_node(element.r()).root(); let win = window_from_node(element);
let target: JSRef<EventTarget> = EventTargetCast::from_ref(element.r()); let target = EventTargetCast::from_ref(element);
let mouse = MouseEvent::new(win.r(), "click".to_owned(), let mouse = MouseEvent::new(win.r(), "click".to_owned(),
EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, Some(win.r()), 1, EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, Some(win.r()), 1,
0, 0, 0, 0, ctrlKey, shiftKey, altKey, metaKey, 0, 0, 0, 0, ctrlKey, shiftKey, altKey, metaKey,
0, None).root(); 0, None);
let event: JSRef<Event> = EventCast::from_ref(mouse.r()); let event = EventCast::from_ref(mouse.r());
event.fire(target); event.fire(target);
// Step 5 // Step 5
@ -64,6 +63,6 @@ pub trait Activatable {
} }
// Step 6 // Step 6
element.r().set_click_in_progress(false); element.set_click_in_progress(false);
} }
} }

View file

@ -6,11 +6,10 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods}; use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods};
use dom::bindings::codegen::InheritTypes::NodeCast; use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Temporary}; use dom::bindings::js::{JS, MutNullableHeap};
use dom::bindings::js::{OptionalRootable, Rootable, RootedReference}; use dom::bindings::js::{Root, RootedReference};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers}; use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window; use dom::window::Window;
use dom::virtualmethods::vtable_for; use dom::virtualmethods::vtable_for;
@ -125,7 +124,7 @@ pub struct Attr {
impl Attr { impl Attr {
fn new_inherited(local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace, fn new_inherited(local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace,
prefix: Option<Atom>, owner: Option<JSRef<Element>>) -> Attr { prefix: Option<Atom>, owner: Option<&Element>) -> Attr {
Attr { Attr {
reflector_: Reflector::new(), reflector_: Reflector::new(),
local_name: local_name, local_name: local_name,
@ -133,13 +132,13 @@ impl Attr {
name: name, name: name,
namespace: namespace, namespace: namespace,
prefix: prefix, prefix: prefix,
owner: MutNullableHeap::new(owner.map(JS::from_rooted)), owner: MutNullableHeap::new(owner.map(JS::from_ref)),
} }
} }
pub fn new(window: JSRef<Window>, local_name: Atom, value: AttrValue, pub fn new(window: &Window, local_name: Atom, value: AttrValue,
name: Atom, namespace: Namespace, name: Atom, namespace: Namespace,
prefix: Option<Atom>, owner: Option<JSRef<Element>>) -> Temporary<Attr> { prefix: Option<Atom>, owner: Option<&Element>) -> Root<Attr> {
reflect_dom_object( reflect_dom_object(
box Attr::new_inherited(local_name, value, name, namespace, prefix, owner), box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
GlobalRef::Window(window), GlobalRef::Window(window),
@ -162,7 +161,7 @@ impl Attr {
} }
} }
impl<'a> AttrMethods for JSRef<'a, Attr> { impl<'a> AttrMethods for &'a Attr {
// https://dom.spec.whatwg.org/#dom-attr-localname // https://dom.spec.whatwg.org/#dom-attr-localname
fn LocalName(self) -> DOMString { fn LocalName(self) -> DOMString {
(**self.local_name()).to_owned() (**self.local_name()).to_owned()
@ -177,8 +176,7 @@ impl<'a> AttrMethods for JSRef<'a, Attr> {
fn SetValue(self, value: DOMString) { fn SetValue(self, value: DOMString) {
match self.owner() { match self.owner() {
None => *self.value.borrow_mut() = AttrValue::String(value), None => *self.value.borrow_mut() = AttrValue::String(value),
Some(o) => { Some(owner) => {
let owner = o.root();
let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value); let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
self.set_value(AttrSettingType::ReplacedAttr, value, owner.r()); self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
} }
@ -225,7 +223,7 @@ impl<'a> AttrMethods for JSRef<'a, Attr> {
} }
// https://dom.spec.whatwg.org/#dom-attr-ownerelement // https://dom.spec.whatwg.org/#dom-attr-ownerelement
fn GetOwnerElement(self) -> Option<Temporary<Element>> { fn GetOwnerElement(self) -> Option<Root<Element>> {
self.owner() self.owner()
} }
@ -236,19 +234,19 @@ impl<'a> AttrMethods for JSRef<'a, Attr> {
} }
pub trait AttrHelpers<'a> { pub trait AttrHelpers<'a> {
fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>); fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element);
fn value(self) -> Ref<'a, AttrValue>; fn value(self) -> Ref<'a, AttrValue>;
fn local_name(self) -> &'a Atom; fn local_name(self) -> &'a Atom;
fn set_owner(self, owner: Option<JSRef<Element>>); fn set_owner(self, owner: Option<&Element>);
fn owner(self) -> Option<Temporary<Element>>; fn owner(self) -> Option<Root<Element>>;
fn summarize(self) -> AttrInfo; fn summarize(self) -> AttrInfo;
} }
impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> { impl<'a> AttrHelpers<'a> for &'a Attr {
fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>) { fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
assert!(Some(owner) == self.owner().root().r()); assert!(Some(owner) == self.owner().r());
let node: JSRef<Node> = NodeCast::from_ref(owner); let node = NodeCast::from_ref(owner);
let namespace_is_null = self.namespace == ns!(""); let namespace_is_null = self.namespace == ns!("");
match set_type { match set_type {
@ -265,21 +263,21 @@ impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
} }
fn value(self) -> Ref<'a, AttrValue> { fn value(self) -> Ref<'a, AttrValue> {
self.extended_deref().value.borrow() self.value.borrow()
} }
fn local_name(self) -> &'a Atom { fn local_name(self) -> &'a Atom {
&self.extended_deref().local_name &self.local_name
} }
/// Sets the owner element. Should be called after the attribute is added /// Sets the owner element. Should be called after the attribute is added
/// or removed from its older parent. /// or removed from its older parent.
fn set_owner(self, owner: Option<JSRef<Element>>) { fn set_owner(self, owner: Option<&Element>) {
let ref ns = self.namespace; let ref ns = self.namespace;
match (self.owner().root().r(), owner) { match (self.owner().r(), owner) {
(None, Some(new)) => { (None, Some(new)) => {
// Already in the list of attributes of new owner. // Already in the list of attributes of new owner.
assert!(new.get_attribute(&ns, &self.local_name).root().r() == Some(self)) assert!(new.get_attribute(&ns, &self.local_name) == Some(Root::from_ref(self)))
} }
(Some(old), None) => { (Some(old), None) => {
// Already gone from the list of attributes of old owner. // Already gone from the list of attributes of old owner.
@ -287,11 +285,11 @@ impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
} }
(old, new) => assert!(old == new) (old, new) => assert!(old == new)
} }
self.owner.set(owner.map(JS::from_rooted)) self.owner.set(owner.map(JS::from_ref))
} }
fn owner(self) -> Option<Temporary<Element>> { fn owner(self) -> Option<Root<Element>> {
self.owner.get().map(Temporary::from_rooted) self.owner.get().map(Root::from_rooted)
} }
fn summarize(self) -> AttrInfo { fn summarize(self) -> AttrInfo {
@ -311,7 +309,7 @@ pub trait AttrHelpersForLayout {
unsafe fn value_atom_forever(&self) -> Option<Atom>; unsafe fn value_atom_forever(&self) -> Option<Atom>;
unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>; unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
unsafe fn local_name_atom_forever(&self) -> Atom; unsafe fn local_name_atom_forever(&self) -> Atom;
unsafe fn value(&self) -> &AttrValue; unsafe fn value_for_layout(&self) -> &AttrValue;
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
@ -354,7 +352,7 @@ impl AttrHelpersForLayout for Attr {
} }
#[inline] #[inline]
unsafe fn value(&self) -> &AttrValue { unsafe fn value_for_layout(&self) -> &AttrValue {
self.value.borrow_for_layout() self.value.borrow_for_layout()
} }
} }

View file

@ -6,15 +6,22 @@
use dom::bindings::error::{Fallible, Error}; use dom::bindings::error::{Fallible, Error};
use dom::bindings::global::global_object_for_js_object; use dom::bindings::global::global_object_for_js_object;
use dom::bindings::js::JSRef;
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
use js::jsapi::{JSContext, JSObject, JS_WrapObject, JS_ObjectIsCallable, JS_GetGlobalObject}; use js::jsapi::{JSContext, JSObject, JS_WrapObject, IsCallable};
use js::jsapi::{JS_GetProperty, JS_IsExceptionPending, JS_ReportPendingException}; use js::jsapi::{JS_GetProperty, JS_IsExceptionPending, JS_ReportPendingException};
use js::jsapi::{RootedObject, RootedValue, MutableHandleObject, Heap};
use js::jsapi::{JSAutoCompartment};
use js::jsapi::{JS_BeginRequest, JS_EndRequest};
use js::jsapi::{JS_EnterCompartment, JS_LeaveCompartment, JSCompartment};
use js::jsapi::GetGlobalForObjectCrossCompartment;
use js::jsapi::{JS_SaveFrameChain, JS_RestoreFrameChain};
use js::jsval::{JSVal, UndefinedValue}; use js::jsval::{JSVal, UndefinedValue};
use js::rust::with_compartment;
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr;
use std::rc::Rc;
use std::intrinsics::return_address;
use std::default::Default;
/// The exception handling used for a call. /// The exception handling used for a call.
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
@ -26,7 +33,7 @@ pub enum ExceptionHandling {
} }
/// A common base class for representing IDL callback function types. /// A common base class for representing IDL callback function types.
#[derive(Copy, Clone,PartialEq)] #[derive(PartialEq)]
#[jstraceable] #[jstraceable]
pub struct CallbackFunction { pub struct CallbackFunction {
object: CallbackObject object: CallbackObject
@ -34,17 +41,23 @@ pub struct CallbackFunction {
impl CallbackFunction { impl CallbackFunction {
/// Create a new `CallbackFunction` for this object. /// Create a new `CallbackFunction` for this object.
pub fn new(callback: *mut JSObject) -> CallbackFunction { pub fn new() -> CallbackFunction {
CallbackFunction { CallbackFunction {
object: CallbackObject { object: CallbackObject {
callback: callback callback: Heap::default()
} }
} }
} }
/// Initialize the callback function with a value.
/// Should be called once this object is done moving.
pub fn init(&mut self, callback: *mut JSObject) {
self.object.callback.set(callback);
}
} }
/// A common base class for representing IDL callback interface types. /// A common base class for representing IDL callback interface types.
#[derive(Copy, Clone,PartialEq)] #[derive(PartialEq)]
#[jstraceable] #[jstraceable]
pub struct CallbackInterface { pub struct CallbackInterface {
object: CallbackObject object: CallbackObject
@ -53,18 +66,23 @@ pub struct CallbackInterface {
/// A common base class for representing IDL callback function and /// A common base class for representing IDL callback function and
/// callback interface types. /// callback interface types.
#[allow(raw_pointer_derive)] #[allow(raw_pointer_derive)]
#[derive(Copy, Clone,PartialEq)]
#[jstraceable] #[jstraceable]
struct CallbackObject { struct CallbackObject {
/// The underlying `JSObject`. /// The underlying `JSObject`.
callback: *mut JSObject, callback: Heap<*mut JSObject>,
}
impl PartialEq for CallbackObject {
fn eq(&self, other: &CallbackObject) -> bool {
self.callback.get() == other.callback.get()
}
} }
/// A trait to be implemented by concrete IDL callback function and /// A trait to be implemented by concrete IDL callback function and
/// callback interface types. /// callback interface types.
pub trait CallbackContainer { pub trait CallbackContainer {
/// Create a new CallbackContainer object for the given `JSObject`. /// Create a new CallbackContainer object for the given `JSObject`.
fn new(callback: *mut JSObject) -> Self; fn new(callback: *mut JSObject) -> Rc<Self>;
/// Returns the underlying `JSObject`. /// Returns the underlying `JSObject`.
fn callback(&self) -> *mut JSObject; fn callback(&self) -> *mut JSObject;
} }
@ -72,83 +90,103 @@ pub trait CallbackContainer {
impl CallbackInterface { impl CallbackInterface {
/// Returns the underlying `JSObject`. /// Returns the underlying `JSObject`.
pub fn callback(&self) -> *mut JSObject { pub fn callback(&self) -> *mut JSObject {
self.object.callback self.object.callback.get()
} }
} }
impl CallbackFunction { impl CallbackFunction {
/// Returns the underlying `JSObject`. /// Returns the underlying `JSObject`.
pub fn callback(&self) -> *mut JSObject { pub fn callback(&self) -> *mut JSObject {
self.object.callback self.object.callback.get()
} }
} }
impl CallbackInterface { impl CallbackInterface {
/// Create a new CallbackInterface object for the given `JSObject`. /// Create a new CallbackInterface object for the given `JSObject`.
pub fn new(callback: *mut JSObject) -> CallbackInterface { pub fn new() -> CallbackInterface {
CallbackInterface { CallbackInterface {
object: CallbackObject { object: CallbackObject {
callback: callback callback: Heap::default()
} }
} }
} }
/// Initialize the callback function with a value.
/// Should be called once this object is done moving.
pub fn init(&mut self, callback: *mut JSObject) {
self.object.callback.set(callback);
}
/// Returns the property with the given `name`, if it is a callable object, /// Returns the property with the given `name`, if it is a callable object,
/// or an error otherwise. /// or an error otherwise.
pub fn get_callable_property(&self, cx: *mut JSContext, name: &str) pub fn get_callable_property(&self, cx: *mut JSContext, name: &str)
-> Fallible<JSVal> { -> Fallible<JSVal> {
let mut callable = UndefinedValue(); let mut callable = RootedValue::new(cx, UndefinedValue());
let obj = RootedObject::new(cx, self.callback());
unsafe { unsafe {
let c_name = CString::new(name).unwrap(); let c_name = CString::new(name).unwrap();
if JS_GetProperty(cx, self.callback(), c_name.as_ptr(), &mut callable) == 0 { if JS_GetProperty(cx, obj.handle(), c_name.as_ptr(),
callable.handle_mut()) == 0 {
return Err(Error::JSFailed); return Err(Error::JSFailed);
} }
if !callable.is_object() || if !callable.ptr.is_object() ||
JS_ObjectIsCallable(cx, callable.to_object()) == 0 { IsCallable(callable.ptr.to_object()) == 0 {
return Err(Error::Type( return Err(Error::Type(
format!("The value of the {} property is not callable", name))); format!("The value of the {} property is not callable", name)));
} }
} }
Ok(callable) Ok(callable.ptr)
} }
} }
/// Wraps the reflector for `p` into the compartment of `cx`. /// Wraps the reflector for `p` into the compartment of `cx`.
pub fn wrap_call_this_object<T: Reflectable>(cx: *mut JSContext, pub fn wrap_call_this_object<T: Reflectable>(cx: *mut JSContext,
p: JSRef<T>) -> *mut JSObject { p: &T,
let mut obj = p.reflector().get_jsobject(); mut rval: MutableHandleObject) {
assert!(!obj.is_null()); rval.set(p.reflector().get_jsobject().get());
assert!(!rval.get().is_null());
unsafe { unsafe {
if JS_WrapObject(cx, &mut obj) == 0 { if JS_WrapObject(cx, rval) == 0 {
return ptr::null_mut(); rval.set(ptr::null_mut());
} }
} }
return obj;
} }
/// A class that performs whatever setup we need to safely make a call while /// A class that performs whatever setup we need to safely make a call while
/// this class is on the stack. After `new` returns, the call is safe to make. /// this class is on the stack. After `new` returns, the call is safe to make.
pub struct CallSetup { pub struct CallSetup {
/// The compartment for reporting exceptions.
/// As a RootedObject, this must be the first field in order to
/// determine the final address on the stack correctly.
exception_compartment: RootedObject,
/// The `JSContext` used for the call. /// The `JSContext` used for the call.
cx: *mut JSContext, cx: *mut JSContext,
/// The compartment we were in before the call.
old_compartment: *mut JSCompartment,
/// The exception handling used for the call. /// The exception handling used for the call.
_handling: ExceptionHandling, handling: ExceptionHandling,
} }
impl CallSetup { impl CallSetup {
/// Performs the setup needed to make a call. /// Performs the setup needed to make a call.
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new<T: CallbackContainer>(callback: T, handling: ExceptionHandling) -> CallSetup { pub fn new<T: CallbackContainer>(callback: &T, handling: ExceptionHandling) -> CallSetup {
let global = global_object_for_js_object(callback.callback()); let global = global_object_for_js_object(callback.callback());
let global = global.root();
let cx = global.r().get_cx(); let cx = global.r().get_cx();
unsafe { JS_BeginRequest(cx); }
let exception_compartment = unsafe {
GetGlobalForObjectCrossCompartment(callback.callback())
};
CallSetup { CallSetup {
exception_compartment:
RootedObject::new_with_addr(cx, exception_compartment,
unsafe { return_address() }),
cx: cx, cx: cx,
_handling: handling, old_compartment: unsafe { JS_EnterCompartment(cx, callback.callback()) },
handling: handling,
} }
} }
@ -160,14 +198,23 @@ impl CallSetup {
impl Drop for CallSetup { impl Drop for CallSetup {
fn drop(&mut self) { fn drop(&mut self) {
let need_to_deal_with_exception = unsafe { JS_IsExceptionPending(self.cx) } != 0; unsafe { JS_LeaveCompartment(self.cx, self.old_compartment); }
let need_to_deal_with_exception =
self.handling == ExceptionHandling::Report &&
unsafe { JS_IsExceptionPending(self.cx) } != 0;
if need_to_deal_with_exception { if need_to_deal_with_exception {
unsafe { unsafe {
let old_global = JS_GetGlobalObject(self.cx); let old_global = RootedObject::new(self.cx, self.exception_compartment.ptr);
with_compartment(self.cx, old_global, || { let saved = JS_SaveFrameChain(self.cx) != 0;
JS_ReportPendingException(self.cx) {
}); let _ac = JSAutoCompartment::new(self.cx, old_global.ptr);
JS_ReportPendingException(self.cx);
}
if saved {
JS_RestoreFrameChain(self.cx);
}
} }
} }
unsafe { JS_EndRequest(self.cx); }
} }
} }

View file

@ -40,7 +40,9 @@ impl<T> DOMRefCell<T> {
/// so you have to be careful in trace code! /// so you have to be careful in trace code!
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub unsafe fn borrow_for_gc_trace<'a>(&'a self) -> &'a T { pub unsafe fn borrow_for_gc_trace<'a>(&'a self) -> &'a T {
debug_assert!(task_state::get().contains(SCRIPT | IN_GC)); // FIXME: IN_GC isn't reliable enough - doesn't catch minor GCs
// https://github.com/servo/servo/issues/6389
//debug_assert!(task_state::get().contains(SCRIPT | IN_GC));
&*self.value.as_unsafe_cell().get() &*self.value.as_unsafe_cell().get()
} }

View file

@ -15,7 +15,7 @@
DOMInterfaces = { DOMInterfaces = {
'Window': { 'Window': {
'outerObjectHook': 'Some(bindings::utils::outerize_global as extern fn(*mut JSContext, JSHandleObject) -> *mut JSObject)', 'outerObjectHook': 'Some(bindings::utils::outerize_global)',
}, },
#FIXME(jdm): This should be 'register': False, but then we don't generate enum types #FIXME(jdm): This should be 'register': False, but then we don't generate enum types

File diff suppressed because it is too large Load diff

View file

@ -148,16 +148,16 @@ class Descriptor(DescriptorProvider):
if self.interface.isCallback(): if self.interface.isCallback():
self.needsRooting = False self.needsRooting = False
ty = "%sBinding::%s" % (ifaceName, ifaceName) ty = "%sBinding::%s" % (ifaceName, ifaceName)
self.returnType = ty self.returnType = "Rc<%s>"% ty
self.argumentType = "???" self.argumentType = "???"
self.memberType = "???" self.memberType = "???"
self.nativeType = ty self.nativeType = ty
else: else:
self.needsRooting = True self.needsRooting = True
self.returnType = "Temporary<%s>" % ifaceName self.returnType = "Root<%s>" % ifaceName
self.argumentType = "JSRef<%s>" % ifaceName self.argumentType = "&%s" % ifaceName
self.memberType = "Root<%s>" % ifaceName self.memberType = "Root<%s>" % ifaceName
self.nativeType = "Unrooted<%s>" % ifaceName self.nativeType = "Root<%s>" % ifaceName
self.concreteType = ifaceName self.concreteType = ifaceName
self.register = desc.get('register', True) self.register = desc.get('register', True)

View file

@ -24,17 +24,17 @@
//! | USVString | `USVString` | //! | USVString | `USVString` |
//! | ByteString | `ByteString` | //! | ByteString | `ByteString` |
//! | object | `*mut JSObject` | //! | object | `*mut JSObject` |
//! | interface types | `JSRef<T>` | `Temporary<T>` | //! | interface types | `&T` | `Root<T>` |
//! | dictionary types | `&T` | *unsupported* | //! | dictionary types | `&T` | *unsupported* |
//! | enumeration types | `T` | //! | enumeration types | `T` |
//! | callback function types | `T` | //! | callback function types | `Rc<T>` |
//! | nullable types | `Option<T>` | //! | nullable types | `Option<T>` |
//! | sequences | `Vec<T>` | //! | sequences | `Vec<T>` |
//! | union types | `T` | //! | union types | `T` |
use dom::bindings::codegen::PrototypeList; use dom::bindings::codegen::PrototypeList;
use dom::bindings::error::throw_type_error; use dom::bindings::error::throw_type_error;
use dom::bindings::js::{JSRef, Root, Unrooted}; use dom::bindings::js::Root;
use dom::bindings::num::Finite; use dom::bindings::num::Finite;
use dom::bindings::str::{ByteString, USVString}; use dom::bindings::str::{ByteString, USVString};
use dom::bindings::utils::{Reflectable, Reflector, DOMClass}; use dom::bindings::utils::{Reflectable, Reflector, DOMClass};
@ -43,14 +43,15 @@ use util::str::DOMString;
use js; use js;
use js::glue::{RUST_JSID_TO_STRING, RUST_JSID_IS_STRING}; use js::glue::{RUST_JSID_TO_STRING, RUST_JSID_IS_STRING};
use js::glue::RUST_JS_NumberValue; use js::glue::RUST_JS_NumberValue;
use js::jsapi::{JSBool, JSContext, JSObject, JSString, jsid}; use js::rust::{ToUint64, ToInt64};
use js::jsapi::{JS_ValueToUint64, JS_ValueToInt64}; use js::rust::{ToUint32, ToInt32};
use js::jsapi::{JS_ValueToECMAUint32, JS_ValueToECMAInt32}; use js::rust::{ToUint16, ToNumber, ToBoolean, ToString};
use js::jsapi::{JS_ValueToUint16, JS_ValueToNumber, JS_ValueToBoolean}; use js::jsapi::{JSContext, JSObject, JSString};
use js::jsapi::{JS_ValueToString, JS_GetStringCharsAndLength}; use js::jsapi::{JS_StringHasLatin1Chars, JS_GetLatin1StringCharsAndLength, JS_GetTwoByteStringCharsAndLength};
use js::jsapi::{JS_NewUCStringCopyN, JS_NewStringCopyN}; use js::jsapi::{JS_NewUCStringCopyN, JS_NewStringCopyN};
use js::jsapi::{JS_WrapValue}; use js::jsapi::{JS_WrapValue};
use js::jsapi::{JSClass, JS_GetClass}; use js::jsapi::{JSClass, JS_GetClass};
use js::jsapi::{HandleId, HandleValue, HandleObject, MutableHandleValue};
use js::jsval::JSVal; use js::jsval::JSVal;
use js::jsval::{UndefinedValue, NullValue, BooleanValue, Int32Value, UInt32Value}; use js::jsval::{UndefinedValue, NullValue, BooleanValue, Int32Value, UInt32Value};
use js::jsval::{StringValue, ObjectValue, ObjectOrNullValue}; use js::jsval::{StringValue, ObjectValue, ObjectOrNullValue};
@ -60,6 +61,9 @@ use num::Float;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::default; use std::default;
use std::slice; use std::slice;
use std::ptr;
use std::rc::Rc;
use core::nonzero::NonZero;
/// A trait to retrieve the constants necessary to check if a `JSObject` /// A trait to retrieve the constants necessary to check if a `JSObject`
/// implements a given interface. /// implements a given interface.
@ -74,7 +78,7 @@ pub trait IDLInterface {
/// A trait to convert Rust types to `JSVal`s. /// A trait to convert Rust types to `JSVal`s.
pub trait ToJSValConvertible { pub trait ToJSValConvertible {
/// Convert `self` to a `JSVal`. JSAPI failure causes a task failure. /// Convert `self` to a `JSVal`. JSAPI failure causes a task failure.
fn to_jsval(&self, cx: *mut JSContext) -> JSVal; fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue);
} }
/// A trait to convert `JSVal`s to Rust types. /// A trait to convert `JSVal`s to Rust types.
@ -85,206 +89,201 @@ pub trait FromJSValConvertible {
/// Optional configuration of type `T` can be passed as the `option` /// Optional configuration of type `T` can be passed as the `option`
/// argument. /// argument.
/// If it returns `Err(())`, a JSAPI exception is pending. /// If it returns `Err(())`, a JSAPI exception is pending.
fn from_jsval(cx: *mut JSContext, val: JSVal, option: Self::Config) -> Result<Self, ()>; fn from_jsval(cx: *mut JSContext, val: HandleValue, option: Self::Config) -> Result<Self, ()>;
} }
impl ToJSValConvertible for () { impl ToJSValConvertible for () {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
UndefinedValue() rval.set(UndefinedValue());
} }
} }
impl ToJSValConvertible for JSVal { impl ToJSValConvertible for JSVal {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
let mut value = *self; rval.set(*self);
if unsafe { JS_WrapValue(cx, &mut value) } == 0 { if unsafe { JS_WrapValue(cx, rval) } == 0 {
panic!("JS_WrapValue failed."); panic!("JS_WrapValue failed.");
} }
value
} }
} }
unsafe fn convert_from_jsval<T: default::Default>( impl ToJSValConvertible for HandleValue {
cx: *mut JSContext, value: JSVal, fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
convert_fn: unsafe extern "C" fn(*mut JSContext, JSVal, *mut T) -> JSBool) -> Result<T, ()> { rval.set(self.get());
let mut ret = default::Default::default(); if unsafe { JS_WrapValue(cx, rval) } == 0 {
if convert_fn(cx, value, &mut ret) == 0 { panic!("JS_WrapValue failed.");
Err(()) }
} else {
Ok(ret)
} }
} }
impl ToJSValConvertible for bool { impl ToJSValConvertible for bool {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
BooleanValue(*self) rval.set(BooleanValue(*self));
} }
} }
impl FromJSValConvertible for bool { impl FromJSValConvertible for bool {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<bool, ()> { fn from_jsval(_cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<bool, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToBoolean) }; Ok(ToBoolean(val))
result.map(|b| b != 0)
} }
} }
impl ToJSValConvertible for i8 { impl ToJSValConvertible for i8 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
Int32Value(*self as i32) rval.set(Int32Value(*self as i32));
} }
} }
impl FromJSValConvertible for i8 { impl FromJSValConvertible for i8 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<i8, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<i8, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToECMAInt32) }; let result = ToInt32(cx, val);
result.map(|v| v as i8) result.map(|v| v as i8)
} }
} }
impl ToJSValConvertible for u8 { impl ToJSValConvertible for u8 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
Int32Value(*self as i32) rval.set(Int32Value(*self as i32));
} }
} }
impl FromJSValConvertible for u8 { impl FromJSValConvertible for u8 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<u8, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<u8, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToECMAInt32) }; let result = ToInt32(cx, val);
result.map(|v| v as u8) result.map(|v| v as u8)
} }
} }
impl ToJSValConvertible for i16 { impl ToJSValConvertible for i16 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
Int32Value(*self as i32) rval.set(Int32Value(*self as i32));
} }
} }
impl FromJSValConvertible for i16 { impl FromJSValConvertible for i16 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<i16, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<i16, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToECMAInt32) }; let result = ToInt32(cx, val);
result.map(|v| v as i16) result.map(|v| v as i16)
} }
} }
impl ToJSValConvertible for u16 { impl ToJSValConvertible for u16 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
Int32Value(*self as i32) rval.set(Int32Value(*self as i32));
} }
} }
impl FromJSValConvertible for u16 { impl FromJSValConvertible for u16 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<u16, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<u16, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToUint16) } ToUint16(cx, val)
} }
} }
impl ToJSValConvertible for i32 { impl ToJSValConvertible for i32 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
Int32Value(*self) rval.set(Int32Value(*self));
} }
} }
impl FromJSValConvertible for i32 { impl FromJSValConvertible for i32 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<i32, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<i32, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToECMAInt32) } ToInt32(cx, val)
} }
} }
impl ToJSValConvertible for u32 { impl ToJSValConvertible for u32 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
UInt32Value(*self) rval.set(UInt32Value(*self));
} }
} }
impl FromJSValConvertible for u32 { impl FromJSValConvertible for u32 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<u32, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<u32, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToECMAUint32) } ToUint32(cx, val)
} }
} }
impl ToJSValConvertible for i64 { impl ToJSValConvertible for i64 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
unsafe { unsafe {
RUST_JS_NumberValue(*self as f64) rval.set(RUST_JS_NumberValue(*self as f64));
} }
} }
} }
impl FromJSValConvertible for i64 { impl FromJSValConvertible for i64 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<i64, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<i64, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToInt64) } ToInt64(cx, val)
} }
} }
impl ToJSValConvertible for u64 { impl ToJSValConvertible for u64 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
unsafe { unsafe {
RUST_JS_NumberValue(*self as f64) rval.set(RUST_JS_NumberValue(*self as f64));
} }
} }
} }
impl FromJSValConvertible for u64 { impl FromJSValConvertible for u64 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<u64, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<u64, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToUint64) } ToUint64(cx, val)
} }
} }
impl ToJSValConvertible for f32 { impl ToJSValConvertible for f32 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
unsafe { unsafe {
RUST_JS_NumberValue(*self as f64) rval.set(RUST_JS_NumberValue(*self as f64));
} }
} }
} }
impl FromJSValConvertible for f32 { impl FromJSValConvertible for f32 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<f32, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<f32, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToNumber) }; let result = ToNumber(cx, val);
result.map(|f| f as f32) result.map(|f| f as f32)
} }
} }
impl ToJSValConvertible for f64 { impl ToJSValConvertible for f64 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
unsafe { unsafe {
RUST_JS_NumberValue(*self) rval.set(RUST_JS_NumberValue(*self));
} }
} }
} }
impl FromJSValConvertible for f64 { impl FromJSValConvertible for f64 {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<f64, ()> { fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<f64, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToNumber) } ToNumber(cx, val)
} }
} }
impl<T: Float + ToJSValConvertible> ToJSValConvertible for Finite<T> { impl<T: Float + ToJSValConvertible> ToJSValConvertible for Finite<T> {
#[inline] #[inline]
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
let value = **self; let value = **self;
value.to_jsval(cx) value.to_jsval(cx, rval);
} }
} }
impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite<T> { impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite<T> {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, value: JSVal, option: ()) -> Result<Finite<T>, ()> { fn from_jsval(cx: *mut JSContext, value: HandleValue, option: ()) -> Result<Finite<T>, ()> {
let result = try!(FromJSValConvertible::from_jsval(cx, value, option)); let result = try!(FromJSValConvertible::from_jsval(cx, value, option));
match Finite::new(result) { match Finite::new(result) {
Some(v) => Ok(v), Some(v) => Ok(v),
@ -297,21 +296,22 @@ impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite
} }
impl ToJSValConvertible for str { impl ToJSValConvertible for str {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
unsafe { unsafe {
let string_utf16: Vec<u16> = self.utf16_units().collect(); let string_utf16: Vec<u16> = self.utf16_units().collect();
let jsstr = JS_NewUCStringCopyN(cx, string_utf16.as_ptr(), string_utf16.len() as libc::size_t); let jsstr = JS_NewUCStringCopyN(cx, string_utf16.as_ptr() as *const i16,
string_utf16.len() as libc::size_t);
if jsstr.is_null() { if jsstr.is_null() {
panic!("JS_NewUCStringCopyN failed"); panic!("JS_NewUCStringCopyN failed");
} }
StringValue(&*jsstr) rval.set(StringValue(&*jsstr));
} }
} }
} }
impl ToJSValConvertible for DOMString { impl ToJSValConvertible for DOMString {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
(**self).to_jsval(cx) (**self).to_jsval(cx, rval);
} }
} }
@ -333,18 +333,36 @@ impl default::Default for StringificationBehavior {
/// Convert the given `JSString` to a `DOMString`. Fails if the string does not /// Convert the given `JSString` to a `DOMString`. Fails if the string does not
/// contain valid UTF-16. /// contain valid UTF-16.
pub fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString { pub fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString {
unsafe { let mut length = 0;
let mut length = 0; let latin1 = unsafe { JS_StringHasLatin1Chars(s) != 0 };
let chars = JS_GetStringCharsAndLength(cx, s, &mut length); if latin1 {
let chars = unsafe {
JS_GetLatin1StringCharsAndLength(cx, ptr::null(), s, &mut length)
};
assert!(!chars.is_null()); assert!(!chars.is_null());
let char_vec = slice::from_raw_parts(chars, length as usize);
let mut buf = String::with_capacity(length as usize);
for i in 0..(length as isize) {
unsafe {
buf.push(*chars.offset(i) as char);
}
}
buf
} else {
let chars = unsafe {
JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), s, &mut length)
};
assert!(!chars.is_null());
let char_vec = unsafe {
slice::from_raw_parts(chars as *const u16, length as usize)
};
String::from_utf16(char_vec).unwrap() String::from_utf16(char_vec).unwrap()
} }
} }
/// Convert the given `jsid` to a `DOMString`. Fails if the `jsid` is not a /// Convert the given `jsid` to a `DOMString`. Fails if the `jsid` is not a
/// string, or if the string does not contain valid UTF-16. /// string, or if the string does not contain valid UTF-16.
pub fn jsid_to_str(cx: *mut JSContext, id: jsid) -> DOMString { pub fn jsid_to_str(cx: *mut JSContext, id: HandleId) -> DOMString {
unsafe { unsafe {
assert!(RUST_JSID_IS_STRING(id) != 0); assert!(RUST_JSID_IS_STRING(id) != 0);
jsstring_to_str(cx, RUST_JSID_TO_STRING(id)) jsstring_to_str(cx, RUST_JSID_TO_STRING(id))
@ -353,15 +371,16 @@ pub fn jsid_to_str(cx: *mut JSContext, id: jsid) -> DOMString {
impl FromJSValConvertible for DOMString { impl FromJSValConvertible for DOMString {
type Config = StringificationBehavior; type Config = StringificationBehavior;
fn from_jsval(cx: *mut JSContext, value: JSVal, fn from_jsval(cx: *mut JSContext, value: HandleValue,
null_behavior: StringificationBehavior) null_behavior: StringificationBehavior)
-> Result<DOMString, ()> { -> Result<DOMString, ()> {
if null_behavior == StringificationBehavior::Empty && value.is_null() { if null_behavior == StringificationBehavior::Empty &&
value.get().is_null() {
Ok("".to_owned()) Ok("".to_owned())
} else { } else {
let jsstr = unsafe { JS_ValueToString(cx, value) }; let jsstr = ToString(cx, value);
if jsstr.is_null() { if jsstr.is_null() {
debug!("JS_ValueToString failed"); debug!("ToString failed");
Err(()) Err(())
} else { } else {
Ok(jsstring_to_str(cx, jsstr)) Ok(jsstring_to_str(cx, jsstr))
@ -371,56 +390,75 @@ impl FromJSValConvertible for DOMString {
} }
impl ToJSValConvertible for USVString { impl ToJSValConvertible for USVString {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
self.0.to_jsval(cx) self.0.to_jsval(cx, rval);
} }
} }
impl FromJSValConvertible for USVString { impl FromJSValConvertible for USVString {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, value: JSVal, _: ()) fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ())
-> Result<USVString, ()> { -> Result<USVString, ()> {
let jsstr = unsafe { JS_ValueToString(cx, value) }; let jsstr = ToString(cx, value);
if jsstr.is_null() { if jsstr.is_null() {
debug!("JS_ValueToString failed"); debug!("ToString failed");
Err(()) return Err(());
} else { }
unsafe { let latin1 = unsafe { JS_StringHasLatin1Chars(jsstr) != 0 };
let mut length = 0; if latin1 {
let chars = JS_GetStringCharsAndLength(cx, jsstr, &mut length); return Ok(USVString(jsstring_to_str(cx, jsstr)));
assert!(!chars.is_null()); }
let char_vec = slice::from_raw_parts(chars, length as usize); unsafe {
Ok(USVString(String::from_utf16_lossy(char_vec))) let mut length = 0;
} let chars = JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), jsstr, &mut length);
assert!(!chars.is_null());
let char_vec = slice::from_raw_parts(chars as *const u16, length as usize);
Ok(USVString(String::from_utf16_lossy(char_vec)))
} }
} }
} }
impl ToJSValConvertible for ByteString { impl ToJSValConvertible for ByteString {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
unsafe { unsafe {
let jsstr = JS_NewStringCopyN(cx, self.as_ptr() as *const libc::c_char, let jsstr = JS_NewStringCopyN(cx, self.as_ptr() as *const libc::c_char,
self.len() as libc::size_t); self.len() as libc::size_t);
if jsstr.is_null() { if jsstr.is_null() {
panic!("JS_NewStringCopyN failed"); panic!("JS_NewStringCopyN failed");
} }
StringValue(&*jsstr) rval.set(StringValue(&*jsstr));
} }
} }
} }
impl FromJSValConvertible for ByteString { impl FromJSValConvertible for ByteString {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, value: JSVal, _option: ()) -> Result<ByteString, ()> { fn from_jsval(cx: *mut JSContext, value: HandleValue, _option: ()) -> Result<ByteString, ()> {
unsafe { let string = ToString(cx, value);
let string = JS_ValueToString(cx, value); if string.is_null() {
if string.is_null() { debug!("ToString failed");
debug!("JS_ValueToString failed"); return Err(());
return Err(()); }
}
let latin1 = unsafe { JS_StringHasLatin1Chars(string) != 0 };
if latin1 {
let mut length = 0; let mut length = 0;
let chars = JS_GetStringCharsAndLength(cx, string, &mut length); let chars = unsafe {
JS_GetLatin1StringCharsAndLength(cx, ptr::null(),
string, &mut length)
};
assert!(!chars.is_null());
let char_vec = unsafe {
Vec::from_raw_buf(chars as *mut u8, length as usize)
};
return Ok(ByteString::new(char_vec));
}
unsafe {
let mut length = 0;
let chars = JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), string, &mut length);
let char_vec = slice::from_raw_parts(chars, length as usize); let char_vec = slice::from_raw_parts(chars, length as usize);
if char_vec.iter().any(|&c| c > 0xFF) { if char_vec.iter().any(|&c| c > 0xFF) {
@ -434,14 +472,13 @@ impl FromJSValConvertible for ByteString {
} }
impl ToJSValConvertible for Reflector { impl ToJSValConvertible for Reflector {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
let obj = self.get_jsobject(); let obj = self.get_jsobject().get();
assert!(!obj.is_null()); assert!(!obj.is_null());
let mut value = ObjectValue(unsafe { &*obj }); rval.set(ObjectValue(unsafe { &*obj }));
if unsafe { JS_WrapValue(cx, &mut value) } == 0 { if unsafe { JS_WrapValue(cx, rval) } == 0 {
panic!("JS_WrapValue failed."); panic!("JS_WrapValue failed.");
} }
value
} }
} }
@ -454,11 +491,10 @@ pub fn is_dom_class(clasp: *const JSClass) -> bool {
/// Returns whether `obj` is a DOM object implemented as a proxy. /// Returns whether `obj` is a DOM object implemented as a proxy.
pub fn is_dom_proxy(obj: *mut JSObject) -> bool { pub fn is_dom_proxy(obj: *mut JSObject) -> bool {
use js::glue::{js_IsObjectProxyClass, js_IsFunctionProxyClass, IsProxyHandlerFamily}; use js::glue::IsProxyHandlerFamily;
unsafe { unsafe {
(js_IsObjectProxyClass(obj) || js_IsFunctionProxyClass(obj)) && let clasp = JS_GetClass(obj);
IsProxyHandlerFamily(obj) ((*clasp).flags & js::JSCLASS_IS_PROXY) != 0 && IsProxyHandlerFamily(obj) != 0
} }
} }
@ -467,29 +503,24 @@ pub fn is_dom_proxy(obj: *mut JSObject) -> bool {
// We use slot 0 for holding the raw object. This is safe for both // We use slot 0 for holding the raw object. This is safe for both
// globals and non-globals. // globals and non-globals.
pub const DOM_OBJECT_SLOT: u32 = 0; pub const DOM_OBJECT_SLOT: u32 = 0;
const DOM_PROXY_OBJECT_SLOT: u32 = js::JSSLOT_PROXY_PRIVATE;
/// Returns the index of the slot wherein a pointer to the reflected DOM object
/// is stored.
///
/// Fails if `obj` is not a DOM object.
pub unsafe fn dom_object_slot(obj: *mut JSObject) -> u32 {
let clasp = JS_GetClass(obj);
if is_dom_class(&*clasp) {
DOM_OBJECT_SLOT
} else {
assert!(is_dom_proxy(obj));
DOM_PROXY_OBJECT_SLOT
}
}
/// Get the DOM object from the given reflector. /// Get the DOM object from the given reflector.
pub unsafe fn native_from_reflector<T>(obj: *mut JSObject) -> *const T { pub unsafe fn native_from_reflector<T>(obj: *mut JSObject) -> *const T {
use js::jsapi::JS_GetReservedSlot; use js::jsapi::JS_GetReservedSlot;
use js::glue::GetProxyPrivate;
let slot = dom_object_slot(obj); let clasp = JS_GetClass(obj);
let value = JS_GetReservedSlot(obj, slot); let value = if is_dom_class(clasp) {
value.to_private() as *const T JS_GetReservedSlot(obj, DOM_OBJECT_SLOT)
} else {
assert!(is_dom_proxy(obj));
GetProxyPrivate(obj)
};
if value.is_undefined() {
ptr::null()
} else {
value.to_private() as *const T
}
} }
/// Get the `DOMClass` from `obj`, or `Err(())` if `obj` is not a DOM object. /// Get the `DOMClass` from `obj`, or `Err(())` if `obj` is not a DOM object.
@ -518,17 +549,16 @@ unsafe fn get_dom_class(obj: *mut JSObject) -> Result<DOMClass, ()> {
/// Returns Err(()) if `obj` is an opaque security wrapper or if the object is /// Returns Err(()) if `obj` is an opaque security wrapper or if the object is
/// not a reflector for a DOM object of the given type (as defined by the /// not a reflector for a DOM object of the given type (as defined by the
/// proto_id and proto_depth). /// proto_id and proto_depth).
pub fn native_from_reflector_jsmanaged<T>(mut obj: *mut JSObject) -> Result<Unrooted<T>, ()> pub fn native_from_reflector_jsmanaged<T>(mut obj: *mut JSObject) -> Result<Root<T>, ()>
where T: Reflectable + IDLInterface where T: Reflectable + IDLInterface
{ {
use js::glue::{IsWrapper, UnwrapObject}; use js::glue::{IsWrapper, UnwrapObject};
use std::ptr;
unsafe { unsafe {
let dom_class = try!(get_dom_class(obj).or_else(|_| { let dom_class = try!(get_dom_class(obj).or_else(|_| {
if IsWrapper(obj) == 1 { if IsWrapper(obj) == 1 {
debug!("found wrapper"); debug!("found wrapper");
obj = UnwrapObject(obj, /* stopAtOuter = */ 0, ptr::null_mut()); obj = UnwrapObject(obj, /* stopAtOuter = */ 0);
if obj.is_null() { if obj.is_null() {
debug!("unwrapping security wrapper failed"); debug!("unwrapping security wrapper failed");
Err(()) Err(())
@ -547,7 +577,9 @@ pub fn native_from_reflector_jsmanaged<T>(mut obj: *mut JSObject) -> Result<Unro
let proto_depth = <T as IDLInterface>::get_prototype_depth(); let proto_depth = <T as IDLInterface>::get_prototype_depth();
if dom_class.interface_chain[proto_depth] == proto_id { if dom_class.interface_chain[proto_depth] == proto_id {
debug!("good prototype"); debug!("good prototype");
Ok(Unrooted::from_raw(native_from_reflector(obj))) let native = native_from_reflector(obj);
assert!(!native.is_null());
Ok(Root::new(NonZero::new(native)))
} else { } else {
debug!("bad prototype"); debug!("bad prototype");
Err(()) Err(())
@ -555,37 +587,54 @@ pub fn native_from_reflector_jsmanaged<T>(mut obj: *mut JSObject) -> Result<Unro
} }
} }
/// Get a Rooted<T> for a DOM object accessible from a HandleValue
pub fn native_from_handlevalue<T>(v: HandleValue) -> Result<Root<T>, ()>
where T: Reflectable + IDLInterface
{
native_from_reflector_jsmanaged(v.get().to_object())
}
/// Get a Rooted<T> for a DOM object accessible from a HandleObject
pub fn native_from_handleobject<T>(obj: HandleObject) -> Result<Root<T>, ()>
where T: Reflectable + IDLInterface
{
native_from_reflector_jsmanaged(obj.get())
}
impl<T: Reflectable> ToJSValConvertible for Root<T> { impl<T: Reflectable> ToJSValConvertible for Root<T> {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
self.r().reflector().to_jsval(cx) self.r().reflector().to_jsval(cx, rval);
} }
} }
impl<'a, T: Reflectable> ToJSValConvertible for JSRef<'a, T> { impl<'a, T: Reflectable> ToJSValConvertible for &'a T {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
self.reflector().to_jsval(cx) self.reflector().to_jsval(cx, rval);
}
}
impl<'a, T: Reflectable> ToJSValConvertible for Unrooted<T> {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
self.reflector().to_jsval(cx)
} }
} }
impl<T: ToJSValConvertible> ToJSValConvertible for Option<T> { impl<T: ToJSValConvertible> ToJSValConvertible for Option<T> {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
match self { match self {
&Some(ref value) => value.to_jsval(cx), &Some(ref value) => value.to_jsval(cx, rval),
&None => NullValue(), &None => rval.set(NullValue()),
}
}
}
impl<T: ToJSValConvertible> ToJSValConvertible for Option<Rc<T>> {
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
match self {
&Some(ref value) => (**value).to_jsval(cx, rval),
&None => rval.set(NullValue()),
} }
} }
} }
impl<X: default::Default, T: FromJSValConvertible<Config=X>> FromJSValConvertible for Option<T> { impl<X: default::Default, T: FromJSValConvertible<Config=X>> FromJSValConvertible for Option<T> {
type Config = (); type Config = ();
fn from_jsval(cx: *mut JSContext, value: JSVal, _: ()) -> Result<Option<T>, ()> { fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ()) -> Result<Option<T>, ()> {
if value.is_null_or_undefined() { if value.get().is_null_or_undefined() {
Ok(None) Ok(None)
} else { } else {
let option: X = default::Default::default(); let option: X = default::Default::default();
@ -596,11 +645,10 @@ impl<X: default::Default, T: FromJSValConvertible<Config=X>> FromJSValConvertibl
} }
impl ToJSValConvertible for *mut JSObject { impl ToJSValConvertible for *mut JSObject {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
let mut wrapped = ObjectOrNullValue(*self); rval.set(ObjectOrNullValue(*self));
unsafe { unsafe {
assert!(JS_WrapValue(cx, &mut wrapped) != 0); assert!(JS_WrapValue(cx, rval) != 0);
} }
wrapped
} }
} }

View file

@ -6,20 +6,22 @@
use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::Rootable;
use dom::domexception::{DOMException, DOMErrorName}; use dom::domexception::{DOMException, DOMErrorName};
use util::str::DOMString; use util::str::DOMString;
use js::jsapi::{JSContext, JSObject}; use js::jsapi::{JSContext, JSObject, RootedValue};
use js::jsapi::{JS_IsExceptionPending, JS_SetPendingException, JS_ReportPendingException}; use js::jsapi::{JS_IsExceptionPending, JS_SetPendingException, JS_ReportPendingException};
use js::jsapi::{JS_ReportErrorNumber, JSErrorFormatString, JSEXN_TYPEERR, JSEXN_RANGEERR}; use js::jsapi::{JS_ReportErrorNumber1, JSErrorFormatString, JSExnType};
use js::jsapi::{JS_SaveFrameChain, JS_RestoreFrameChain}; use js::jsapi::{JS_SaveFrameChain, JS_RestoreFrameChain};
use js::rust::with_compartment; use js::jsapi::JSAutoCompartment;
use js::jsval::UndefinedValue;
use js::JSFalse;
use libc; use libc;
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr;
use std::mem;
/// DOM exceptions that can be thrown by a native DOM method. /// DOM exceptions that can be thrown by a native DOM method.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -116,10 +118,11 @@ pub fn throw_dom_exception(cx: *mut JSContext, global: GlobalRef,
}; };
assert!(unsafe { JS_IsExceptionPending(cx) } == 0); assert!(unsafe { JS_IsExceptionPending(cx) } == 0);
let exception = DOMException::new(global, code).root(); let exception = DOMException::new(global, code);
let thrown = exception.to_jsval(cx); let mut thrown = RootedValue::new(cx, UndefinedValue());
exception.to_jsval(cx, thrown.handle_mut());
unsafe { unsafe {
JS_SetPendingException(cx, thrown); JS_SetPendingException(cx, thrown.handle());
} }
} }
@ -128,9 +131,10 @@ pub fn report_pending_exception(cx: *mut JSContext, obj: *mut JSObject) {
unsafe { unsafe {
if JS_IsExceptionPending(cx) != 0 { if JS_IsExceptionPending(cx) != 0 {
let saved = JS_SaveFrameChain(cx); let saved = JS_SaveFrameChain(cx);
with_compartment(cx, obj, || { {
let _ac = JSAutoCompartment::new(cx, obj);
JS_ReportPendingException(cx); JS_ReportPendingException(cx);
}); }
if saved != 0 { if saved != 0 {
JS_RestoreFrameChain(cx); JS_RestoreFrameChain(cx);
} }
@ -158,25 +162,26 @@ static ERROR_FORMAT_STRING_STRING: [libc::c_char; 4] = [
static mut TYPE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString { static mut TYPE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char, format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
argCount: 1, argCount: 1,
exnType: JSEXN_TYPEERR as i16, exnType: JSExnType::JSEXN_TYPEERR as i16,
}; };
/// Format string struct used to throw `RangeError`s. /// Format string struct used to throw `RangeError`s.
static mut RANGE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString { static mut RANGE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char, format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
argCount: 1, argCount: 1,
exnType: JSEXN_RANGEERR as i16, exnType: JSExnType::JSEXN_RANGEERR as i16,
}; };
/// Callback used to throw javascript errors. /// Callback used to throw javascript errors.
/// See throw_js_error for info about error_number. /// See throw_js_error for info about error_number.
unsafe extern fn get_error_message(_user_ref: *mut libc::c_void, unsafe extern fn get_error_message(_user_ref: *mut libc::c_void,
_locale: *const libc::c_char, error_number: libc::c_uint)
error_number: libc::c_uint) -> *const JSErrorFormatString -> *const JSErrorFormatString
{ {
match error_number as i32 { let num: JSExnType = mem::transmute(error_number);
JSEXN_TYPEERR => &TYPE_ERROR_FORMAT_STRING as *const JSErrorFormatString, match num {
JSEXN_RANGEERR => &RANGE_ERROR_FORMAT_STRING as *const JSErrorFormatString, JSExnType::JSEXN_TYPEERR => &TYPE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
JSExnType::JSEXN_RANGEERR => &RANGE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
_ => panic!("Bad js error number given to get_error_message: {}", error_number) _ => panic!("Bad js error number given to get_error_message: {}", error_number)
} }
} }
@ -188,20 +193,18 @@ unsafe extern fn get_error_message(_user_ref: *mut libc::c_void,
fn throw_js_error(cx: *mut JSContext, error: &str, error_number: u32) { fn throw_js_error(cx: *mut JSContext, error: &str, error_number: u32) {
let error = CString::new(error).unwrap(); let error = CString::new(error).unwrap();
unsafe { unsafe {
JS_ReportErrorNumber(cx, JS_ReportErrorNumber1(cx,
Some(get_error_message as Some(get_error_message),
unsafe extern "C" fn(*mut libc::c_void, *const libc::c_char,
libc::c_uint) -> *const JSErrorFormatString),
ptr::null_mut(), error_number, error.as_ptr()); ptr::null_mut(), error_number, error.as_ptr());
} }
} }
/// Throw a `TypeError` with the given message. /// Throw a `TypeError` with the given message.
pub fn throw_type_error(cx: *mut JSContext, error: &str) { pub fn throw_type_error(cx: *mut JSContext, error: &str) {
throw_js_error(cx, error, JSEXN_TYPEERR as u32); throw_js_error(cx, error, JSExnType::JSEXN_TYPEERR as u32);
} }
/// Throw a `RangeError` with the given message. /// Throw a `RangeError` with the given message.
pub fn throw_range_error(cx: *mut JSContext, error: &str) { pub fn throw_range_error(cx: *mut JSContext, error: &str) {
throw_js_error(cx, error, JSEXN_RANGEERR as u32); throw_js_error(cx, error, JSExnType::JSEXN_RANGEERR as u32);
} }

View file

@ -9,7 +9,7 @@
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::conversions::native_from_reflector_jsmanaged; use dom::bindings::conversions::native_from_reflector_jsmanaged;
use dom::bindings::js::{JS, JSRef, Rootable, Root, Unrooted}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::DocumentHelpers; use dom::document::DocumentHelpers;
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers}; use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
@ -21,7 +21,7 @@ use msg::constellation_msg::{PipelineId, WorkerId};
use net_traits::ResourceTask; use net_traits::ResourceTask;
use js::{JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS}; use js::{JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS};
use js::glue::{GetGlobalForObjectCrossCompartment}; use js::jsapi::{GetGlobalForObjectCrossCompartment};
use js::jsapi::{JSContext, JSObject}; use js::jsapi::{JSContext, JSObject};
use js::jsapi::{JS_GetClass}; use js::jsapi::{JS_GetClass};
use url::Url; use url::Url;
@ -30,9 +30,9 @@ use url::Url;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum GlobalRef<'a> { pub enum GlobalRef<'a> {
/// A reference to a `Window` object. /// A reference to a `Window` object.
Window(JSRef<'a, window::Window>), Window(&'a window::Window),
/// A reference to a `WorkerGlobalScope` object. /// A reference to a `WorkerGlobalScope` object.
Worker(JSRef<'a, WorkerGlobalScope>), Worker(&'a WorkerGlobalScope),
} }
/// A stack-based rooted reference to a global object. /// A stack-based rooted reference to a global object.
@ -55,15 +55,6 @@ pub enum GlobalField {
Worker(JS<WorkerGlobalScope>), Worker(JS<WorkerGlobalScope>),
} }
/// An unrooted reference to a global object.
#[must_root]
pub enum GlobalUnrooted {
/// An unrooted reference to a `Window` object.
Window(Unrooted<window::Window>),
/// An unrooted reference to a `WorkerGlobalScope` object.
Worker(Unrooted<WorkerGlobalScope>),
}
impl<'a> GlobalRef<'a> { impl<'a> GlobalRef<'a> {
/// Get the `JSContext` for the `JSRuntime` associated with the thread /// Get the `JSContext` for the `JSRuntime` associated with the thread
/// this global object is on. /// this global object is on.
@ -76,7 +67,7 @@ impl<'a> GlobalRef<'a> {
/// Extract a `Window`, causing task failure if the global object is not /// Extract a `Window`, causing task failure if the global object is not
/// a `Window`. /// a `Window`.
pub fn as_window<'b>(&'b self) -> JSRef<'b, window::Window> { pub fn as_window<'b>(&'b self) -> &'b window::Window {
match *self { match *self {
GlobalRef::Window(window) => window, GlobalRef::Window(window) => window,
GlobalRef::Worker(_) => panic!("expected a Window scope"), GlobalRef::Worker(_) => panic!("expected a Window scope"),
@ -104,7 +95,7 @@ impl<'a> GlobalRef<'a> {
pub fn resource_task(&self) -> ResourceTask { pub fn resource_task(&self) -> ResourceTask {
match *self { match *self {
GlobalRef::Window(ref window) => { GlobalRef::Window(ref window) => {
let doc = window.Document().root(); let doc = window.Document();
let doc = doc.r(); let doc = doc.r();
let loader = doc.loader(); let loader = doc.loader();
loader.resource_task.clone() loader.resource_task.clone()
@ -182,8 +173,8 @@ impl GlobalField {
/// Create a new `GlobalField` from a rooted reference. /// Create a new `GlobalField` from a rooted reference.
pub fn from_rooted(global: &GlobalRef) -> GlobalField { pub fn from_rooted(global: &GlobalRef) -> GlobalField {
match *global { match *global {
GlobalRef::Window(window) => GlobalField::Window(JS::from_rooted(window)), GlobalRef::Window(window) => GlobalField::Window(JS::from_ref(window)),
GlobalRef::Worker(worker) => GlobalField::Worker(JS::from_rooted(worker)), GlobalRef::Worker(worker) => GlobalField::Worker(JS::from_ref(worker)),
} }
} }
@ -196,30 +187,20 @@ impl GlobalField {
} }
} }
impl GlobalUnrooted {
/// Create a stack-bounded root for this reference.
pub fn root(&self) -> GlobalRoot {
match *self {
GlobalUnrooted::Window(ref window) => GlobalRoot::Window(window.root()),
GlobalUnrooted::Worker(ref worker) => GlobalRoot::Worker(worker.root()),
}
}
}
/// Returns the global object of the realm that the given JS object was created in. /// Returns the global object of the realm that the given JS object was created in.
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn global_object_for_js_object(obj: *mut JSObject) -> GlobalUnrooted { pub fn global_object_for_js_object(obj: *mut JSObject) -> GlobalRoot {
unsafe { unsafe {
let global = GetGlobalForObjectCrossCompartment(obj); let global = GetGlobalForObjectCrossCompartment(obj);
let clasp = JS_GetClass(global); let clasp = JS_GetClass(global);
assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0); assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0);
match native_from_reflector_jsmanaged(global) { match native_from_reflector_jsmanaged(global) {
Ok(window) => return GlobalUnrooted::Window(window), Ok(window) => return GlobalRoot::Window(window),
Err(_) => (), Err(_) => (),
} }
match native_from_reflector_jsmanaged(global) { match native_from_reflector_jsmanaged(global) {
Ok(worker) => return GlobalUnrooted::Worker(worker), Ok(worker) => return GlobalRoot::Worker(worker),
Err(_) => (), Err(_) => (),
} }

View file

@ -11,178 +11,32 @@
//! //!
//! Here is a brief overview of the important types: //! Here is a brief overview of the important types:
//! //!
//! - `JSRef<T>`: a freely-copyable reference to a rooted DOM object.
//! - `Root<T>`: a stack-based reference to a rooted DOM object. //! - `Root<T>`: a stack-based reference to a rooted DOM object.
//! - `JS<T>`: a reference to a DOM object that can automatically be traced by //! - `JS<T>`: a reference to a DOM object that can automatically be traced by
//! the GC when encountered as a field of a Rust structure. //! the GC when encountered as a field of a Rust structure.
//! - `Temporary<T>`: a reference to a DOM object that will remain rooted for
//! the duration of its lifetime.
//! //!
//! The rule of thumb is as follows: //! `JS<T>` does not allow access to their inner value without explicitly
//! creating a stack-based root via the `root` method. This returns a `Root<T>`,
//! which causes the JS-owned value to be uncollectable for the duration of the
//! `Root` object's lifetime. A reference to the object can then be obtained
//! from the `Root` object. These references are not allowed to outlive their
//! originating `Root<T>`.
//! //!
//! - All methods return `Temporary<T>`, to ensure the value remains alive
//! until it is stored somewhere that is reachable by the GC.
//! - All functions take `JSRef<T>` arguments, to ensure that they will remain
//! uncollected for the duration of their usage.
//! - All DOM structs contain `JS<T>` fields and derive the `JSTraceable`
//! trait, to ensure that they are transitively marked as reachable by the GC
//! if the enclosing value is reachable.
//! - All methods for type `T` are implemented for `JSRef<T>`, to ensure that
//! the self value will not be collected for the duration of the method call.
//!
//! Both `Temporary<T>` and `JS<T>` do not allow access to their inner value
//! without explicitly creating a stack-based root via the `root` method
//! through the `Rootable<T>` trait. This returns a `Root<T>`, which causes the
//! JS-owned value to be uncollectable for the duration of the `Root` object's
//! lifetime. A `JSRef<T>` can be obtained from a `Root<T>` by calling the `r`
//! method. These `JSRef<T>` values are not allowed to outlive their
//! originating `Root<T>`, to ensure that all interactions with the enclosed
//! value only occur when said value is uncollectable, and will cause static
//! lifetime errors if misused.
//!
//! Other miscellaneous helper traits:
//!
//! - `OptionalRootable` and `OptionalOptionalRootable`: make rooting `Option`
//! values easy via a `root` method
//! - `ResultRootable`: make rooting successful `Result` values easy
//! - `TemporaryPushable`: allows mutating vectors of `JS<T>` with new elements
//! of `JSRef`/`Temporary`
//! - `RootedReference`: makes obtaining an `Option<JSRef<T>>` from an
//! `Option<Root<T>>` easy
use dom::bindings::trace::JSTraceable; use dom::bindings::trace::JSTraceable;
use dom::bindings::trace::RootedVec; use dom::bindings::trace::trace_reflector;
use dom::bindings::utils::{Reflector, Reflectable}; use dom::bindings::utils::{Reflector, Reflectable};
use dom::node::Node; use dom::node::Node;
use js::jsapi::JSObject; use js::jsapi::{JSObject, Heap, JSTracer};
use js::jsval::JSVal; use js::jsval::{JSVal, UndefinedValue};
use layout_interface::TrustedNodeAddress; use layout_interface::TrustedNodeAddress;
use script_task::STACK_ROOTS; use script_task::STACK_ROOTS;
use core::nonzero::NonZero; use core::nonzero::NonZero;
use libc;
use std::cell::{Cell, UnsafeCell}; use std::cell::{Cell, UnsafeCell};
use std::default::Default; use std::default::Default;
use std::intrinsics::return_address;
use std::marker::PhantomData;
use std::ops::Deref; use std::ops::Deref;
/// An unrooted, JS-owned value. Must not be held across a GC.
///
/// This is used in particular to wrap pointers extracted from a reflector.
#[must_root]
pub struct Unrooted<T> {
ptr: NonZero<*const T>
}
impl<T: Reflectable> Unrooted<T> {
/// Create a new JS-owned value wrapped from a raw Rust pointer.
pub unsafe fn from_raw(raw: *const T) -> Unrooted<T> {
assert!(!raw.is_null());
Unrooted {
ptr: NonZero::new(raw)
}
}
/// Create a new unrooted value from a `JS<T>`.
#[allow(unrooted_must_root)]
pub fn from_js(ptr: JS<T>) -> Unrooted<T> {
Unrooted {
ptr: ptr.ptr
}
}
/// Create a new unrooted value from a `Temporary<T>`.
#[allow(unrooted_must_root)]
pub fn from_temporary(ptr: Temporary<T>) -> Unrooted<T> {
Unrooted::from_js(ptr.inner)
}
/// Get the `Reflector` for this pointer.
pub fn reflector<'a>(&'a self) -> &'a Reflector {
unsafe {
(**self.ptr).reflector()
}
}
/// Returns an unsafe pointer to the interior of this object.
pub unsafe fn unsafe_get(&self) -> *const T {
*self.ptr
}
}
impl<T: Reflectable> Rootable<T> for Unrooted<T> {
/// Create a stack-bounded root for this value.
fn root(&self) -> Root<T> {
STACK_ROOTS.with(|ref collection| {
let RootCollectionPtr(collection) = collection.get().unwrap();
unsafe {
Root::new(&*collection, self.ptr)
}
})
}
}
impl<T> Copy for Unrooted<T> {}
impl<T> Clone for Unrooted<T> {
fn clone(&self) -> Unrooted<T> { *self }
}
/// A type that represents a JS-owned value that is rooted for the lifetime of
/// this value. Importantly, it requires explicit rooting in order to interact
/// with the inner value. Can be assigned into JS-owned member fields (i.e.
/// `JS<T>` types) safely via the `JS<T>::assign` method or
/// `OptionalSettable::assign` (for `Option<JS<T>>` fields).
#[allow(unrooted_must_root)]
pub struct Temporary<T> {
inner: JS<T>,
/// On-stack JS pointer to assuage conservative stack scanner
_js_ptr: *mut JSObject,
}
impl<T> Clone for Temporary<T> {
fn clone(&self) -> Temporary<T> {
Temporary {
inner: self.inner,
_js_ptr: self._js_ptr,
}
}
}
impl<T> PartialEq for Temporary<T> {
fn eq(&self, other: &Temporary<T>) -> bool {
self.inner == other.inner
}
}
impl<T: Reflectable> Temporary<T> {
/// Create a new `Temporary` value from an unrooted value.
#[allow(unrooted_must_root)]
pub fn from_unrooted(unrooted: Unrooted<T>) -> Temporary<T> {
Temporary {
inner: JS { ptr: unrooted.ptr },
_js_ptr: unrooted.reflector().get_jsobject(),
}
}
/// Create a new `Temporary` value from a rooted value.
#[allow(unrooted_must_root)]
pub fn from_rooted<U: Assignable<T>>(root: U) -> Temporary<T> {
let inner = JS::from_rooted(root);
Temporary {
inner: inner,
_js_ptr: inner.reflector().get_jsobject(),
}
}
}
impl<T: Reflectable> Rootable<T> for Temporary<T> {
/// Create a stack-bounded root for this value.
fn root(&self) -> Root<T> {
self.inner.root()
}
}
/// A traced reference to a DOM object. Must only be used as a field in other /// A traced reference to a DOM object. Must only be used as a field in other
/// DOM objects. /// DOM objects.
#[must_root] #[must_root]
@ -198,6 +52,32 @@ impl<T> JS<T> {
} }
} }
} }
impl<T: Reflectable> JS<T> {
/// Root this JS-owned value to prevent its collection as garbage.
pub fn root(&self) -> Root<T> {
Root::new(self.ptr)
}
/// Create a JS<T> from a Root<T>
/// XXX Not a great API. Should be a call on Root<T> instead
pub fn from_rooted(root: &Root<T>) -> JS<T> {
JS {
ptr: unsafe { NonZero::new(&**root) }
}
}
/// Create a JS<T> from a &T
pub fn from_ref(obj: &T) -> JS<T> {
JS {
ptr: unsafe { NonZero::new(&*obj) }
}
}
/// Store an rooted value in this field. This is safe under the
/// assumption that JS<T> values are only used as fields in DOM types that
/// are reachable in the GC graph, so this unrooted value becomes
/// transitively rooted for the lifetime of its new owner.
pub fn assign(&mut self, val: Root<T>) {
self.ptr = val.ptr.clone();
}
}
/// An unrooted reference to a DOM object for use in layout. `Layout*Helpers` /// An unrooted reference to a DOM object for use in layout. `Layout*Helpers`
/// traits must be implemented on this. /// traits must be implemented on this.
@ -208,7 +88,7 @@ pub struct LayoutJS<T> {
impl<T: Reflectable> LayoutJS<T> { impl<T: Reflectable> LayoutJS<T> {
/// Get the reflector. /// Get the reflector.
pub unsafe fn get_jsobject(&self) -> *mut JSObject { pub unsafe fn get_jsobject(&self) -> *mut JSObject {
(**self.ptr).reflector().get_jsobject() (**self.ptr).reflector().get_jsobject().get()
} }
} }
@ -217,14 +97,12 @@ impl<T> Copy for JS<T> {}
impl<T> Copy for LayoutJS<T> {} impl<T> Copy for LayoutJS<T> {}
impl<T> PartialEq for JS<T> { impl<T> PartialEq for JS<T> {
#[allow(unrooted_must_root)]
fn eq(&self, other: &JS<T>) -> bool { fn eq(&self, other: &JS<T>) -> bool {
self.ptr == other.ptr self.ptr == other.ptr
} }
} }
impl<T> PartialEq for LayoutJS<T> { impl<T> PartialEq for LayoutJS<T> {
#[allow(unrooted_must_root)]
fn eq(&self, other: &LayoutJS<T>) -> bool { fn eq(&self, other: &LayoutJS<T>) -> bool {
self.ptr == other.ptr self.ptr == other.ptr
} }
@ -260,29 +138,6 @@ impl LayoutJS<Node> {
} }
} }
impl<T: Reflectable> Rootable<T> for JS<T> {
/// Root this JS-owned value to prevent its collection as garbage.
fn root(&self) -> Root<T> {
STACK_ROOTS.with(|ref collection| {
let RootCollectionPtr(collection) = collection.get().unwrap();
unsafe {
Root::new(&*collection, self.ptr)
}
})
}
}
impl<U: Reflectable> JS<U> {
/// Create a `JS<T>` from any JS-managed pointer.
pub fn from_rooted<T: Assignable<U>>(root: T) -> JS<U> {
unsafe {
root.get_js()
}
}
}
//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> { impl<T: Reflectable> Reflectable for JS<T> {
fn reflector<'a>(&'a self) -> &'a Reflector { fn reflector<'a>(&'a self) -> &'a Reflector {
unsafe { unsafe {
@ -298,19 +153,50 @@ impl<T: Reflectable> Reflectable for JS<T> {
pub trait HeapGCValue: JSTraceable { pub trait HeapGCValue: JSTraceable {
} }
impl HeapGCValue for JSVal { impl HeapGCValue for Heap<JSVal> {
} }
impl<T: Reflectable> HeapGCValue for JS<T> { impl<T: Reflectable> HeapGCValue for JS<T> {
} }
/// A holder that provides interior mutability for GC-managed values such as /// A holder that provides interior mutability for GC-managed JSVals.
/// `JSVal` and `JS<T>`.
/// ///
/// Must be used in place of traditional interior mutability to ensure proper /// Must be used in place of traditional interior mutability to ensure proper
/// GC barriers are enforced. /// GC barriers are enforced.
#[must_root] #[must_root]
#[jstraceable] #[jstraceable]
pub struct MutHeapJSVal {
val: UnsafeCell<Heap<JSVal>>,
}
impl MutHeapJSVal {
/// Create a new `MutHeapJSVal`.
pub fn new() -> MutHeapJSVal {
MutHeapJSVal {
val: UnsafeCell::new(Heap::default()),
}
}
/// Set this `MutHeapJSVal` to the given value, calling write barriers as
/// appropriate.
pub fn set(&self, val: JSVal) {
unsafe {
let cell = self.val.get();
(*cell).set(val);
}
}
/// Set the value in this `MutHeapJSVal`, calling read barriers as appropriate.
pub fn get(&self) -> JSVal {
unsafe { (*self.val.get()).get() }
}
}
/// A holder that provides interior mutability for GC-managed values such as
/// `JS<T>`.
#[must_root]
#[jstraceable]
pub struct MutHeap<T: HeapGCValue+Copy> { pub struct MutHeap<T: HeapGCValue+Copy> {
val: Cell<T>, val: Cell<T>,
} }
@ -323,13 +209,12 @@ impl<T: HeapGCValue+Copy> MutHeap<T> {
} }
} }
/// Set this `MutHeap` to the given value, calling write barriers as /// Set this `MutHeap` to the given value.
/// appropriate.
pub fn set(&self, val: T) { pub fn set(&self, val: T) {
self.val.set(val) self.val.set(val)
} }
/// Set the value in this `MutHeap`, calling read barriers as appropriate. /// Set the value in this `MutHeap`.
pub fn get(&self) -> T { pub fn get(&self) -> T {
self.val.get() self.val.get()
} }
@ -353,8 +238,7 @@ impl<T: HeapGCValue+Copy> MutNullableHeap<T> {
} }
} }
/// Set this `MutNullableHeap` to the given value, calling write barriers /// Set this `MutNullableHeap` to the given value.
/// as appropriate.
pub fn set(&self, val: Option<T>) { pub fn set(&self, val: Option<T>) {
self.ptr.set(val); self.ptr.set(val);
} }
@ -368,14 +252,14 @@ impl<T: HeapGCValue+Copy> MutNullableHeap<T> {
impl<T: Reflectable> MutNullableHeap<JS<T>> { impl<T: Reflectable> MutNullableHeap<JS<T>> {
/// Retrieve a copy of the current inner value. If it is `None`, it is /// Retrieve a copy of the current inner value. If it is `None`, it is
/// initialized with the result of `cb` first. /// initialized with the result of `cb` first.
pub fn or_init<F>(&self, cb: F) -> Temporary<T> pub fn or_init<F>(&self, cb: F) -> Root<T>
where F: FnOnce() -> Temporary<T> where F: FnOnce() -> Root<T>
{ {
match self.get() { match self.get() {
Some(inner) => Temporary::from_rooted(inner), Some(inner) => Root::from_rooted(inner),
None => { None => {
let inner = cb(); let inner = cb();
self.set(Some(JS::from_rooted(inner.clone()))); self.set(Some(JS::from_rooted(&inner)));
inner inner
}, },
} }
@ -396,16 +280,6 @@ impl<T: HeapGCValue+Copy> Default for MutNullableHeap<T> {
} }
} }
impl<T: Reflectable> JS<T> {
/// Store an unrooted value in this field. This is safe under the
/// assumption that JS<T> values are only used as fields in DOM types that
/// are reachable in the GC graph, so this unrooted value becomes
/// transitively rooted for the lifetime of its new owner.
pub fn assign(&mut self, val: Temporary<T>) {
*self = val.inner.clone();
}
}
impl<T: Reflectable> LayoutJS<T> { impl<T: Reflectable> LayoutJS<T> {
/// Returns an unsafe pointer to the interior of this JS object. This is /// Returns an unsafe pointer to the interior of this JS object. This is
/// the only method that be safely accessed from layout. (The fact that /// the only method that be safely accessed from layout. (The fact that
@ -419,129 +293,36 @@ impl<T: Reflectable> LayoutJS<T> {
pub trait RootedReference<T> { pub trait RootedReference<T> {
/// Obtain a safe optional reference to the wrapped JS owned-value that /// Obtain a safe optional reference to the wrapped JS owned-value that
/// cannot outlive the lifetime of this root. /// cannot outlive the lifetime of this root.
fn r<'a>(&'a self) -> Option<JSRef<'a, T>>; fn r<'a>(&'a self) -> Option<&'a T>;
} }
impl<T: Reflectable> RootedReference<T> for Option<Root<T>> { impl<T: Reflectable> RootedReference<T> for Option<Root<T>> {
fn r<'a>(&'a self) -> Option<JSRef<'a, T>> { fn r<'a>(&'a self) -> Option<&'a T> {
self.as_ref().map(|root| root.r()) self.as_ref().map(|root| root.r())
} }
} }
/// Get an `Option<Option<JSRef<T>>>` out of an `Option<Option<Root<T>>>` /// Get an `Option<Option<&T>>` out of an `Option<Option<Root<T>>>`
pub trait OptionalRootedReference<T> { pub trait OptionalRootedReference<T> {
/// Obtain a safe optional optional reference to the wrapped JS owned-value /// Obtain a safe optional optional reference to the wrapped JS owned-value
/// that cannot outlive the lifetime of this root. /// that cannot outlive the lifetime of this root.
fn r<'a>(&'a self) -> Option<Option<JSRef<'a, T>>>; fn r<'a>(&'a self) -> Option<Option<&'a T>>;
} }
impl<T: Reflectable> OptionalRootedReference<T> for Option<Option<Root<T>>> { impl<T: Reflectable> OptionalRootedReference<T> for Option<Option<Root<T>>> {
fn r<'a>(&'a self) -> Option<Option<JSRef<'a, T>>> { fn r<'a>(&'a self) -> Option<Option<&'a T>> {
self.as_ref().map(|inner| inner.r()) self.as_ref().map(|inner| inner.r())
} }
} }
/// Trait that allows extracting a `JS<T>` value from a variety of /// A rooting mechanism for reflectors on the stack.
/// rooting-related containers, which in general is an unsafe operation since /// LIFO is not required.
/// they can outlive the rooted lifetime of the original value.
pub trait Assignable<T> {
/// Extract an unrooted `JS<T>`.
unsafe fn get_js(&self) -> JS<T>;
}
impl<T> Assignable<T> for JS<T> {
unsafe fn get_js(&self) -> JS<T> {
self.clone()
}
}
impl<'a, T: Reflectable> Assignable<T> for JSRef<'a, T> {
unsafe fn get_js(&self) -> JS<T> {
JS {
ptr: self.ptr
}
}
}
impl<T: Reflectable> Assignable<T> for Temporary<T> {
unsafe fn get_js(&self) -> JS<T> {
self.inner.clone()
}
}
/// Root a rootable `Option` type (used for `Option<Temporary<T>>`)
pub trait OptionalRootable<T> {
/// Root the inner value, if it exists.
fn root(&self) -> Option<Root<T>>;
}
impl<T: Reflectable, U: Rootable<T>> OptionalRootable<T> for Option<U> {
fn root(&self) -> Option<Root<T>> {
self.as_ref().map(|inner| inner.root())
}
}
/// Root a rootable `Option<Option>` type (used for `Option<Option<JS<T>>>`)
pub trait OptionalOptionalRootable<T> {
/// Root the inner value, if it exists.
fn root(&self) -> Option<Option<Root<T>>>;
}
impl<T: Reflectable, U: OptionalRootable<T>> OptionalOptionalRootable<T> for Option<U> {
fn root(&self) -> Option<Option<Root<T>>> {
self.as_ref().map(|inner| inner.root())
}
}
/// Root a rootable `Result` type (any of `Temporary<T>` or `JS<T>`)
pub trait ResultRootable<T,U> {
/// Root the inner value, if it exists.
fn root(self) -> Result<Root<T>, U>;
}
impl<T: Reflectable, U, V: Rootable<T>> ResultRootable<T, U> for Result<V, U> {
fn root(self) -> Result<Root<T>, U> {
self.map(|inner| inner.root())
}
}
/// Root a rootable type.
pub trait Rootable<T> {
/// Root the value.
fn root(&self) -> Root<T>;
}
/// Provides a facility to push unrooted values onto lists of rooted values.
/// This is safe under the assumption that said lists are reachable via the GC
/// graph, and therefore the new values are transitively rooted for the
/// lifetime of their new owner.
pub trait TemporaryPushable<T> {
/// Push a new value onto this container.
fn push_unrooted(&mut self, val: &T);
/// Insert a new value into this container.
fn insert_unrooted(&mut self, index: usize, val: &T);
}
impl<T: Assignable<U>, U: Reflectable> TemporaryPushable<T> for Vec<JS<U>> {
fn push_unrooted(&mut self, val: &T) {
self.push(unsafe { val.get_js() });
}
fn insert_unrooted(&mut self, index: usize, val: &T) {
self.insert(index, unsafe { val.get_js() });
}
}
/// An opaque, LIFO rooting mechanism. This tracks roots and ensures that they
/// are destructed in a LIFO order.
/// ///
/// See also [*Exact Stack Rooting - Storing a GCPointer on the CStack*] /// See also [*Exact Stack Rooting - Storing a GCPointer on the CStack*]
/// (https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/GC/Exact_Stack_Rooting). /// (https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/GC/Exact_Stack_Rooting).
#[no_move] #[no_move]
pub struct RootCollection { pub struct RootCollection {
roots: UnsafeCell<RootedVec<*mut JSObject>>, roots: UnsafeCell<Vec<*const Reflector>>,
} }
/// A pointer to a RootCollection, for use in global variables. /// A pointer to a RootCollection, for use in global variables.
@ -555,142 +336,114 @@ impl Clone for RootCollectionPtr {
impl RootCollection { impl RootCollection {
/// Create an empty collection of roots /// Create an empty collection of roots
pub fn new() -> RootCollection { pub fn new() -> RootCollection {
let addr = unsafe {
return_address() as *const libc::c_void
};
RootCollection { RootCollection {
roots: UnsafeCell::new(RootedVec::new_with_destination_address(addr)), roots: UnsafeCell::new(vec!()),
} }
} }
/// Track a stack-based root as a pointer to ensure LIFO root ordering. /// Start tracking a stack-based root
fn root<'b>(&self, untracked_js_ptr: *mut JSObject) { fn root<'b>(&self, untracked_reflector: *const Reflector) {
unsafe { unsafe {
let roots = self.roots.get(); let mut roots = &mut *self.roots.get();
(*roots).push(untracked_js_ptr); roots.push(untracked_reflector);
debug!(" rooting {:?}", untracked_js_ptr); assert!(!(*untracked_reflector).get_jsobject().is_null())
} }
} }
/// Stop tracking a stack-based root, asserting if LIFO root ordering has /// Stop tracking a stack-based root, asserting if the reflector isn't found
/// been violated
fn unroot<'b, T: Reflectable>(&self, rooted: &Root<T>) { fn unroot<'b, T: Reflectable>(&self, rooted: &Root<T>) {
unsafe { unsafe {
let roots = self.roots.get(); let mut roots = &mut *self.roots.get();
let unrooted = (*roots).pop().unwrap(); let old_reflector = &*rooted.r().reflector();
debug!("unrooted {:?} (expecting {:?}", unrooted, rooted.js_ptr); match roots.iter().rposition(|r| *r == old_reflector) {
assert!(unrooted == rooted.js_ptr); Some(idx) => {
roots.remove(idx);
},
None => panic!("Can't remove a root that was never rooted!")
}
} }
} }
} }
/// SM Callback that traces the rooted reflectors
pub unsafe fn trace_roots(tracer: *mut JSTracer) {
STACK_ROOTS.with(|ref collection| {
let RootCollectionPtr(collection) = collection.get().unwrap();
let collection = &*(*collection).roots.get();
for root in collection.iter() {
trace_reflector(tracer, "reflector", &**root);
}
});
}
/// A rooted reference to a DOM object. /// A rooted reference to a DOM object.
/// ///
/// The JS value is pinned for the duration of this object's lifetime; roots /// The JS value is pinned for the duration of this object's lifetime; roots
/// are additive, so this object's destruction will not invalidate other roots /// are additive, so this object's destruction will not invalidate other roots
/// for the same JS value. `Root`s cannot outlive the associated /// for the same JS value. `Root`s cannot outlive the associated
/// `RootCollection` object. Attempts to transfer ownership of a `Root` via /// `RootCollection` object.
/// moving will trigger dynamic unrooting failures due to incorrect ordering.
#[no_move]
pub struct Root<T: Reflectable> { pub struct Root<T: Reflectable> {
/// List that ensures correct dynamic root ordering
root_list: &'static RootCollection,
/// Reference to rooted value that must not outlive this container /// Reference to rooted value that must not outlive this container
ptr: NonZero<*const T>, ptr: NonZero<*const T>,
/// On-stack JS pointer to assuage conservative stack scanner /// List that ensures correct dynamic root ordering
js_ptr: *mut JSObject, root_list: *const RootCollection,
} }
impl<T: Reflectable> Root<T> { impl<T: Reflectable> Root<T> {
/// Create a new stack-bounded root for the provided JS-owned value. /// Create a new stack-bounded root for the provided JS-owned value.
/// It cannot not outlive its associated `RootCollection`, and it contains /// It cannot not outlive its associated `RootCollection`, and it gives
/// a `JSRef` which cannot outlive this new `Root`. /// out references which cannot outlive this new `Root`.
#[inline] pub fn new(unrooted: NonZero<*const T>)
fn new(roots: &'static RootCollection, unrooted: NonZero<*const T>) -> Root<T> {
-> Root<T> { STACK_ROOTS.with(|ref collection| {
let js_ptr = unsafe { let RootCollectionPtr(collection) = collection.get().unwrap();
(**unrooted).reflector().get_jsobject() unsafe { (*collection).root(&*(**unrooted).reflector()) }
}; Root {
roots.root(js_ptr); ptr: unrooted,
Root { root_list: collection,
root_list: roots, }
ptr: unrooted, })
js_ptr: js_ptr, }
}
/// Generate a new root from a reference
pub fn from_ref(unrooted: &T) -> Root<T> {
Root::new(unsafe { NonZero::new(&*unrooted) })
} }
/// Obtain a safe reference to the wrapped JS owned-value that cannot /// Obtain a safe reference to the wrapped JS owned-value that cannot
/// outlive the lifetime of this root. /// outlive the lifetime of this root.
pub fn r<'b>(&'b self) -> JSRef<'b, T> { pub fn r<'a>(&'a self) -> &'a T {
JSRef { &**self
ptr: self.ptr,
chain: PhantomData,
}
} }
/// Obtain an unsafe reference to the wrapped JS owned-value that can /// Don't use this. Don't make me find you.
/// outlive the lifetime of this root. pub fn get_unsound_ref_forever<'a, 'b>(&'a self) -> &'b T {
/// unsafe { &**self.ptr }
/// DO NOT CALL. }
pub fn get_unsound_ref_forever<'b>(&self) -> JSRef<'b, T> {
JSRef { /// Generate a new root from a JS<T> reference
ptr: self.ptr, #[allow(unrooted_must_root)]
chain: PhantomData, pub fn from_rooted(js: JS<T>) -> Root<T> {
} js.root()
}
}
impl<T: Reflectable> Deref for Root<T> {
type Target = T;
fn deref<'a>(&'a self) -> &'a T {
unsafe { &**self.ptr.deref() }
}
}
impl<T: Reflectable> PartialEq for Root<T> {
fn eq(&self, other: &Root<T>) -> bool {
self.ptr == other.ptr
} }
} }
impl<T: Reflectable> Drop for Root<T> { impl<T: Reflectable> Drop for Root<T> {
fn drop(&mut self) { fn drop(&mut self) {
self.root_list.unroot(self); unsafe { (*self.root_list).unroot(self); }
} }
} }
impl<'a, T: Reflectable> Deref for JSRef<'a, T> {
type Target = T;
fn deref<'b>(&'b self) -> &'b T {
unsafe {
&**self.ptr
}
}
}
/// A reference to a DOM object that is guaranteed to be alive. This is freely
/// copyable.
pub struct JSRef<'a, T> {
ptr: NonZero<*const T>,
chain: PhantomData<&'a ()>,
}
impl<'a, T> Copy for JSRef<'a, T> {}
impl<'a, T> Clone for JSRef<'a, T> {
fn clone(&self) -> JSRef<'a, T> {
JSRef {
ptr: self.ptr.clone(),
chain: self.chain,
}
}
}
impl<'a, 'b, T> PartialEq<JSRef<'b, T>> for JSRef<'a, T> {
fn eq(&self, other: &JSRef<T>) -> bool {
self.ptr == other.ptr
}
}
impl<'a, T: Reflectable> JSRef<'a, T> {
/// Returns the inner pointer directly.
pub fn extended_deref(self) -> &'a T {
unsafe {
&**self.ptr
}
}
}
impl<'a, T: Reflectable> Reflectable for JSRef<'a, T> {
fn reflector<'b>(&'b self) -> &'b Reflector {
(**self).reflector()
}
}

View file

@ -8,18 +8,19 @@
use dom::bindings::conversions::is_dom_proxy; use dom::bindings::conversions::is_dom_proxy;
use dom::bindings::utils::delete_property_by_id; use dom::bindings::utils::delete_property_by_id;
use js::jsapi::{JSContext, jsid, JSPropertyDescriptor, JSObject, JSString}; use js::jsapi::{JSContext, JSPropertyDescriptor, JSObject, JSString};
use js::jsapi::{JS_GetPropertyDescriptorById, JS_NewStringCopyN}; use js::jsapi::{JS_GetPropertyDescriptorById, JS_NewStringCopyN};
use js::jsapi::{JS_DefinePropertyById, JS_NewObjectWithGivenProto}; use js::jsapi::{JS_DefinePropertyById6, JS_NewObjectWithGivenProto};
use js::jsapi::{JS_ReportErrorFlagsAndNumber, JS_StrictPropertyStub}; use js::jsapi::{JS_StrictPropertyStub, JSErrNum};
use js::jsapi::{JSREPORT_WARNING, JSREPORT_STRICT, JSREPORT_STRICT_MODE_ERROR}; use js::jsapi::{Handle, HandleObject, HandleId, MutableHandle, RootedObject, ObjectOpResult};
use js::jsapi::AutoIdVector;
use js::jsapi::GetObjectProto;
use js::jsval::ObjectValue; use js::jsval::ObjectValue;
use js::glue::GetProxyExtra; use js::glue::GetProxyExtra;
use js::glue::{GetObjectProto, GetObjectParent, SetProxyExtra, GetProxyHandler}; use js::glue::{SetProxyExtra, GetProxyHandler};
use js::glue::InvokeGetOwnPropertyDescriptor; use js::glue::InvokeGetOwnPropertyDescriptor;
use js::glue::RUST_js_GetErrorMessage; use js::{JSPROP_GETTER, JSPROP_ENUMERATE, JSPROP_READONLY};
use js::glue::AutoIdVector; use js::{JSTrue, JSFalse};
use js::{JSPROP_GETTER, JSPROP_ENUMERATE, JSPROP_READONLY, JSRESOLVE_QUALIFIED};
use libc; use libc;
use std::mem; use std::mem;
@ -32,60 +33,78 @@ static JSPROXYSLOT_EXPANDO: u32 = 0;
/// Otherwise, walk along the prototype chain to find a property with that /// Otherwise, walk along the prototype chain to find a property with that
/// name. /// name.
pub unsafe extern fn get_property_descriptor(cx: *mut JSContext, pub unsafe extern fn get_property_descriptor(cx: *mut JSContext,
proxy: *mut JSObject, proxy: HandleObject,
id: jsid, set: bool, id: HandleId,
desc: *mut JSPropertyDescriptor) desc: MutableHandle<JSPropertyDescriptor>)
-> bool { -> u8 {
let handler = GetProxyHandler(proxy); let handler = GetProxyHandler(proxy.get());
if !InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, set, desc) { if InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) == 0 {
return false; return JSFalse;
} }
if !(*desc).obj.is_null() { if !desc.get().obj.is_null() {
return true; return JSTrue;
} }
//let proto = JS_GetPrototype(proxy); let mut proto = RootedObject::new(cx, ptr::null_mut());
let proto = GetObjectProto(proxy); if GetObjectProto(cx, proxy, proto.handle_mut()) == 0 {
if proto.is_null() { desc.get().obj = ptr::null_mut();
(*desc).obj = ptr::null_mut(); return JSTrue;
return true;
} }
JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, desc) != 0 JS_GetPropertyDescriptorById(cx, proto.handle(), id, desc)
} }
/// Defines an expando on the given `proxy`. /// Defines an expando on the given `proxy`.
pub unsafe extern fn define_property(cx: *mut JSContext, proxy: *mut JSObject, pub unsafe extern fn define_property(cx: *mut JSContext, proxy: HandleObject,
id: jsid, desc: *mut JSPropertyDescriptor) id: HandleId, desc: Handle<JSPropertyDescriptor>,
-> bool { result: *mut ObjectOpResult)
static JSMSG_GETTER_ONLY: libc::c_uint = 160; -> u8 {
//FIXME: Workaround for https://github.com/mozilla/rust/issues/13385 //FIXME: Workaround for https://github.com/mozilla/rust/issues/13385
let setter: *const libc::c_void = mem::transmute((*desc).setter); let setter: *const libc::c_void = mem::transmute(desc.get().setter);
let setter_stub: *const libc::c_void = mem::transmute(JS_StrictPropertyStub); let setter_stub: *const libc::c_void = mem::transmute(JS_StrictPropertyStub);
if ((*desc).attrs & JSPROP_GETTER) != 0 && setter == setter_stub { if (desc.get().attrs & JSPROP_GETTER) != 0 && setter == setter_stub {
return JS_ReportErrorFlagsAndNumber(cx, (*result).code_ = JSErrNum::JSMSG_GETTER_ONLY as u32;
JSREPORT_WARNING | JSREPORT_STRICT | return JSTrue;
JSREPORT_STRICT_MODE_ERROR,
Some(RUST_js_GetErrorMessage), ptr::null_mut(),
JSMSG_GETTER_ONLY) != 0;
} }
let expando = ensure_expando_object(cx, proxy); let expando = RootedObject::new(cx, ensure_expando_object(cx, proxy));
return JS_DefinePropertyById(cx, expando, id, (*desc).value, (*desc).getter, JS_DefinePropertyById6(cx, expando.handle(), id, desc, result)
(*desc).setter, (*desc).attrs) != 0;
} }
/// Deletes an expando off the given `proxy`. /// Deletes an expando off the given `proxy`.
pub unsafe extern fn delete(cx: *mut JSContext, proxy: *mut JSObject, id: jsid, pub unsafe extern fn delete(cx: *mut JSContext, proxy: HandleObject, id: HandleId,
bp: *mut bool) -> bool { bp: *mut ObjectOpResult) -> u8 {
let expando = get_expando_object(proxy); let expando = RootedObject::new(cx, get_expando_object(proxy));
if expando.is_null() { if expando.ptr.is_null() {
*bp = true; (*bp).code_ = 0 /* OkCode */;
return true; return JSTrue;
} }
return delete_property_by_id(cx, expando, id, &mut *bp); delete_property_by_id(cx, expando.handle(), id, bp)
}
/// Stub for ownPropertyKeys
pub unsafe extern fn own_property_keys(cx: *mut JSContext,
proxy: HandleObject,
props: *mut AutoIdVector) -> u8 {
// FIXME: implement this
// https://github.com/servo/servo/issues/6390
JSTrue
}
/// Controls whether the Extensible bit can be changed
pub unsafe extern fn prevent_extensions(_cx: *mut JSContext,
_proxy: HandleObject,
result: *mut ObjectOpResult) -> u8 {
(*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as u32;
return JSTrue;
}
/// Reports whether the object is Extensible
pub unsafe extern fn is_extensible(_cx: *mut JSContext, _proxy: HandleObject,
succeeded: *mut u8) -> u8 {
*succeeded = JSTrue;
return JSTrue;
} }
/// Returns the stringification of an object with class `name`. /// Returns the stringification of an object with class `name`.
@ -103,10 +122,10 @@ pub fn object_to_string(cx: *mut JSContext, name: &str) -> *mut JSString {
} }
/// Get the expando object, or null if there is none. /// Get the expando object, or null if there is none.
pub fn get_expando_object(obj: *mut JSObject) -> *mut JSObject { pub fn get_expando_object(obj: HandleObject) -> *mut JSObject {
unsafe { unsafe {
assert!(is_dom_proxy(obj)); assert!(is_dom_proxy(obj.get()));
let val = GetProxyExtra(obj, JSPROXYSLOT_EXPANDO); let val = GetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO);
if val.is_undefined() { if val.is_undefined() {
ptr::null_mut() ptr::null_mut()
} else { } else {
@ -117,18 +136,16 @@ pub fn get_expando_object(obj: *mut JSObject) -> *mut JSObject {
/// Get the expando object, or create it if it doesn't exist yet. /// Get the expando object, or create it if it doesn't exist yet.
/// Fails on JSAPI failure. /// Fails on JSAPI failure.
pub fn ensure_expando_object(cx: *mut JSContext, obj: *mut JSObject) pub fn ensure_expando_object(cx: *mut JSContext, obj: HandleObject)
-> *mut JSObject { -> *mut JSObject {
unsafe { unsafe {
assert!(is_dom_proxy(obj)); assert!(is_dom_proxy(obj.get()));
let mut expando = get_expando_object(obj); let mut expando = get_expando_object(obj);
if expando.is_null() { if expando.is_null() {
expando = JS_NewObjectWithGivenProto(cx, ptr::null_mut(), expando = JS_NewObjectWithGivenProto(cx, ptr::null_mut(), HandleObject::null());
ptr::null_mut(),
GetObjectParent(obj));
assert!(!expando.is_null()); assert!(!expando.is_null());
SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(&*expando)); SetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO, ObjectValue(&*expando));
} }
return expando; return expando;
} }
@ -142,18 +159,4 @@ pub fn fill_property_descriptor(desc: &mut JSPropertyDescriptor,
desc.attrs = if readonly { JSPROP_READONLY } else { 0 } | JSPROP_ENUMERATE; desc.attrs = if readonly { JSPROP_READONLY } else { 0 } | JSPROP_ENUMERATE;
desc.getter = None; desc.getter = None;
desc.setter = None; desc.setter = None;
desc.shortid = 0;
}
/// No-op required hook.
pub unsafe extern fn get_own_property_names(_cx: *mut JSContext,
_obj: *mut JSObject,
_v: *mut AutoIdVector) -> bool {
true
}
/// No-op required hook.
pub unsafe extern fn enumerate(_cx: *mut JSContext, _obj: *mut JSObject,
_v: *mut AutoIdVector) -> bool {
true
} }

View file

@ -22,11 +22,12 @@
//! is rooted when a hashmap entry is first created, and unrooted when the hashmap entry //! is rooted when a hashmap entry is first created, and unrooted when the hashmap entry
//! is removed. //! is removed.
use dom::bindings::js::{Temporary, JSRef, Unrooted}; use dom::bindings::js::Root;
use dom::bindings::utils::{Reflector, Reflectable}; use dom::bindings::utils::{Reflector, Reflectable};
use dom::bindings::trace::trace_reflector;
use script_task::{ScriptMsg, ScriptChan}; use script_task::{ScriptMsg, ScriptChan};
use js::jsapi::{JS_AddObjectRoot, JS_RemoveObjectRoot, JSContext}; use js::jsapi::{JSContext, JSTracer};
use libc; use libc;
use std::cell::RefCell; use std::cell::RefCell;
@ -35,6 +36,7 @@ use std::collections::hash_map::Entry::{Vacant, Occupied};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use core::nonzero::NonZero;
thread_local!(pub static LIVE_REFERENCES: Rc<RefCell<Option<LiveDOMReferences>>> = Rc::new(RefCell::new(None))); thread_local!(pub static LIVE_REFERENCES: Rc<RefCell<Option<LiveDOMReferences>>> = Rc::new(RefCell::new(None)));
@ -63,7 +65,7 @@ impl<T: Reflectable> Trusted<T> {
/// Create a new `Trusted<T>` instance from an existing DOM pointer. The DOM object will /// Create a new `Trusted<T>` instance from an existing DOM pointer. The DOM object will
/// be prevented from being GCed for the duration of the resulting `Trusted<T>` object's /// be prevented from being GCed for the duration of the resulting `Trusted<T>` object's
/// lifetime. /// lifetime.
pub fn new(cx: *mut JSContext, ptr: JSRef<T>, script_chan: Box<ScriptChan + Send>) -> Trusted<T> { pub fn new(cx: *mut JSContext, ptr: &T, script_chan: Box<ScriptChan + Send>) -> Trusted<T> {
LIVE_REFERENCES.with(|ref r| { LIVE_REFERENCES.with(|ref r| {
let r = r.borrow(); let r = r.borrow();
let live_references = r.as_ref().unwrap(); let live_references = r.as_ref().unwrap();
@ -81,14 +83,14 @@ impl<T: Reflectable> Trusted<T> {
/// Obtain a usable DOM pointer from a pinned `Trusted<T>` value. Fails if used on /// Obtain a usable DOM pointer from a pinned `Trusted<T>` value. Fails if used on
/// a different thread than the original value from which this `Trusted<T>` was /// a different thread than the original value from which this `Trusted<T>` was
/// obtained. /// obtained.
pub fn to_temporary(&self) -> Temporary<T> { pub fn root(&self) -> Root<T> {
assert!(LIVE_REFERENCES.with(|ref r| { assert!(LIVE_REFERENCES.with(|ref r| {
let r = r.borrow(); let r = r.borrow();
let live_references = r.as_ref().unwrap(); let live_references = r.as_ref().unwrap();
self.owner_thread == (&*live_references) as *const _ as *const libc::c_void self.owner_thread == (&*live_references) as *const _ as *const libc::c_void
})); }));
unsafe { unsafe {
Temporary::from_unrooted(Unrooted::from_raw(self.ptr as *const T)) Root::new(NonZero::new(self.ptr as *const T))
} }
} }
} }
@ -151,10 +153,6 @@ impl LiveDOMReferences {
refcount.clone() refcount.clone()
} }
Vacant(entry) => { Vacant(entry) => {
unsafe {
let rootable = (*ptr).reflector().rootable();
JS_AddObjectRoot(cx, rootable);
}
let refcount = Arc::new(Mutex::new(1)); let refcount = Arc::new(Mutex::new(1));
entry.insert(refcount.clone()); entry.insert(refcount.clone());
refcount refcount
@ -168,7 +166,6 @@ impl LiveDOMReferences {
LIVE_REFERENCES.with(|ref r| { LIVE_REFERENCES.with(|ref r| {
let r = r.borrow(); let r = r.borrow();
let live_references = r.as_ref().unwrap(); let live_references = r.as_ref().unwrap();
let reflectable = raw_reflectable as *const Reflector;
let mut table = live_references.table.borrow_mut(); let mut table = live_references.table.borrow_mut();
match table.entry(raw_reflectable) { match table.entry(raw_reflectable) {
Occupied(entry) => { Occupied(entry) => {
@ -178,9 +175,6 @@ impl LiveDOMReferences {
return; return;
} }
unsafe {
JS_RemoveObjectRoot(cx, (*reflectable).rootable());
}
let _ = entry.remove(); let _ = entry.remove();
} }
Vacant(_) => { Vacant(_) => {
@ -194,3 +188,16 @@ impl LiveDOMReferences {
}) })
} }
} }
/// A JSTraceDataOp for tracing reflectors held in LIVE_REFERENCES
pub unsafe extern fn trace_refcounted_objects(tracer: *mut JSTracer, _data: *mut libc::c_void) {
LIVE_REFERENCES.with(|ref r| {
let r = r.borrow();
let live_references = r.as_ref().unwrap();
let table = live_references.table.borrow();
for obj in table.keys() {
let reflectable = &*(*obj as *const Reflector);
trace_reflector(tracer, "LIVE_REFERENCES", reflectable);
}
});
}

View file

@ -13,7 +13,7 @@ use js::glue::JS_STRUCTURED_CLONE_VERSION;
use js::jsapi::JSContext; use js::jsapi::JSContext;
use js::jsapi::{JS_WriteStructuredClone, JS_ClearPendingException}; use js::jsapi::{JS_WriteStructuredClone, JS_ClearPendingException};
use js::jsapi::JS_ReadStructuredClone; use js::jsapi::JS_ReadStructuredClone;
use js::jsval::{JSVal, UndefinedValue}; use js::jsapi::{HandleValue, MutableHandleValue};
use libc::size_t; use libc::size_t;
use std::ptr; use std::ptr;
@ -26,13 +26,14 @@ pub struct StructuredCloneData {
impl StructuredCloneData { impl StructuredCloneData {
/// Writes a structured clone. Returns a `DataClone` error if that fails. /// Writes a structured clone. Returns a `DataClone` error if that fails.
pub fn write(cx: *mut JSContext, message: JSVal) pub fn write(cx: *mut JSContext, message: HandleValue)
-> Fallible<StructuredCloneData> { -> Fallible<StructuredCloneData> {
let mut data = ptr::null_mut(); let mut data = ptr::null_mut();
let mut nbytes = 0; let mut nbytes = 0;
let result = unsafe { let result = unsafe {
JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes, JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes,
ptr::null(), ptr::null_mut()) ptr::null(), ptr::null_mut(),
HandleValue::undefined())
}; };
if result == 0 { if result == 0 {
unsafe { JS_ClearPendingException(cx); } unsafe { JS_ClearPendingException(cx); }
@ -47,15 +48,13 @@ impl StructuredCloneData {
/// Reads a structured clone. /// Reads a structured clone.
/// ///
/// Panics if `JS_ReadStructuredClone` fails. /// Panics if `JS_ReadStructuredClone` fails.
pub fn read(self, global: GlobalRef) -> JSVal { pub fn read(self, global: GlobalRef, rval: MutableHandleValue) {
let mut message = UndefinedValue();
unsafe { unsafe {
assert!(JS_ReadStructuredClone( assert!(JS_ReadStructuredClone(
global.get_cx(), self.data as *const u64, self.nbytes, global.get_cx(), self.data, self.nbytes,
JS_STRUCTURED_CLONE_VERSION, &mut message, JS_STRUCTURED_CLONE_VERSION, rval,
ptr::null(), ptr::null_mut()) != 0); ptr::null(), ptr::null_mut()) != 0);
} }
message
} }
} }

View file

@ -44,7 +44,8 @@ use euclid::size::Size2D;
use html5ever::tree_builder::QuirksMode; use html5ever::tree_builder::QuirksMode;
use hyper::header::Headers; use hyper::header::Headers;
use hyper::method::Method; use hyper::method::Method;
use js::jsapi::{JSObject, JSTracer, JS_CallTracer, JSGCTraceKind}; use js::jsapi::{JSObject, JSTracer, JSGCTraceKind, JS_CallValueTracer, JS_CallObjectTracer, GCTraceKindToAscii, Heap};
use js::jsapi::JS_CallUnbarrieredObjectTracer;
use js::jsval::JSVal; use js::jsval::JSVal;
use js::rust::Runtime; use js::rust::Runtime;
use layout_interface::{LayoutRPC, LayoutChan}; use layout_interface::{LayoutRPC, LayoutChan};
@ -59,7 +60,7 @@ use msg::compositor_msg::ScriptListener;
use msg::constellation_msg::ConstellationChan; use msg::constellation_msg::ConstellationChan;
use net_traits::image::base::Image; use net_traits::image::base::Image;
use util::str::{LengthOrPercentageOrAuto}; use util::str::{LengthOrPercentageOrAuto};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, UnsafeCell, RefCell};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::collections::hash_state::HashState; use std::collections::hash_state::HashState;
use std::ffi::CString; use std::ffi::CString;
@ -91,36 +92,46 @@ no_jsmanaged_fields!(EncodingRef);
no_jsmanaged_fields!(Reflector); no_jsmanaged_fields!(Reflector);
/// Trace a `JSVal`. /// Trace a `JSVal`.
pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: JSVal) { pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap<JSVal>) {
if !val.is_markable() {
return;
}
unsafe { unsafe {
if !val.get().is_markable() {
return;
}
let name = CString::new(description).unwrap(); let name = CString::new(description).unwrap();
(*tracer).debugPrinter = None; (*tracer).debugPrinter_ = None;
(*tracer).debugPrintIndex = !0; (*tracer).debugPrintIndex_ = !0;
(*tracer).debugPrintArg = name.as_ptr() as *const libc::c_void; (*tracer).debugPrintArg_ = name.as_ptr() as *const libc::c_void;
debug!("tracing value {}", description); debug!("tracing value {}", description);
JS_CallTracer(tracer, val.to_gcthing(), val.trace_kind()); JS_CallValueTracer(tracer, val.ptr.get() as *mut _,
GCTraceKindToAscii(val.get().trace_kind()));
} }
} }
/// Trace the `JSObject` held by `reflector`. /// Trace the `JSObject` held by `reflector`.
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Reflector) { pub fn trace_reflector(tracer: *mut JSTracer, description: &str, reflector: &Reflector) {
trace_object(tracer, description, reflector.get_jsobject()) unsafe {
let name = CString::new(description).unwrap();
(*tracer).debugPrinter_ = None;
(*tracer).debugPrintIndex_ = !0;
(*tracer).debugPrintArg_ = name.as_ptr() as *const libc::c_void;
debug!("tracing reflector {}", description);
JS_CallUnbarrieredObjectTracer(tracer, reflector.rootable(),
GCTraceKindToAscii(JSGCTraceKind::JSTRACE_OBJECT));
}
} }
/// Trace a `JSObject`. /// Trace a `JSObject`.
pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: *mut JSObject) { pub fn trace_object(tracer: *mut JSTracer, description: &str, obj: &Heap<*mut JSObject>) {
unsafe { unsafe {
let name = CString::new(description).unwrap(); let name = CString::new(description).unwrap();
(*tracer).debugPrinter = None; (*tracer).debugPrinter_ = None;
(*tracer).debugPrintIndex = !0; (*tracer).debugPrintIndex_ = !0;
(*tracer).debugPrintArg = name.as_ptr() as *const libc::c_void; (*tracer).debugPrintArg_ = name.as_ptr() as *const libc::c_void;
debug!("tracing {}", description); debug!("tracing {}", description);
JS_CallTracer(tracer, obj as *mut libc::c_void, JSGCTraceKind::JSTRACE_OBJECT); JS_CallObjectTracer(tracer, obj.ptr.get() as *mut _,
GCTraceKindToAscii(JSGCTraceKind::JSTRACE_OBJECT));
} }
} }
@ -168,15 +179,26 @@ impl<T: JSTraceable+Copy> JSTraceable for Cell<T> {
} }
} }
impl JSTraceable for *mut JSObject { impl<T: JSTraceable> JSTraceable for UnsafeCell<T> {
fn trace(&self, trc: *mut JSTracer) { fn trace(&self, trc: *mut JSTracer) {
trace_object(trc, "object", *self); unsafe { (*self.get()).trace(trc) }
} }
} }
impl JSTraceable for JSVal {
impl JSTraceable for Heap<*mut JSObject> {
fn trace(&self, trc: *mut JSTracer) { fn trace(&self, trc: *mut JSTracer) {
trace_jsval(trc, "val", *self); if self.get().is_null() {
return;
}
trace_object(trc, "object", self);
}
}
impl JSTraceable for Heap<JSVal> {
fn trace(&self, trc: *mut JSTracer) {
trace_jsval(trc, "val", self);
} }
} }
@ -324,115 +346,101 @@ impl JSTraceable for () {
} }
} }
/// Holds a set of vectors that need to be rooted /// Homemade trait object for JSTraceable things
pub struct RootedCollectionSet { struct TraceableInfo {
set: Vec<HashSet<*const RootedVec<Void>>> pub ptr: *const libc::c_void,
pub trace: fn(obj: *const libc::c_void, tracer: *mut JSTracer)
} }
/// TLV Holds a set of vectors that need to be rooted /// Holds a set of JSTraceables that need to be rooted
thread_local!(pub static ROOTED_COLLECTIONS: Rc<RefCell<RootedCollectionSet>> = pub struct RootedTraceableSet {
Rc::new(RefCell::new(RootedCollectionSet::new()))); set: Vec<TraceableInfo>
/// Type of `RootedVec`
pub enum CollectionType {
/// DOM objects
DOMObjects,
/// `JSVal`s
JSVals,
/// `*mut JSObject`s
JSObjects,
} }
/// TLV Holds a set of JSTraceables that need to be rooted
thread_local!(pub static ROOTED_TRACEABLES: Rc<RefCell<RootedTraceableSet>> =
Rc::new(RefCell::new(RootedTraceableSet::new())));
impl RootedCollectionSet { impl RootedTraceableSet {
fn new() -> RootedCollectionSet { fn new() -> RootedTraceableSet {
RootedCollectionSet { RootedTraceableSet {
set: vec!(HashSet::new(), HashSet::new(), HashSet::new()) set: vec!()
} }
} }
fn remove<T: VecRootableType>(collection: &RootedVec<T>) { fn remove<T: JSTraceable>(traceable: &T) {
ROOTED_COLLECTIONS.with(|ref collections| { ROOTED_TRACEABLES.with(|ref traceables| {
let type_ = VecRootableType::tag(None::<T>); let mut traceables = traceables.borrow_mut();
let mut collections = collections.borrow_mut(); let idx =
assert!(collections.set[type_ as usize].remove(&(collection as *const _ as *const _))); match traceables.set.iter()
.rposition(|x| x.ptr == traceable as *const T as *const _) {
Some(idx) => idx,
None => unreachable!(),
};
traceables.set.remove(idx);
}); });
} }
fn add<T: VecRootableType>(collection: &RootedVec<T>) { fn add<T: JSTraceable>(traceable: &T) {
ROOTED_COLLECTIONS.with(|ref collections| { ROOTED_TRACEABLES.with(|ref traceables| {
let type_ = VecRootableType::tag(None::<T>); fn trace<T: JSTraceable>(obj: *const libc::c_void, tracer: *mut JSTracer) {
let mut collections = collections.borrow_mut(); let obj: &T = unsafe { &*(obj as *const T) };
collections.set[type_ as usize].insert(collection as *const _ as *const _); obj.trace(tracer);
}
let mut traceables = traceables.borrow_mut();
let info = TraceableInfo {
ptr: traceable as *const T as *const libc::c_void,
trace: trace::<T>,
};
traceables.set.push(info);
}) })
} }
unsafe fn trace(&self, tracer: *mut JSTracer) { unsafe fn trace(&self, tracer: *mut JSTracer) {
fn trace_collection_type<T>(tracer: *mut JSTracer, for info in self.set.iter() {
collections: &HashSet<*const RootedVec<Void>>) (info.trace)(info.ptr, tracer);
where T: JSTraceable + VecRootableType
{
for collection in collections {
let collection: *const RootedVec<Void> = *collection;
let collection = collection as *const RootedVec<T>;
unsafe {
let _ = (*collection).trace(tracer);
}
}
} }
let dom_collections =
&self.set[CollectionType::DOMObjects as usize] as *const _ as *const HashSet<*const RootedVec<JS<Void>>>;
for dom_collection in (*dom_collections).iter() {
for reflector in (**dom_collection).iter() {
trace_reflector(tracer, "", reflector.reflector());
}
}
trace_collection_type::<JSVal>(tracer, &self.set[CollectionType::JSVals as usize]);
trace_collection_type::<*mut JSObject>(tracer, &self.set[CollectionType::JSObjects as usize]);
} }
} }
/// Roots any JSTraceable thing
/// Trait implemented by all types that can be used with RootedVec ///
pub trait VecRootableType { /// If you have a valid Reflectable, use Root.
/// Return the type tag used to determine how to trace RootedVec /// If you have GC things like *mut JSObject or JSVal, use jsapi::Rooted.
fn tag(_a: Option<Self>) -> CollectionType; /// If you have an arbitrary number of Reflectables to root, use RootedVec<JS<T>>
/// If you know what you're doing, use this.
#[jstraceable]
pub struct RootedTraceable<'a, T: 'a + JSTraceable> {
ptr: &'a T
} }
impl<T: Reflectable> VecRootableType for JS<T> { impl<'a, T: JSTraceable> RootedTraceable<'a, T> {
fn tag(_a: Option<JS<T>>) -> CollectionType { CollectionType::DOMObjects } /// Root a JSTraceable thing for the life of this RootedTraceable
pub fn new(traceable: &'a T) -> RootedTraceable<'a, T> {
RootedTraceableSet::add(traceable);
RootedTraceable { ptr: traceable }
}
} }
impl VecRootableType for JSVal { impl<'a, T: JSTraceable> Drop for RootedTraceable<'a, T> {
fn tag(_a: Option<JSVal>) -> CollectionType { CollectionType::JSVals } fn drop(&mut self) {
} RootedTraceableSet::remove(self.ptr);
}
impl VecRootableType for *mut JSObject {
fn tag(_a: Option<*mut JSObject>) -> CollectionType { CollectionType::JSObjects }
}
enum Void {}
impl VecRootableType for Void {
fn tag(_a: Option<Void>) -> CollectionType { unreachable!() }
}
impl Reflectable for Void {
fn reflector<'a>(&'a self) -> &'a Reflector { unreachable!() }
} }
/// A vector of items that are rooted for the lifetime /// A vector of items that are rooted for the lifetime
/// of this struct /// of this struct.
/// Must be a reflectable
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
#[no_move] #[no_move]
pub struct RootedVec<T: VecRootableType> { #[jstraceable]
pub struct RootedVec<T: JSTraceable + Reflectable> {
v: Vec<T> v: Vec<T>
} }
impl<T: VecRootableType> RootedVec<T> { impl<T: JSTraceable + Reflectable> RootedVec<T> {
/// Create a vector of items of type T that is rooted for /// Create a vector of items of type T that is rooted for
/// the lifetime of this struct /// the lifetime of this struct
pub fn new() -> RootedVec<T> { pub fn new() -> RootedVec<T> {
@ -444,39 +452,38 @@ impl<T: VecRootableType> RootedVec<T> {
} }
/// Create a vector of items of type T. This constructor is specific /// Create a vector of items of type T. This constructor is specific
/// for RootCollection. /// for RootTraceableSet.
pub fn new_with_destination_address(addr: *const libc::c_void) -> RootedVec<T> { pub fn new_with_destination_address(addr: *const libc::c_void) -> RootedVec<T> {
unsafe { unsafe {
RootedCollectionSet::add::<T>(&*(addr as *const _)); RootedTraceableSet::add::<RootedVec<T>>(&*(addr as *const _));
} }
RootedVec::<T> { v: vec!() } RootedVec::<T> { v: vec!() }
} }
} }
impl<T: VecRootableType> Drop for RootedVec<T> { impl<T: JSTraceable + Reflectable> Drop for RootedVec<T> {
fn drop(&mut self) { fn drop(&mut self) {
RootedCollectionSet::remove(self); RootedTraceableSet::remove(self);
} }
} }
impl<T: VecRootableType> Deref for RootedVec<T> { impl<T: JSTraceable + Reflectable> Deref for RootedVec<T> {
type Target = Vec<T>; type Target = Vec<T>;
fn deref(&self) -> &Vec<T> { fn deref(&self) -> &Vec<T> {
&self.v &self.v
} }
} }
impl<T: VecRootableType> DerefMut for RootedVec<T> { impl<T: JSTraceable + Reflectable> DerefMut for RootedVec<T> {
fn deref_mut(&mut self) -> &mut Vec<T> { fn deref_mut(&mut self) -> &mut Vec<T> {
&mut self.v &mut self.v
} }
} }
/// SM Callback that traces the rooted traceables
/// SM Callback that traces the rooted collections pub unsafe fn trace_traceables(tracer: *mut JSTracer) {
pub unsafe fn trace_collections(tracer: *mut JSTracer) { ROOTED_TRACEABLES.with(|ref traceables| {
ROOTED_COLLECTIONS.with(|ref collections| { let traceables = traceables.borrow();
let collections = collections.borrow(); traceables.trace(tracer);
collections.trace(tracer);
}); });
} }

View file

@ -6,10 +6,10 @@
use dom::bindings::codegen::PrototypeList; use dom::bindings::codegen::PrototypeList;
use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH; use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH;
use dom::bindings::conversions::{native_from_reflector_jsmanaged, is_dom_class}; use dom::bindings::conversions::{native_from_handleobject, is_dom_class, jsstring_to_str};
use dom::bindings::error::{Error, ErrorResult, Fallible, throw_type_error}; use dom::bindings::error::{Error, ErrorResult, Fallible, throw_type_error};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{Temporary, Root, Rootable}; use dom::bindings::js::Root;
use dom::bindings::trace::trace_object; use dom::bindings::trace::trace_object;
use dom::browsercontext; use dom::browsercontext;
use dom::window; use dom::window;
@ -19,30 +19,39 @@ use util::str::DOMString;
use libc; use libc;
use libc::c_uint; use libc::c_uint;
use std::boxed; use std::boxed;
use std::cell::Cell;
use std::ffi::CString; use std::ffi::CString;
use std::ptr; use std::ptr;
use std::cmp::PartialEq;
use std::default::Default;
use std::cell::UnsafeCell;
use js::glue::UnwrapObject; use js::glue::UnwrapObject;
use js::glue::{IsWrapper, RUST_JSID_IS_INT, RUST_JSID_TO_INT}; use js::glue::{IsWrapper, RUST_JSID_IS_INT, RUST_JSID_TO_INT};
use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewFunction}; use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewFunction, JSTraceOp};
use js::jsapi::{JS_DefineProperties, JS_ForwardGetPropertyTo}; use js::jsapi::{JS_DefineProperties, JS_ForwardGetPropertyTo};
use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype, JS_GetStringCharsAndLength}; use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype};
use js::jsapi::{JSHandleObject, JSTracer}; use js::jsapi::{HandleObject, HandleId, HandleValue, MutableHandleValue};
use js::jsapi::JS_GetFunctionObject; use js::jsapi::JS_GetFunctionObject;
use js::jsapi::{JS_HasPropertyById, JS_GetPrototype}; use js::jsapi::{JS_HasPropertyById, JS_GetPrototype};
use js::jsapi::{JS_GetProperty, JS_HasProperty, JS_SetProperty}; use js::jsapi::{JS_GetProperty, JS_HasProperty, JS_SetProperty};
use js::jsapi::{JS_DefineFunctions, JS_DefineProperty}; use js::jsapi::{JS_DefineFunctions, JS_DefineProperty, JS_DefineProperty1};
use js::jsapi::{JS_ValueToString, JS_GetReservedSlot, JS_SetReservedSlot}; use js::jsapi::{JS_GetReservedSlot, JS_SetReservedSlot};
use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass}; use js::jsapi::{JSContext, JSObject, JSClass, JSTracer};
use js::jsapi::{JSFunctionSpec, JSPropertySpec}; use js::jsapi::{JSFunctionSpec, JSPropertySpec};
use js::jsapi::{JS_NewGlobalObject, JS_InitStandardClasses}; use js::jsapi::{JS_NewGlobalObject, JS_InitStandardClasses};
use js::jsapi::JS_DeletePropertyById2; use js::jsapi::{OnNewGlobalHookOption, CompartmentOptions};
use js::jsfriendapi::JS_ObjectToOuterObject; use js::jsapi::{JS_FireOnNewGlobalObject, JSVersion};
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType; use js::jsapi::JS_DeletePropertyById1;
use js::jsapi::JS_ObjectToOuterObject;
use js::jsapi::JS_NewObjectWithUniqueType;
use js::jsapi::{ObjectOpResult, RootedObject, RootedValue, Heap, MutableHandleObject};
use js::jsapi::PropertyDefinitionBehavior;
use js::jsapi::JSAutoCompartment;
use js::jsapi::{DOMCallbacks, JSWrapObjectCallbacks};
use js::jsval::JSVal; use js::jsval::JSVal;
use js::jsval::{PrivateValue, ObjectValue, NullValue}; use js::jsval::{PrivateValue, NullValue};
use js::jsval::{Int32Value, UInt32Value, DoubleValue, BooleanValue, UndefinedValue}; use js::jsval::{Int32Value, UInt32Value, DoubleValue, BooleanValue};
use js::rust::with_compartment; use js::rust::{GCMethods, ToString};
use js::glue::{WrapperNew, GetCrossCompartmentWrapper};
use js::{JSPROP_ENUMERATE, JSPROP_READONLY, JSPROP_PERMANENT}; use js::{JSPROP_ENUMERATE, JSPROP_READONLY, JSPROP_PERMANENT};
use js::JSFUN_CONSTRUCTOR; use js::JSFUN_CONSTRUCTOR;
use js; use js;
@ -145,7 +154,7 @@ unsafe impl Sync for DOMClass {}
#[derive(Copy)] #[derive(Copy)]
pub struct DOMJSClass { pub struct DOMJSClass {
/// The actual JSClass. /// The actual JSClass.
pub base: js::Class, pub base: js::jsapi::Class,
/// Associated data for DOM object reflectors. /// Associated data for DOM object reflectors.
pub dom_class: DOMClass pub dom_class: DOMClass
} }
@ -181,95 +190,93 @@ unsafe impl Sync for NativeProperties {}
/// A JSNative that cannot be null. /// A JSNative that cannot be null.
pub type NonNullJSNative = pub type NonNullJSNative =
unsafe extern "C" fn (arg1: *mut JSContext, arg2: c_uint, arg3: *mut JSVal) -> JSBool; unsafe extern "C" fn (arg1: *mut JSContext, arg2: c_uint, arg3: *mut JSVal) -> u8;
/// Creates the *interface prototype object* (if a `proto_class` is given) /// Creates the *interface prototype object* (if a `proto_class` is given)
/// and the *interface object* (if a `constructor` is given). /// and the *interface object* (if a `constructor` is given).
/// Fails on JSAPI failure. /// Fails on JSAPI failure.
pub fn do_create_interface_objects(cx: *mut JSContext, global: *mut JSObject, pub fn do_create_interface_objects(cx: *mut JSContext,
receiver: *mut JSObject, receiver: HandleObject,
proto_proto: *mut JSObject, proto_proto: HandleObject,
proto_class: Option<&'static JSClass>, proto_class: Option<&'static JSClass>,
constructor: Option<(NonNullJSNative, &'static str, u32)>, constructor: Option<(NonNullJSNative, &'static str, u32)>,
dom_class: *const DOMClass, dom_class: *const DOMClass,
members: &'static NativeProperties) members: &'static NativeProperties,
-> *mut JSObject { rval: MutableHandleObject) {
if let Some(proto_class) = proto_class {
create_interface_prototype_object(cx, proto_proto,
proto_class, members, rval);
}
unsafe { unsafe {
let proto = match proto_class { if !rval.get().is_null() {
Some(proto_class) => { JS_SetReservedSlot(rval.get(), DOM_PROTO_INSTANCE_CLASS_SLOT,
let proto = create_interface_prototype_object(cx, global, proto_proto, PrivateValue(dom_class as *const libc::c_void));
proto_class, members);
JS_SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
PrivateValue(dom_class as *const libc::c_void));
proto
},
None => ptr::null_mut()
};
if let Some((native, name, nargs)) = constructor {
let s = CString::new(name).unwrap();
create_interface_object(cx, global, receiver,
native, nargs, proto,
members, s.as_ptr())
} }
}
proto if let Some((native, name, nargs)) = constructor {
let s = CString::new(name).unwrap();
create_interface_object(cx, receiver,
native, nargs, rval.handle(),
members, s.as_ptr())
} }
} }
/// Creates the *interface object*. /// Creates the *interface object*.
/// Fails on JSAPI failure. /// Fails on JSAPI failure.
fn create_interface_object(cx: *mut JSContext, global: *mut JSObject, fn create_interface_object(cx: *mut JSContext,
receiver: *mut JSObject, receiver: HandleObject,
constructor_native: NonNullJSNative, constructor_native: NonNullJSNative,
ctor_nargs: u32, proto: *mut JSObject, ctor_nargs: u32, proto: HandleObject,
members: &'static NativeProperties, members: &'static NativeProperties,
name: *const libc::c_char) { name: *const libc::c_char) {
unsafe { unsafe {
let fun = JS_NewFunction(cx, Some(constructor_native), ctor_nargs, let fun = JS_NewFunction(cx, Some(constructor_native), ctor_nargs,
JSFUN_CONSTRUCTOR, global, name); JSFUN_CONSTRUCTOR, name);
assert!(!fun.is_null()); assert!(!fun.is_null());
let constructor = JS_GetFunctionObject(fun); let constructor = RootedObject::new(cx, JS_GetFunctionObject(fun));
assert!(!constructor.is_null()); assert!(!constructor.ptr.is_null());
if let Some(static_methods) = members.static_methods { if let Some(static_methods) = members.static_methods {
define_methods(cx, constructor, static_methods); define_methods(cx, constructor.handle(), static_methods);
} }
if let Some(static_properties) = members.static_attrs { if let Some(static_properties) = members.static_attrs {
define_properties(cx, constructor, static_properties); define_properties(cx, constructor.handle(), static_properties);
} }
if let Some(constants) = members.consts { if let Some(constants) = members.consts {
define_constants(cx, constructor, constants); define_constants(cx, constructor.handle(), constants);
} }
if !proto.is_null() { if !proto.get().is_null() {
assert!(JS_LinkConstructorAndPrototype(cx, constructor, proto) != 0); assert!(JS_LinkConstructorAndPrototype(cx, constructor.handle(), proto) != 0);
} }
let mut already_defined = 0; let mut already_defined = 0;
assert!(JS_AlreadyHasOwnProperty(cx, receiver, name, &mut already_defined) != 0); assert!(JS_AlreadyHasOwnProperty(cx, receiver, name, &mut already_defined) != 0);
if already_defined == 0 { if already_defined == 0 {
assert!(JS_DefineProperty(cx, receiver, name, assert!(JS_DefineProperty1(cx, receiver, name,
ObjectValue(&*constructor), constructor.handle(),
None, None, 0) != 0); 0, None, None) != 0);
} }
} }
} }
/// Defines constants on `obj`. /// Defines constants on `obj`.
/// Fails on JSAPI failure. /// Fails on JSAPI failure.
fn define_constants(cx: *mut JSContext, obj: *mut JSObject, fn define_constants(cx: *mut JSContext, obj: HandleObject,
constants: &'static [ConstantSpec]) { constants: &'static [ConstantSpec]) {
for spec in constants.iter() { for spec in constants.iter() {
let value = RootedValue::new(cx, spec.get_value());
unsafe { unsafe {
assert!(JS_DefineProperty(cx, obj, spec.name.as_ptr() as *const libc::c_char, assert!(JS_DefineProperty(cx, obj, spec.name.as_ptr() as *const libc::c_char,
spec.get_value(), None, None, value.handle(),
JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_READONLY |
JSPROP_PERMANENT) != 0); JSPROP_PERMANENT, None, None) != 0);
} }
} }
} }
@ -277,17 +284,17 @@ fn define_constants(cx: *mut JSContext, obj: *mut JSObject,
/// Defines methods on `obj`. The last entry of `methods` must contain zeroed /// Defines methods on `obj`. The last entry of `methods` must contain zeroed
/// memory. /// memory.
/// Fails on JSAPI failure. /// Fails on JSAPI failure.
fn define_methods(cx: *mut JSContext, obj: *mut JSObject, fn define_methods(cx: *mut JSContext, obj: HandleObject,
methods: &'static [JSFunctionSpec]) { methods: &'static [JSFunctionSpec]) {
unsafe { unsafe {
assert!(JS_DefineFunctions(cx, obj, methods.as_ptr()) != 0); assert!(JS_DefineFunctions(cx, obj, methods.as_ptr(), PropertyDefinitionBehavior::DefineAllProperties) != 0);
} }
} }
/// Defines attributes on `obj`. The last entry of `properties` must contain /// Defines attributes on `obj`. The last entry of `properties` must contain
/// zeroed memory. /// zeroed memory.
/// Fails on JSAPI failure. /// Fails on JSAPI failure.
fn define_properties(cx: *mut JSContext, obj: *mut JSObject, fn define_properties(cx: *mut JSContext, obj: HandleObject,
properties: &'static [JSPropertySpec]) { properties: &'static [JSPropertySpec]) {
unsafe { unsafe {
assert!(JS_DefineProperties(cx, obj, properties.as_ptr()) != 0); assert!(JS_DefineProperties(cx, obj, properties.as_ptr()) != 0);
@ -296,36 +303,32 @@ fn define_properties(cx: *mut JSContext, obj: *mut JSObject,
/// Creates the *interface prototype object*. /// Creates the *interface prototype object*.
/// Fails on JSAPI failure. /// Fails on JSAPI failure.
fn create_interface_prototype_object(cx: *mut JSContext, global: *mut JSObject, fn create_interface_prototype_object(cx: *mut JSContext, global: HandleObject,
parent_proto: *mut JSObject,
proto_class: &'static JSClass, proto_class: &'static JSClass,
members: &'static NativeProperties) members: &'static NativeProperties,
-> *mut JSObject { rval: MutableHandleObject) {
unsafe { unsafe {
let our_proto = JS_NewObjectWithUniqueType(cx, proto_class, rval.set(JS_NewObjectWithUniqueType(cx, proto_class, global));
&*parent_proto, &*global); assert!(!rval.get().is_null());
assert!(!our_proto.is_null());
if let Some(methods) = members.methods { if let Some(methods) = members.methods {
define_methods(cx, our_proto, methods); define_methods(cx, rval.handle(), methods);
} }
if let Some(properties) = members.attrs { if let Some(properties) = members.attrs {
define_properties(cx, our_proto, properties); define_properties(cx, rval.handle(), properties);
} }
if let Some(constants) = members.consts { if let Some(constants) = members.consts {
define_constants(cx, our_proto, constants); define_constants(cx, rval.handle(), constants);
} }
return our_proto;
} }
} }
/// A throwing constructor, for those interfaces that have neither /// A throwing constructor, for those interfaces that have neither
/// `NoInterfaceObject` nor `Constructor`. /// `NoInterfaceObject` nor `Constructor`.
pub unsafe extern fn throwing_constructor(cx: *mut JSContext, _argc: c_uint, pub unsafe extern fn throwing_constructor(cx: *mut JSContext, _argc: c_uint,
_vp: *mut JSVal) -> JSBool { _vp: *mut JSVal) -> u8 {
throw_type_error(cx, "Illegal constructor."); throw_type_error(cx, "Illegal constructor.");
return 0; return 0;
} }
@ -351,6 +354,10 @@ pub fn initialize_global(global: *mut JSObject) {
pub trait Reflectable { pub trait Reflectable {
/// Returns the receiver's reflector. /// Returns the receiver's reflector.
fn reflector<'a>(&'a self) -> &'a Reflector; fn reflector<'a>(&'a self) -> &'a Reflector;
/// Initializes the Reflector
fn init_reflector(&mut self, _obj: *mut JSObject) {
panic!("Cannot call init on this Reflectable");
}
} }
/// Create the reflector for a new DOM object and yield ownership to the /// Create the reflector for a new DOM object and yield ownership to the
@ -358,47 +365,56 @@ pub trait Reflectable {
pub fn reflect_dom_object<T: Reflectable> pub fn reflect_dom_object<T: Reflectable>
(obj: Box<T>, (obj: Box<T>,
global: GlobalRef, global: GlobalRef,
wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<T>) -> Temporary<T>) wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<T>) -> Root<T>)
-> Temporary<T> { -> Root<T> {
wrap_fn(global.get_cx(), global, obj) wrap_fn(global.get_cx(), global, obj)
} }
/// A struct to store a reference to the reflector of a DOM object. /// A struct to store a reference to the reflector of a DOM object.
// Allowing unused_attribute because the lint sometimes doesn't run in order // Allowing unused_attribute because the lint sometimes doesn't run in order
#[allow(raw_pointer_derive, unrooted_must_root, unused_attributes)] #[allow(raw_pointer_derive, unrooted_must_root, unused_attributes)]
#[derive(PartialEq)]
#[must_root] #[must_root]
#[servo_lang = "reflector"] #[servo_lang = "reflector"]
// If you're renaming or moving this field, update the path in plugins::reflector as well // If you're renaming or moving this field, update the path in plugins::reflector as well
pub struct Reflector { pub struct Reflector {
object: Cell<*mut JSObject>, object: UnsafeCell<*mut JSObject>,
}
#[allow(unrooted_must_root)]
impl PartialEq for Reflector {
fn eq(&self, other: &Reflector) -> bool {
unsafe { *self.object.get() == *other.object.get() }
}
} }
impl Reflector { impl Reflector {
/// Get the reflector. /// Get the reflector.
#[inline] #[inline]
pub fn get_jsobject(&self) -> *mut JSObject { pub fn get_jsobject(&self) -> HandleObject {
self.object.get() HandleObject { ptr: self.object.get() }
} }
/// Initialize the reflector. (May be called only once.) /// Initialize the reflector. (May be called only once.)
pub fn set_jsobject(&self, object: *mut JSObject) { pub fn set_jsobject(&mut self, object: *mut JSObject) {
assert!(self.object.get().is_null()); unsafe {
assert!(!object.is_null()); let obj = self.object.get();
self.object.set(object); assert!((*obj).is_null());
assert!(!object.is_null());
*obj = object;
}
} }
/// Return a pointer to the memory location at which the JS reflector /// Return a pointer to the memory location at which the JS reflector
/// object is stored. Used by Temporary values to root the reflector, as /// object is stored. Used to root the reflector, as
/// required by the JSAPI rooting APIs. /// required by the JSAPI rooting APIs.
pub unsafe fn rootable(&self) -> *mut *mut JSObject { pub fn rootable(&self) -> *mut *mut JSObject {
self.object.as_unsafe_cell().get() self.object.get()
} }
/// Create an uninitialized `Reflector`. /// Create an uninitialized `Reflector`.
pub fn new() -> Reflector { pub fn new() -> Reflector {
Reflector { Reflector {
object: Cell::new(ptr::null_mut()), object: UnsafeCell::new(ptr::null_mut())
} }
} }
} }
@ -407,33 +423,34 @@ impl Reflector {
/// set to true and `*vp` to the value, otherwise `*found` is set to false. /// set to true and `*vp` to the value, otherwise `*found` is set to false.
/// ///
/// Returns false on JSAPI failure. /// Returns false on JSAPI failure.
pub fn get_property_on_prototype(cx: *mut JSContext, proxy: *mut JSObject, pub fn get_property_on_prototype(cx: *mut JSContext, proxy: HandleObject,
id: jsid, found: *mut bool, vp: *mut JSVal) id: HandleId, found: *mut bool, vp: MutableHandleValue)
-> bool { -> bool {
unsafe { unsafe {
//let proto = GetObjectProto(proxy); //let proto = GetObjectProto(proxy);
let proto = JS_GetPrototype(proxy); let mut proto = RootedObject::new(cx, ptr::null_mut());
if proto.is_null() { if JS_GetPrototype(cx, proxy, proto.handle_mut()) == 0 ||
proto.ptr.is_null() {
*found = false; *found = false;
return true; return true;
} }
let mut has_property = 0; let mut has_property = 0;
if JS_HasPropertyById(cx, proto, id, &mut has_property) == 0 { if JS_HasPropertyById(cx, proto.handle(), id, &mut has_property) == 0 {
return false; return false;
} }
*found = has_property != 0; *found = has_property != 0;
let no_output = vp.is_null(); let no_output = vp.ptr.is_null();
if has_property == 0 || no_output { if has_property == 0 || no_output {
return true; return true;
} }
JS_ForwardGetPropertyTo(cx, proto, id, proxy, vp) != 0 JS_ForwardGetPropertyTo(cx, proto.handle(), id, proxy, vp) != 0
} }
} }
/// Get an array index from the given `jsid`. Returns `None` if the given /// Get an array index from the given `jsid`. Returns `None` if the given
/// `jsid` is not an integer. /// `jsid` is not an integer.
pub fn get_array_index_from_id(_cx: *mut JSContext, id: jsid) -> Option<u32> { pub fn get_array_index_from_id(_cx: *mut JSContext, id: HandleId) -> Option<u32> {
unsafe { unsafe {
if RUST_JSID_IS_INT(id) != 0 { if RUST_JSID_IS_INT(id) != 0 {
return Some(RUST_JSID_TO_INT(id) as u32); return Some(RUST_JSID_TO_INT(id) as u32);
@ -460,28 +477,16 @@ pub fn get_array_index_from_id(_cx: *mut JSContext, id: jsid) -> Option<u32> {
/// Returns `Err(())` on JSAPI failure (there is a pending exception), and /// Returns `Err(())` on JSAPI failure (there is a pending exception), and
/// `Ok(None)` if there was no matching string. /// `Ok(None)` if there was no matching string.
pub fn find_enum_string_index(cx: *mut JSContext, pub fn find_enum_string_index(cx: *mut JSContext,
v: JSVal, v: HandleValue,
values: &[&'static str]) values: &[&'static str])
-> Result<Option<usize>, ()> { -> Result<Option<usize>, ()> {
unsafe { let jsstr = ToString(cx, v);
let jsstr = JS_ValueToString(cx, v); if jsstr.is_null() {
if jsstr.is_null() { return Err(());
return Err(());
}
let mut length = 0;
let chars = JS_GetStringCharsAndLength(cx, jsstr, &mut length);
if chars.is_null() {
return Err(());
}
Ok(values.iter().position(|value| {
value.len() == length as usize &&
(0..length as usize).all(|j| {
value.as_bytes()[j] as u16 == *chars.offset(j as isize)
})
}))
} }
let search = jsstring_to_str(cx, jsstr);
Ok(values.iter().position(|value| value == &search))
} }
/// Returns wether `obj` is a platform object /// Returns wether `obj` is a platform object
@ -495,7 +500,7 @@ pub fn is_platform_object(obj: *mut JSObject) -> bool {
} }
// Now for simplicity check for security wrappers before anything else // Now for simplicity check for security wrappers before anything else
if IsWrapper(obj) == 1 { if IsWrapper(obj) == 1 {
let unwrapped_obj = UnwrapObject(obj, /* stopAtOuter = */ 0, ptr::null_mut()); let unwrapped_obj = UnwrapObject(obj, /* stopAtOuter = */ 0);
if unwrapped_obj.is_null() { if unwrapped_obj.is_null() {
return false; return false;
} }
@ -508,53 +513,54 @@ pub fn is_platform_object(obj: *mut JSObject) -> bool {
/// Get the property with name `property` from `object`. /// Get the property with name `property` from `object`.
/// Returns `Err(())` on JSAPI failure (there is a pending exception), and /// Returns `Err(())` on JSAPI failure (there is a pending exception), and
/// `Ok(None)` if there was no property with the given name. /// `Ok(false)` if there was no property with the given name.
pub fn get_dictionary_property(cx: *mut JSContext, pub fn get_dictionary_property(cx: *mut JSContext,
object: *mut JSObject, object: HandleObject,
property: &str) -> Result<Option<JSVal>, ()> { property: &str,
fn has_property(cx: *mut JSContext, object: *mut JSObject, property: &CString, rval: MutableHandleValue)
found: &mut JSBool) -> bool { -> Result<bool, ()> {
fn has_property(cx: *mut JSContext, object: HandleObject, property: &CString,
found: &mut u8) -> bool {
unsafe { unsafe {
JS_HasProperty(cx, object, property.as_ptr(), found) != 0 JS_HasProperty(cx, object, property.as_ptr(), found) != 0
} }
} }
fn get_property(cx: *mut JSContext, object: *mut JSObject, property: &CString, fn get_property(cx: *mut JSContext, object: HandleObject, property: &CString,
value: &mut JSVal) -> bool { value: MutableHandleValue) -> bool {
unsafe { unsafe {
JS_GetProperty(cx, object, property.as_ptr(), value) != 0 JS_GetProperty(cx, object, property.as_ptr(), value) != 0
} }
} }
let property = CString::new(property).unwrap(); let property = CString::new(property).unwrap();
if object.is_null() { if object.get().is_null() {
return Ok(None); return Ok(false);
} }
let mut found: JSBool = 0; let mut found: u8 = 0;
if !has_property(cx, object, &property, &mut found) { if !has_property(cx, object, &property, &mut found) {
return Err(()); return Err(());
} }
if found == 0 { if found == 0 {
return Ok(None); return Ok(false);
} }
let mut value = NullValue(); if !get_property(cx, object, &property, rval) {
if !get_property(cx, object, &property, &mut value) {
return Err(()); return Err(());
} }
Ok(Some(value)) Ok(true)
} }
/// Set the property with name `property` from `object`. /// Set the property with name `property` from `object`.
/// Returns `Err(())` on JSAPI failure, or null object, /// Returns `Err(())` on JSAPI failure, or null object,
/// and Ok(()) otherwise /// and Ok(()) otherwise
pub fn set_dictionary_property(cx: *mut JSContext, pub fn set_dictionary_property(cx: *mut JSContext,
object: *mut JSObject, object: HandleObject,
property: &str, property: &str,
value: &mut JSVal) -> Result<(), ()> { value: HandleValue) -> Result<(), ()> {
if object.is_null() { if object.get().is_null() {
return Err(()); return Err(());
} }
@ -569,79 +575,99 @@ pub fn set_dictionary_property(cx: *mut JSContext,
} }
/// Returns whether `proxy` has a property `id` on its prototype. /// Returns whether `proxy` has a property `id` on its prototype.
pub fn has_property_on_prototype(cx: *mut JSContext, proxy: *mut JSObject, pub fn has_property_on_prototype(cx: *mut JSContext, proxy: HandleObject,
id: jsid) -> bool { id: HandleId) -> bool {
// MOZ_ASSERT(js::IsProxy(proxy) && js::GetProxyHandler(proxy) == handler); // MOZ_ASSERT(js::IsProxy(proxy) && js::GetProxyHandler(proxy) == handler);
let mut found = false; let mut found = false;
return !get_property_on_prototype(cx, proxy, id, &mut found, ptr::null_mut()) || found; return !get_property_on_prototype(cx, proxy, id, &mut found,
MutableHandleValue { ptr: ptr::null_mut() }) || found;
} }
/// Create a DOM global object with the given class. /// Create a DOM global object with the given class.
pub fn create_dom_global(cx: *mut JSContext, class: *const JSClass) pub fn create_dom_global(cx: *mut JSContext, class: *const JSClass,
trace: JSTraceOp)
-> *mut JSObject { -> *mut JSObject {
unsafe { unsafe {
let obj = JS_NewGlobalObject(cx, class, ptr::null_mut()); let mut options = CompartmentOptions::default();
if obj.is_null() { options.version_ = JSVersion::JSVERSION_LATEST;
options.traceGlobal_ = trace;
let obj =
RootedObject::new(cx,
JS_NewGlobalObject(cx, class, ptr::null_mut(),
OnNewGlobalHookOption::DontFireOnNewGlobalHook, &options));
if obj.ptr.is_null() {
return ptr::null_mut(); return ptr::null_mut();
} }
with_compartment(cx, obj, || { let _ac = JSAutoCompartment::new(cx, obj.ptr);
JS_InitStandardClasses(cx, obj); JS_InitStandardClasses(cx, obj.handle());
}); initialize_global(obj.ptr);
initialize_global(obj); JS_FireOnNewGlobalObject(cx, obj.handle());
obj obj.ptr
} }
} }
/// Drop the resources held by reserved slots of a global object /// Drop the resources held by reserved slots of a global object
pub unsafe fn finalize_global(obj: *mut JSObject) { pub unsafe fn finalize_global(obj: *mut JSObject) {
let protolist = get_proto_or_iface_array(obj);
let list = (*protolist).as_mut_ptr();
for idx in 0..(PrototypeList::ID::Count as isize) {
let entry = list.offset(idx);
let value = *entry;
if <*mut JSObject>::needs_post_barrier(value) {
<*mut JSObject>::relocate(entry);
}
}
let _: Box<ProtoOrIfaceArray> = let _: Box<ProtoOrIfaceArray> =
Box::from_raw(get_proto_or_iface_array(obj)); Box::from_raw(protolist);
} }
/// Trace the resources held by reserved slots of a global object /// Trace the resources held by reserved slots of a global object
pub unsafe fn trace_global(tracer: *mut JSTracer, obj: *mut JSObject) { pub unsafe fn trace_global(tracer: *mut JSTracer, obj: *mut JSObject) {
let array = get_proto_or_iface_array(obj); let array = get_proto_or_iface_array(obj);
for &proto in (*array).iter() { for proto in (&*array).iter() {
if !proto.is_null() { if !proto.is_null() {
trace_object(tracer, "prototype", proto); trace_object(tracer, "prototype", &*(proto as *const *mut JSObject as *const Heap<*mut JSObject>));
} }
} }
} }
/// Callback to outerize windows when wrapping. unsafe extern fn wrap(cx: *mut JSContext,
pub unsafe extern fn wrap_for_same_compartment(cx: *mut JSContext, obj: *mut JSObject) -> *mut JSObject { existing: HandleObject,
obj: HandleObject)
-> *mut JSObject {
// FIXME terrible idea. need security wrappers
// https://github.com/servo/servo/issues/2382
WrapperNew(cx, obj, GetCrossCompartmentWrapper())
}
unsafe extern fn pre_wrap(cx: *mut JSContext, _existing: HandleObject,
obj: HandleObject, _object_passed_to_wrap: HandleObject)
-> *mut JSObject {
let _ac = JSAutoCompartment::new(cx, obj.get());
JS_ObjectToOuterObject(cx, obj) JS_ObjectToOuterObject(cx, obj)
} }
/// Callback to outerize windows before wrapping. /// Callback table for use with JS_SetWrapObjectCallbacks
pub unsafe extern fn pre_wrap(cx: *mut JSContext, _scope: *mut JSObject, pub static WRAP_CALLBACKS: JSWrapObjectCallbacks = JSWrapObjectCallbacks {
obj: *mut JSObject, _flags: c_uint) -> *mut JSObject { wrap: Some(wrap),
JS_ObjectToOuterObject(cx, obj) preWrap: Some(pre_wrap),
} };
/// Callback to outerize windows. /// Callback to outerize windows.
pub extern fn outerize_global(_cx: *mut JSContext, obj: JSHandleObject) -> *mut JSObject { pub unsafe extern fn outerize_global(_cx: *mut JSContext, obj: HandleObject) -> *mut JSObject {
unsafe { debug!("outerizing");
debug!("outerizing"); let win: Root<window::Window> = native_from_handleobject(obj).unwrap();
let obj = *obj.unnamed_field1; // FIXME(https://github.com/rust-lang/rust/issues/23338)
let win: Root<window::Window> = native_from_reflector_jsmanaged(obj).unwrap().root(); let win = win.r();
// FIXME(https://github.com/rust-lang/rust/issues/23338) let context = win.browser_context();
let win = win.r(); context.as_ref().unwrap().window_proxy()
let context = win.browser_context();
context.as_ref().unwrap().window_proxy()
}
} }
/// Deletes the property `id` from `object`. /// Deletes the property `id` from `object`.
pub unsafe fn delete_property_by_id(cx: *mut JSContext, object: *mut JSObject, pub unsafe fn delete_property_by_id(cx: *mut JSContext, object: HandleObject,
id: jsid, bp: &mut bool) -> bool { id: HandleId, bp: *mut ObjectOpResult) -> u8 {
let mut value = UndefinedValue(); JS_DeletePropertyById1(cx, object, id, bp)
if JS_DeletePropertyById2(cx, object, id, &mut value) == 0 {
return false;
}
*bp = value.to_boolean();
return true;
} }
/// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details. /// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details.
@ -659,6 +685,18 @@ pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult {
} }
} }
unsafe extern "C" fn instance_class_has_proto_at_depth(clasp: *const js::jsapi::Class,
proto_id: u32,
depth: u32) -> u8 {
let domclass: *const DOMJSClass = clasp as *const _;
let domclass = &*domclass;
(domclass.dom_class.interface_chain[depth as usize] as u32 == proto_id) as u8
}
pub const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks {
instanceClassMatchesProto: Some(instance_class_has_proto_at_depth),
};
/// Validate a namespace and qualified name and extract their parts. /// Validate a namespace and qualified name and extract their parts.
/// See https://dom.spec.whatwg.org/#validate-and-extract for details. /// See https://dom.spec.whatwg.org/#validate-and-extract for details.
pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str) pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str)

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::InheritTypes::FileDerived; use dom::bindings::codegen::InheritTypes::FileDerived;
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::codegen::Bindings::BlobBinding; use dom::bindings::codegen::Bindings::BlobBinding;
@ -54,20 +54,20 @@ impl Blob {
} }
pub fn new(global: GlobalRef, bytes: Option<Vec<u8>>, pub fn new(global: GlobalRef, bytes: Option<Vec<u8>>,
typeString: &str) -> Temporary<Blob> { typeString: &str) -> Root<Blob> {
reflect_dom_object(box Blob::new_inherited(global, BlobTypeId::Blob, bytes, typeString), reflect_dom_object(box Blob::new_inherited(global, BlobTypeId::Blob, bytes, typeString),
global, global,
BlobBinding::Wrap) BlobBinding::Wrap)
} }
// http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob // http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob
pub fn Constructor(global: GlobalRef) -> Fallible<Temporary<Blob>> { pub fn Constructor(global: GlobalRef) -> Fallible<Root<Blob>> {
Ok(Blob::new(global, None, "")) Ok(Blob::new(global, None, ""))
} }
// http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob // http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob
pub fn Constructor_(global: GlobalRef, blobParts: DOMString, pub fn Constructor_(global: GlobalRef, blobParts: DOMString,
blobPropertyBag: &BlobBinding::BlobPropertyBag) -> Fallible<Temporary<Blob>> { blobPropertyBag: &BlobBinding::BlobPropertyBag) -> Fallible<Root<Blob>> {
//TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView or Blob //TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView or Blob
let bytes: Option<Vec<u8>> = Some(blobParts.into_bytes()); let bytes: Option<Vec<u8>> = Some(blobParts.into_bytes());
let typeString = if is_ascii_printable(&blobPropertyBag.type_) { let typeString = if is_ascii_printable(&blobPropertyBag.type_) {
@ -79,7 +79,7 @@ impl Blob {
} }
} }
impl<'a> BlobMethods for JSRef<'a, Blob> { impl<'a> BlobMethods for &'a Blob {
// http://dev.w3.org/2006/webapi/FileAPI/#dfn-size // http://dev.w3.org/2006/webapi/FileAPI/#dfn-size
fn Size(self) -> u64{ fn Size(self) -> u64{
match self.bytes { match self.bytes {
@ -95,7 +95,7 @@ impl<'a> BlobMethods for JSRef<'a, Blob> {
// http://dev.w3.org/2006/webapi/FileAPI/#slice-method-algo // http://dev.w3.org/2006/webapi/FileAPI/#slice-method-algo
fn Slice(self, start: Option<i64>, end: Option<i64>, fn Slice(self, start: Option<i64>, end: Option<i64>,
contentType: Option<DOMString>) -> Temporary<Blob> { contentType: Option<DOMString>) -> Root<Blob> {
let size: i64 = self.Size().to_i64().unwrap(); let size: i64 = self.Size().to_i64().unwrap();
let relativeStart: i64 = match start { let relativeStart: i64 = match start {
None => 0, None => 0,

View file

@ -2,11 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::conversions::native_from_reflector_jsmanaged; use dom::bindings::conversions::native_from_handleobject;
use dom::bindings::conversions::{ToJSValConvertible}; use dom::bindings::conversions::{ToJSValConvertible};
use dom::bindings::js::{JS, JSRef, Temporary, Root}; use dom::bindings::js::{JS, Root};
use dom::bindings::js::{OptionalRootable, OptionalOptionalRootable};
use dom::bindings::js::{ResultRootable, Rootable};
use dom::bindings::proxyhandler::{get_property_descriptor, fill_property_descriptor}; use dom::bindings::proxyhandler::{get_property_descriptor, fill_property_descriptor};
use dom::bindings::utils::{Reflectable, WindowProxyHandler}; use dom::bindings::utils::{Reflectable, WindowProxyHandler};
use dom::bindings::utils::get_array_index_from_id; use dom::bindings::utils::get_array_index_from_id;
@ -15,73 +13,72 @@ use dom::element::Element;
use dom::window::Window; use dom::window::Window;
use dom::window::WindowHelpers; use dom::window::WindowHelpers;
use js::jsapi::{JSContext, JSObject, jsid, JSPropertyDescriptor}; use js::jsapi::{JSContext, JSObject, JSPropertyDescriptor, JSErrNum};
use js::jsapi::{HandleObject, HandleId, MutableHandle, MutableHandleValue};
use js::jsapi::{JS_AlreadyHasOwnPropertyById, JS_ForwardGetPropertyTo}; use js::jsapi::{JS_AlreadyHasOwnPropertyById, JS_ForwardGetPropertyTo};
use js::jsapi::{JS_GetPropertyDescriptorById, JS_DefinePropertyById}; use js::jsapi::{JS_GetPropertyDescriptorById, JS_DefinePropertyById6};
use js::jsapi::{JS_SetPropertyById}; use js::jsapi::{JS_ForwardSetPropertyTo, ObjectOpResult, RootedObject, RootedValue, Handle, HandleValue, Heap};
use js::jsval::JSVal; use js::jsapi::{JSAutoRequest, JSAutoCompartment};
use js::jsval::{ObjectValue, UndefinedValue};
use js::glue::{GetProxyPrivate}; use js::glue::{GetProxyPrivate};
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps}; use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};
use js::rust::with_compartment; use js::{JSTrue, JSFalse};
use js::{JSRESOLVE_QUALIFIED, JSRESOLVE_ASSIGNING};
use std::ptr; use std::ptr;
use std::default::Default;
#[allow(raw_pointer_derive)]
#[jstraceable] #[jstraceable]
#[privatize] #[privatize]
pub struct BrowserContext { pub struct BrowserContext {
history: Vec<SessionHistoryEntry>, history: Vec<SessionHistoryEntry>,
active_index: usize, active_index: usize,
window_proxy: *mut JSObject, window_proxy: Heap<*mut JSObject>,
frame_element: Option<JS<Element>>, frame_element: Option<JS<Element>>,
} }
impl BrowserContext { impl BrowserContext {
pub fn new(document: JSRef<Document>, frame_element: Option<JSRef<Element>>) -> BrowserContext { pub fn new(document: &Document, frame_element: Option<&Element>) -> BrowserContext {
let mut context = BrowserContext { BrowserContext {
history: vec!(SessionHistoryEntry::new(document)), history: vec!(SessionHistoryEntry::new(document)),
active_index: 0, active_index: 0,
window_proxy: ptr::null_mut(), window_proxy: Heap::default(),
frame_element: frame_element.map(JS::from_rooted), frame_element: frame_element.map(JS::from_ref),
}; }
context.create_window_proxy();
context
} }
pub fn active_document(&self) -> Temporary<Document> { pub fn active_document(&self) -> Root<Document> {
Temporary::from_rooted(self.history[self.active_index].document.clone()) self.history[self.active_index].document.root()
} }
pub fn active_window(&self) -> Temporary<Window> { pub fn active_window(&self) -> Root<Window> {
let doc = self.active_document().root(); let doc = self.active_document();
doc.r().window() doc.r().window()
} }
pub fn frame_element(&self) -> Option<Temporary<Element>> { pub fn frame_element(&self) -> Option<Root<Element>> {
self.frame_element.map(Temporary::from_rooted) self.frame_element.map(Root::from_rooted)
} }
pub fn window_proxy(&self) -> *mut JSObject { pub fn window_proxy(&self) -> *mut JSObject {
assert!(!self.window_proxy.is_null()); assert!(!self.window_proxy.get().is_null());
self.window_proxy self.window_proxy.get()
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn create_window_proxy(&mut self) { pub fn create_window_proxy(&mut self) {
let win = self.active_window().root(); let win = self.active_window();
let win = win.r(); let win = win.r();
let WindowProxyHandler(handler) = win.windowproxy_handler(); let WindowProxyHandler(handler) = win.windowproxy_handler();
assert!(!handler.is_null()); assert!(!handler.is_null());
let parent = win.reflector().get_jsobject();
let cx = win.get_cx(); let cx = win.get_cx();
let wrapper = with_compartment(cx, parent, || unsafe { let _ar = JSAutoRequest::new(cx);
WrapperNew(cx, parent, handler) let parent = win.reflector().get_jsobject();
}); let _ac = JSAutoCompartment::new(cx, parent.get());
let wrapper = unsafe { WrapperNew(cx, parent, handler) };
assert!(!wrapper.is_null()); assert!(!wrapper.is_null());
self.window_proxy = wrapper; self.window_proxy.set(wrapper);
} }
} }
@ -96,20 +93,20 @@ pub struct SessionHistoryEntry {
} }
impl SessionHistoryEntry { impl SessionHistoryEntry {
fn new(document: JSRef<Document>) -> SessionHistoryEntry { fn new(document: &Document) -> SessionHistoryEntry {
SessionHistoryEntry { SessionHistoryEntry {
document: JS::from_rooted(document), document: JS::from_ref(document),
children: vec!() children: vec!()
} }
} }
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe fn GetSubframeWindow(cx: *mut JSContext, proxy: *mut JSObject, id: jsid) -> Option<Temporary<Window>> { unsafe fn GetSubframeWindow(cx: *mut JSContext, proxy: HandleObject, id: HandleId) -> Option<Root<Window>> {
let index = get_array_index_from_id(cx, id); let index = get_array_index_from_id(cx, id);
if let Some(index) = index { if let Some(index) = index {
let target = GetProxyPrivate(proxy).to_object(); let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
let win: Root<Window> = native_from_reflector_jsmanaged(target).unwrap().root(); let win: Root<Window> = native_from_handleobject(target.handle()).unwrap();
let mut found = false; let mut found = false;
return win.r().IndexedGetter(index, &mut found); return win.r().IndexedGetter(index, &mut found);
} }
@ -118,132 +115,133 @@ unsafe fn GetSubframeWindow(cx: *mut JSContext, proxy: *mut JSObject, id: jsid)
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe extern fn getOwnPropertyDescriptor(cx: *mut JSContext, proxy: *mut JSObject, id: jsid, unsafe extern fn getOwnPropertyDescriptor(cx: *mut JSContext, proxy: HandleObject, id: HandleId,
set: bool, desc: *mut JSPropertyDescriptor) -> bool { desc: MutableHandle<JSPropertyDescriptor>) -> u8 {
let window = GetSubframeWindow(cx, proxy, id); let window = GetSubframeWindow(cx, proxy, id);
if let Some(window) = window { if let Some(window) = window {
let window = window.root(); let mut val = RootedValue::new(cx, UndefinedValue());
(*desc).value = window.to_jsval(cx); window.to_jsval(cx, val.handle_mut());
fill_property_descriptor(&mut *desc, proxy, true); (*desc.ptr).value = val.ptr;
return true; fill_property_descriptor(&mut *desc.ptr, *proxy.ptr, true);
return JSTrue;
} }
let target = GetProxyPrivate(proxy).to_object(); let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
let flags = if set { JSRESOLVE_ASSIGNING } else { 0 } | JSRESOLVE_QUALIFIED;
// XXX This should be JS_GetOwnPropertyDescriptorById // XXX This should be JS_GetOwnPropertyDescriptorById
if JS_GetPropertyDescriptorById(cx, target, id, flags, desc) == 0 { if JS_GetPropertyDescriptorById(cx, target.handle(), id, desc) == 0 {
return false; return JSFalse;
} }
if (*desc).obj != target { if (*desc.ptr).obj != target.ptr {
// Not an own property // Not an own property
(*desc).obj = ptr::null_mut(); (*desc.ptr).obj = ptr::null_mut();
} else { } else {
(*desc).obj = proxy; (*desc.ptr).obj = *proxy.ptr;
} }
true JSTrue
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe extern fn defineProperty(cx: *mut JSContext, proxy: *mut JSObject, id: jsid, unsafe extern fn defineProperty(cx: *mut JSContext,
desc: *mut JSPropertyDescriptor) -> bool { proxy: HandleObject,
id: HandleId,
desc: Handle<JSPropertyDescriptor>,
res: *mut ObjectOpResult) -> u8 {
if get_array_index_from_id(cx, id).is_some() { if get_array_index_from_id(cx, id).is_some() {
// Spec says to Reject whether this is a supported index or not, // Spec says to Reject whether this is a supported index or not,
// since we have no indexed setter or indexed creator. That means // since we have no indexed setter or indexed creator. That means
// throwing in strict mode (FIXME: Bug 828137), doing nothing in // throwing in strict mode (FIXME: Bug 828137), doing nothing in
// non-strict mode. // non-strict mode.
return true; (*res).code_ = JSErrNum::JSMSG_CANT_DEFINE_WINDOW_ELEMENT as u32;
return JSTrue;
} }
let target = GetProxyPrivate(proxy).to_object(); let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
JS_DefinePropertyById(cx, target, id, (*desc).value, (*desc).getter, JS_DefinePropertyById6(cx, target.handle(), id, desc, res)
(*desc).setter, (*desc).attrs) != 0
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe extern fn hasOwn(cx: *mut JSContext, proxy: *mut JSObject, id: jsid, bp: *mut bool) -> bool { unsafe extern fn hasOwn(cx: *mut JSContext, proxy: HandleObject, id: HandleId, bp: *mut u8) -> u8 {
let window = GetSubframeWindow(cx, proxy, id); let window = GetSubframeWindow(cx, proxy, id);
if window.is_some() { if window.is_some() {
*bp = true; *bp = JSTrue;
return true; return JSTrue;
} }
let target = GetProxyPrivate(proxy).to_object(); let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
let mut found = 0; let mut found = 0;
if JS_AlreadyHasOwnPropertyById(cx, target, id, &mut found) == 0 { if JS_AlreadyHasOwnPropertyById(cx, target.handle(), id, &mut found) == 0 {
return false; return JSFalse;
} }
*bp = found != 0; *bp = (found != 0) as u8;
return true; return JSTrue;
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe extern fn get(cx: *mut JSContext, proxy: *mut JSObject, receiver: *mut JSObject, id: jsid, unsafe extern fn get(cx: *mut JSContext,
vp: *mut JSVal) -> bool { proxy: HandleObject,
receiver: HandleObject,
id: HandleId,
vp: MutableHandleValue) -> u8 {
let window = GetSubframeWindow(cx, proxy, id); let window = GetSubframeWindow(cx, proxy, id);
if let Some(window) = window { if let Some(window) = window {
let window = window.root(); window.to_jsval(cx, vp);
*vp = window.to_jsval(cx); return JSTrue;
return true;
} }
let target = GetProxyPrivate(proxy).to_object(); let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
JS_ForwardGetPropertyTo(cx, target, id, receiver, vp) != 0 JS_ForwardGetPropertyTo(cx, target.handle(), id, receiver, vp)
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
unsafe extern fn set(cx: *mut JSContext, proxy: *mut JSObject, _receiver: *mut JSObject, unsafe extern fn set(cx: *mut JSContext,
id: jsid, _strict: bool, vp: *mut JSVal) -> bool { proxy: HandleObject,
receiver: HandleObject,
id: HandleId,
vp: MutableHandleValue,
res: *mut ObjectOpResult) -> u8 {
if get_array_index_from_id(cx, id).is_some() { if get_array_index_from_id(cx, id).is_some() {
// Reject (which means throw if and only if strict) the set. // Reject (which means throw if and only if strict) the set.
// FIXME: Throw (*res).code_ = JSErrNum::JSMSG_READ_ONLY as u32;
return true; return JSTrue;
} }
// FIXME: The receiver should be used, we need something like JS_ForwardSetPropertyTo. let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
let target = GetProxyPrivate(proxy).to_object(); let receiver = RootedValue::new(cx, ObjectValue(&**receiver.ptr));
JS_SetPropertyById(cx, target, id, vp) != 0 JS_ForwardSetPropertyTo(cx, target.handle(), id, HandleValue { ptr: vp.ptr }, receiver.handle(), res)
} }
static PROXY_HANDLER: ProxyTraps = ProxyTraps { static PROXY_HANDLER: ProxyTraps = ProxyTraps {
getPropertyDescriptor: Some(get_property_descriptor enter: None,
as unsafe extern "C" fn(*mut JSContext, *mut JSObject, jsid, bool, getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor),
*mut JSPropertyDescriptor) -> bool), defineProperty: Some(defineProperty),
getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor ownPropertyKeys: None,
as unsafe extern "C" fn(*mut JSContext, *mut JSObject,
jsid, bool, *mut JSPropertyDescriptor)
-> bool),
defineProperty: Some(defineProperty as unsafe extern "C" fn(*mut JSContext, *mut JSObject, jsid,
*mut JSPropertyDescriptor) -> bool),
getOwnPropertyNames: None,
delete_: None, delete_: None,
enumerate: None, enumerate: None,
preventExtensions: None,
isExtensible: None,
has: None, has: None,
hasOwn: Some(hasOwn as unsafe extern "C" fn(*mut JSContext, *mut JSObject, jsid, *mut bool) -> bool), get: Some(get),
get: Some(get as unsafe extern "C" fn(*mut JSContext, *mut JSObject, *mut JSObject, jsid, *mut JSVal) -> bool), set: Some(set),
set: Some(set as unsafe extern "C" fn(*mut JSContext, *mut JSObject, *mut JSObject,
jsid, bool, *mut JSVal) -> bool),
keys: None,
iterate: None,
call: None, call: None,
construct: None, construct: None,
nativeCall: 0 as *const u8, getPropertyDescriptor: Some(get_property_descriptor),
hasOwn: Some(hasOwn),
getOwnEnumerablePropertyKeys: None,
nativeCall: None,
hasInstance: None, hasInstance: None,
typeOf: None,
objectClassIs: None, objectClassIs: None,
obj_toString: None, className: None,
fun_toString: None, fun_toString: None,
//regexp_toShared: 0 as *u8, boxedValue_unbox: None,
defaultValue: None, defaultValue: None,
iteratorNext: None, trace: None,
finalize: None, finalize: None,
getElementIfPresent: None, objectMoved: None,
getPrototypeOf: None, isCallable: None,
trace: None isConstructor: None,
}; };
#[allow(unsafe_code)] #[allow(unsafe_code)]

View file

@ -8,7 +8,7 @@ use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CanvasGradientBinding; use dom::bindings::codegen::Bindings::CanvasGradientBinding;
use dom::bindings::codegen::Bindings::CanvasGradientBinding::CanvasGradientMethods; use dom::bindings::codegen::Bindings::CanvasGradientBinding::CanvasGradientMethods;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::bindings::num::Finite; use dom::bindings::num::Finite;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::canvasrenderingcontext2d::parse_color; use dom::canvasrenderingcontext2d::parse_color;
@ -37,13 +37,13 @@ impl CanvasGradient {
} }
} }
pub fn new(global: GlobalRef, style: CanvasGradientStyle) -> Temporary<CanvasGradient> { pub fn new(global: GlobalRef, style: CanvasGradientStyle) -> Root<CanvasGradient> {
reflect_dom_object(box CanvasGradient::new_inherited(style), reflect_dom_object(box CanvasGradient::new_inherited(style),
global, CanvasGradientBinding::Wrap) global, CanvasGradientBinding::Wrap)
} }
} }
impl<'a> CanvasGradientMethods for JSRef<'a, CanvasGradient> { impl<'a> CanvasGradientMethods for &'a CanvasGradient {
// https://html.spec.whatwg.org/multipage/#dom-canvasgradient-addcolorstop // https://html.spec.whatwg.org/multipage/#dom-canvasgradient-addcolorstop
fn AddColorStop(self, offset: Finite<f64>, color: String) { fn AddColorStop(self, offset: Finite<f64>, color: String) {
let default_black = RGBA { let default_black = RGBA {
@ -61,11 +61,11 @@ impl<'a> CanvasGradientMethods for JSRef<'a, CanvasGradient> {
} }
pub trait ToFillOrStrokeStyle { pub trait ToFillOrStrokeStyle {
fn to_fill_or_stroke_style(&self) -> FillOrStrokeStyle; fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle;
} }
impl<'a> ToFillOrStrokeStyle for JSRef<'a, CanvasGradient> { impl<'a> ToFillOrStrokeStyle for &'a CanvasGradient {
fn to_fill_or_stroke_style(&self) -> FillOrStrokeStyle { fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle {
let gradient_stops = self.stops.borrow().clone(); let gradient_stops = self.stops.borrow().clone();
match self.style { match self.style {
CanvasGradientStyle::Linear(ref gradient) => { CanvasGradientStyle::Linear(ref gradient) => {

View file

@ -5,7 +5,7 @@
use canvas_traits::{FillOrStrokeStyle, SurfaceStyle, RepetitionStyle}; use canvas_traits::{FillOrStrokeStyle, SurfaceStyle, RepetitionStyle};
use dom::bindings::codegen::Bindings::CanvasPatternBinding; use dom::bindings::codegen::Bindings::CanvasPatternBinding;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::canvasgradient::ToFillOrStrokeStyle; use dom::canvasgradient::ToFillOrStrokeStyle;
use euclid::size::Size2D; use euclid::size::Size2D;
@ -41,14 +41,14 @@ impl CanvasPattern {
surface_data: Vec<u8>, surface_data: Vec<u8>,
surface_size: Size2D<i32>, surface_size: Size2D<i32>,
repeat: RepetitionStyle) repeat: RepetitionStyle)
-> Temporary<CanvasPattern> { -> Root<CanvasPattern> {
reflect_dom_object(box CanvasPattern::new_inherited(surface_data, surface_size, repeat), reflect_dom_object(box CanvasPattern::new_inherited(surface_data, surface_size, repeat),
global, CanvasPatternBinding::Wrap) global, CanvasPatternBinding::Wrap)
} }
} }
impl<'a> ToFillOrStrokeStyle for JSRef<'a, CanvasPattern> { impl<'a> ToFillOrStrokeStyle for &'a CanvasPattern {
fn to_fill_or_stroke_style(&self) -> FillOrStrokeStyle { fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle {
FillOrStrokeStyle::Surface( FillOrStrokeStyle::Surface(
SurfaceStyle::new(self.surface_data.clone(), self.surface_size, self.repeat_x, self.repeat_y)) SurfaceStyle::new(self.surface_data.clone(), self.surface_size, self.repeat_x, self.repeat_y))
} }

View file

@ -12,7 +12,7 @@ use dom::bindings::codegen::UnionTypes::StringOrCanvasGradientOrCanvasPattern;
use dom::bindings::error::Error::{IndexSize, NotSupported, Type, InvalidState, Syntax}; use dom::bindings::error::Error::{IndexSize, NotSupported, Type, InvalidState, Syntax};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, LayoutJS, Rootable, Temporary, Unrooted}; use dom::bindings::js::{JS, LayoutJS, Root};
use dom::bindings::num::Finite; use dom::bindings::num::Finite;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle};
@ -115,20 +115,20 @@ impl CanvasContextState {
} }
impl CanvasRenderingContext2D { impl CanvasRenderingContext2D {
fn new_inherited(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>) fn new_inherited(global: GlobalRef, canvas: &HTMLCanvasElement, size: Size2D<i32>)
-> CanvasRenderingContext2D { -> CanvasRenderingContext2D {
CanvasRenderingContext2D { CanvasRenderingContext2D {
reflector_: Reflector::new(), reflector_: Reflector::new(),
global: GlobalField::from_rooted(&global), global: GlobalField::from_rooted(&global),
renderer: CanvasPaintTask::start(size), renderer: CanvasPaintTask::start(size),
canvas: JS::from_rooted(canvas), canvas: JS::from_ref(canvas),
state: RefCell::new(CanvasContextState::new()), state: RefCell::new(CanvasContextState::new()),
saved_states: RefCell::new(Vec::new()), saved_states: RefCell::new(Vec::new()),
} }
} }
pub fn new(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>) pub fn new(global: GlobalRef, canvas: &HTMLCanvasElement, size: Size2D<i32>)
-> Temporary<CanvasRenderingContext2D> { -> Root<CanvasRenderingContext2D> {
reflect_dom_object(box CanvasRenderingContext2D::new_inherited(global, canvas, size), reflect_dom_object(box CanvasRenderingContext2D::new_inherited(global, canvas, size),
global, CanvasRenderingContext2DBinding::Wrap) global, CanvasRenderingContext2DBinding::Wrap)
} }
@ -211,7 +211,7 @@ impl CanvasRenderingContext2D {
// //
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn draw_html_canvas_element(&self, fn draw_html_canvas_element(&self,
canvas: JSRef<HTMLCanvasElement>, canvas: &HTMLCanvasElement,
sx: f64, sy: f64, sw: f64, sh: f64, sx: f64, sy: f64, sw: f64, sh: f64,
dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> { dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> {
// 1. Check the usability of the image argument // 1. Check the usability of the image argument
@ -235,7 +235,7 @@ impl CanvasRenderingContext2D {
CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled)) CanvasMsg::Canvas2d(Canvas2dMsg::DrawImageSelf(image_size, dest_rect, source_rect, smoothing_enabled))
} else { // Source and target canvases are different } else { // Source and target canvases are different
let context = match canvas.get_or_init_2d_context() { let context = match canvas.get_or_init_2d_context() {
Some(context) => context.root(), Some(context) => context,
None => return Err(InvalidState), None => return Err(InvalidState),
}; };
@ -275,7 +275,7 @@ impl CanvasRenderingContext2D {
} }
fn fetch_image_data(&self, fn fetch_image_data(&self,
image_element: &JSRef<HTMLImageElement>) image_element: &&HTMLImageElement)
-> Option<(Vec<u8>, Size2D<f64>)> { -> Option<(Vec<u8>, Size2D<f64>)> {
let url = match image_element.get_url() { let url = match image_element.get_url() {
Some(url) => url, Some(url) => url,
@ -302,7 +302,7 @@ impl CanvasRenderingContext2D {
fn request_image_from_cache(&self, url: Url) -> ImageResponse { fn request_image_from_cache(&self, url: Url) -> ImageResponse {
let canvas = self.canvas.root(); let canvas = self.canvas.root();
let window = window_from_node(canvas.r()).root(); let window = window_from_node(canvas.r());
let window = window.r(); let window = window.r();
let image_cache = window.image_cache_task(); let image_cache = window.image_cache_task();
let (response_chan, response_port) = channel(); let (response_chan, response_port) = channel();
@ -325,11 +325,11 @@ impl CanvasRenderingContext2D {
} }
pub trait CanvasRenderingContext2DHelpers { pub trait CanvasRenderingContext2DHelpers {
fn get_renderer(&self) -> Sender<CanvasMsg>; fn get_renderer(self) -> Sender<CanvasMsg>;
} }
impl CanvasRenderingContext2DHelpers for CanvasRenderingContext2D { impl<'a> CanvasRenderingContext2DHelpers for &'a CanvasRenderingContext2D {
fn get_renderer(&self) -> Sender<CanvasMsg> { fn get_renderer(self) -> Sender<CanvasMsg> {
self.renderer.clone() self.renderer.clone()
} }
} }
@ -355,10 +355,10 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutJS<CanvasRenderingContext2D
// Restricted values are guarded in glue code. Therefore we need not add a guard. // Restricted values are guarded in glue code. Therefore we need not add a guard.
// //
// FIXME: this behavior should might be generated by some annotattions to idl. // FIXME: this behavior should might be generated by some annotattions to idl.
impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D> { impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas // https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas
fn Canvas(self) -> Temporary<HTMLCanvasElement> { fn Canvas(self) -> Root<HTMLCanvasElement> {
Temporary::from_rooted(self.canvas) self.canvas.root()
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-save // https://html.spec.whatwg.org/multipage/#dom-context-2d-save
@ -552,8 +552,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
let sy: f64 = 0f64; let sy: f64 = 0f64;
match image { match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(canvas) => {
let canvas = image.root();
let canvas_size = canvas.r().get_size(); let canvas_size = canvas.r().get_size();
let dw: f64 = canvas_size.width as f64; let dw: f64 = canvas_size.width as f64;
let dh: f64 = canvas_size.height as f64; let dh: f64 = canvas_size.height as f64;
@ -564,9 +563,8 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
dx, dy, dw, dh) dx, dy, dw, dh)
} }
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => {
let image = image.root();
let context = image.r(); let context = image.r();
let canvas = context.Canvas().root(); let canvas = context.Canvas();
let canvas_size = canvas.r().get_size(); let canvas_size = canvas.r().get_size();
let dw: f64 = canvas_size.width as f64; let dw: f64 = canvas_size.width as f64;
let dh: f64 = canvas_size.height as f64; let dh: f64 = canvas_size.height as f64;
@ -577,7 +575,6 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
dx, dy, dw, dh) dx, dy, dw, dh)
} }
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image = image.root();
let image_element = image.r(); let image_element = image.r();
// https://html.spec.whatwg.org/multipage/#img-error // https://html.spec.whatwg.org/multipage/#img-error
// If the image argument is an HTMLImageElement object that is in the broken state, // If the image argument is an HTMLImageElement object that is in the broken state,
@ -615,8 +612,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
let sy: f64 = 0f64; let sy: f64 = 0f64;
match image { match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(canvas) => {
let canvas = image.root();
let canvas_size = canvas.r().get_size(); let canvas_size = canvas.r().get_size();
let sw: f64 = canvas_size.width as f64; let sw: f64 = canvas_size.width as f64;
let sh: f64 = canvas_size.height as f64; let sh: f64 = canvas_size.height as f64;
@ -625,9 +621,8 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
dx, dy, dw, dh) dx, dy, dw, dh)
} }
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => {
let image = image.root();
let context = image.r(); let context = image.r();
let canvas = context.Canvas().root(); let canvas = context.Canvas();
let canvas_size = canvas.r().get_size(); let canvas_size = canvas.r().get_size();
let sw: f64 = canvas_size.width as f64; let sw: f64 = canvas_size.width as f64;
let sh: f64 = canvas_size.height as f64; let sh: f64 = canvas_size.height as f64;
@ -636,7 +631,6 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
dx, dy, dw, dh) dx, dy, dw, dh)
} }
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image = image.root();
let image_element = image.r(); let image_element = image.r();
// https://html.spec.whatwg.org/multipage/#img-error // https://html.spec.whatwg.org/multipage/#img-error
// If the image argument is an HTMLImageElement object that is in the broken state, // If the image argument is an HTMLImageElement object that is in the broken state,
@ -666,21 +660,18 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
match image { match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => {
let canvas = image.root(); return self.draw_html_canvas_element(image.r(),
return self.draw_html_canvas_element(canvas.r(),
sx, sy, sw, sh, sx, sy, sw, sh,
dx, dy, dw, dh) dx, dy, dw, dh)
} }
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => {
let image = image.root();
let context = image.r(); let context = image.r();
let canvas = context.Canvas().root(); let canvas = context.Canvas();
return self.draw_html_canvas_element(canvas.r(), return self.draw_html_canvas_element(canvas.r(),
sx, sy, sw, sh, sx, sy, sw, sh,
dx, dy, dw, dh) dx, dy, dw, dh)
} }
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image = image.root();
let image_element = image.r(); let image_element = image.r();
// https://html.spec.whatwg.org/multipage/#img-error // https://html.spec.whatwg.org/multipage/#img-error
// If the image argument is an HTMLImageElement object that is in the broken state, // If the image argument is an HTMLImageElement object that is in the broken state,
@ -820,7 +811,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
StringOrCanvasGradientOrCanvasPattern::eString(result) StringOrCanvasGradientOrCanvasPattern::eString(result)
}, },
CanvasFillOrStrokeStyle::Gradient(gradient) => { CanvasFillOrStrokeStyle::Gradient(gradient) => {
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(Unrooted::from_js(gradient)) StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient.root())
}, },
} }
} }
@ -840,11 +831,10 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
} }
}, },
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient) => { StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient) => {
let gradient_root = gradient.root();
self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Gradient( self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Gradient(
JS::from_rooted(gradient_root.r())); JS::from_ref(gradient.r()));
let msg = CanvasMsg::Canvas2d( let msg = CanvasMsg::Canvas2d(
Canvas2dMsg::SetStrokeStyle(gradient_root.r().to_fill_or_stroke_style())); Canvas2dMsg::SetStrokeStyle(gradient.r().to_fill_or_stroke_style()));
self.renderer.send(msg).unwrap(); self.renderer.send(msg).unwrap();
}, },
_ => {} _ => {}
@ -860,7 +850,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
StringOrCanvasGradientOrCanvasPattern::eString(result) StringOrCanvasGradientOrCanvasPattern::eString(result)
}, },
CanvasFillOrStrokeStyle::Gradient(gradient) => { CanvasFillOrStrokeStyle::Gradient(gradient) => {
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(Unrooted::from_js(gradient)) StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient.root())
}, },
} }
} }
@ -880,22 +870,21 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
} }
} }
StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient) => { StringOrCanvasGradientOrCanvasPattern::eCanvasGradient(gradient) => {
let gradient_root = gradient.root();
self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Gradient( self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Gradient(
JS::from_rooted(gradient_root.r())); JS::from_rooted(&gradient));
let msg = CanvasMsg::Canvas2d( let msg = CanvasMsg::Canvas2d(
Canvas2dMsg::SetFillStyle(gradient_root.r().to_fill_or_stroke_style())); Canvas2dMsg::SetFillStyle(gradient.r().to_fill_or_stroke_style()));
self.renderer.send(msg).unwrap(); self.renderer.send(msg).unwrap();
} }
StringOrCanvasGradientOrCanvasPattern::eCanvasPattern(pattern) => { StringOrCanvasGradientOrCanvasPattern::eCanvasPattern(pattern) => {
self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetFillStyle( self.renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetFillStyle(
pattern.root().r().to_fill_or_stroke_style()))).unwrap(); pattern.r().to_fill_or_stroke_style()))).unwrap();
} }
} }
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
fn CreateImageData(self, sw: f64, sh: f64) -> Fallible<Temporary<ImageData>> { fn CreateImageData(self, sw: f64, sh: f64) -> Fallible<Root<ImageData>> {
if !(sw.is_finite() && sh.is_finite()) { if !(sw.is_finite() && sh.is_finite()) {
return Err(NotSupported); return Err(NotSupported);
} }
@ -908,7 +897,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
fn CreateImageData_(self, imagedata: JSRef<ImageData>) -> Fallible<Temporary<ImageData>> { fn CreateImageData_(self, imagedata: &ImageData) -> Fallible<Root<ImageData>> {
Ok(ImageData::new(self.global.root().r(), imagedata.Width(), imagedata.Height(), None)) Ok(ImageData::new(self.global.root().r(), imagedata.Width(), imagedata.Height(), None))
} }
@ -917,7 +906,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
sx: Finite<f64>, sx: Finite<f64>,
sy: Finite<f64>, sy: Finite<f64>,
sw: Finite<f64>, sw: Finite<f64>,
sh: Finite<f64>) -> Fallible<Temporary<ImageData>> { sh: Finite<f64>) -> Fallible<Root<ImageData>> {
let sx = *sx; let sx = *sx;
let sy = *sy; let sy = *sy;
let sw = *sw; let sw = *sw;
@ -938,7 +927,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
fn PutImageData(self, imagedata: JSRef<ImageData>, dx: Finite<f64>, dy: Finite<f64>) { fn PutImageData(self, imagedata: &ImageData, dx: Finite<f64>, dy: Finite<f64>) {
let dx = *dx; let dx = *dx;
let dy = *dy; let dy = *dy;
@ -960,7 +949,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
fn PutImageData_(self, imagedata: JSRef<ImageData>, dx: Finite<f64>, dy: Finite<f64>, fn PutImageData_(self, imagedata: &ImageData, dx: Finite<f64>, dy: Finite<f64>,
dirtyX: Finite<f64>, dirtyY: Finite<f64>, dirtyWidth: Finite<f64>, dirtyHeight: Finite<f64>) { dirtyX: Finite<f64>, dirtyY: Finite<f64>, dirtyWidth: Finite<f64>, dirtyHeight: Finite<f64>) {
let dx = *dx; let dx = *dx;
let dy = *dy; let dy = *dy;
@ -989,7 +978,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient // https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient
fn CreateLinearGradient(self, x0: Finite<f64>, y0: Finite<f64>, fn CreateLinearGradient(self, x0: Finite<f64>, y0: Finite<f64>,
x1: Finite<f64>, y1: Finite<f64>) -> Fallible<Temporary<CanvasGradient>> { x1: Finite<f64>, y1: Finite<f64>) -> Fallible<Root<CanvasGradient>> {
let x0 = *x0; let x0 = *x0;
let y0 = *y0; let y0 = *y0;
let x1 = *x1; let x1 = *x1;
@ -1006,7 +995,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient // https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient
fn CreateRadialGradient(self, x0: Finite<f64>, y0: Finite<f64>, r0: Finite<f64>, fn CreateRadialGradient(self, x0: Finite<f64>, y0: Finite<f64>, r0: Finite<f64>,
x1: Finite<f64>, y1: Finite<f64>, r1: Finite<f64>) x1: Finite<f64>, y1: Finite<f64>, r1: Finite<f64>)
-> Fallible<Temporary<CanvasGradient>> { -> Fallible<Root<CanvasGradient>> {
let x0 = *x0; let x0 = *x0;
let y0 = *y0; let y0 = *y0;
let r0 = *r0; let r0 = *r0;
@ -1025,10 +1014,9 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern // https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
fn CreatePattern(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, fn CreatePattern(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
repetition: DOMString) -> Fallible<Temporary<CanvasPattern>> { repetition: DOMString) -> Fallible<Root<CanvasPattern>> {
match image { match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image = image.root();
let image_element = image.r(); let image_element = image.r();
let url = match image_element.get_url() { let url = match image_element.get_url() {

View file

@ -11,7 +11,7 @@ use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::error::{Fallible, ErrorResult}; use dom::bindings::error::{Fallible, ErrorResult};
use dom::bindings::error::Error::IndexSize; use dom::bindings::error::Error::IndexSize;
use dom::bindings::js::{JSRef, LayoutJS, Temporary}; use dom::bindings::js::{LayoutJS, Root};
use dom::document::Document; use dom::document::Document;
use dom::element::Element; use dom::element::Element;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -39,7 +39,7 @@ impl CharacterDataDerived for EventTarget {
} }
impl CharacterData { impl CharacterData {
pub fn new_inherited(id: CharacterDataTypeId, data: DOMString, document: JSRef<Document>) -> CharacterData { pub fn new_inherited(id: CharacterDataTypeId, data: DOMString, document: &Document) -> CharacterData {
CharacterData { CharacterData {
node: Node::new_inherited(NodeTypeId::CharacterData(id), document), node: Node::new_inherited(NodeTypeId::CharacterData(id), document),
data: DOMRefCell::new(data), data: DOMRefCell::new(data),
@ -47,7 +47,7 @@ impl CharacterData {
} }
} }
impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> { impl<'a> CharacterDataMethods for &'a CharacterData {
// https://dom.spec.whatwg.org/#dom-characterdata-data // https://dom.spec.whatwg.org/#dom-characterdata-data
fn Data(self) -> DOMString { fn Data(self) -> DOMString {
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
@ -136,20 +136,20 @@ impl<'a> CharacterDataMethods for JSRef<'a, CharacterData> {
// https://dom.spec.whatwg.org/#dom-childnode-remove // https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(self) { fn Remove(self) {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.remove_self(); node.remove_self();
} }
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling // https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling
fn GetPreviousElementSibling(self) -> Option<Temporary<Element>> { fn GetPreviousElementSibling(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).preceding_siblings() NodeCast::from_ref(self).preceding_siblings()
.filter_map(ElementCast::to_temporary).next() .filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling // https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling
fn GetNextElementSibling(self) -> Option<Temporary<Element>> { fn GetNextElementSibling(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).following_siblings() NodeCast::from_ref(self).following_siblings()
.filter_map(ElementCast::to_temporary).next() .filter_map(ElementCast::to_root).next()
} }
} }
@ -166,10 +166,10 @@ pub trait CharacterDataHelpers<'a> {
fn data(self) -> Ref<'a, DOMString>; fn data(self) -> Ref<'a, DOMString>;
} }
impl<'a> CharacterDataHelpers<'a> for JSRef<'a, CharacterData> { impl<'a> CharacterDataHelpers<'a> for &'a CharacterData {
#[inline] #[inline]
fn data(self) -> Ref<'a, DOMString> { fn data(self) -> Ref<'a, DOMString> {
self.extended_deref().data.borrow() self.data.borrow()
} }
} }

View file

@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::CloseEventBinding::CloseEventMethods;
use dom::bindings::codegen::InheritTypes::EventCast; use dom::bindings::codegen::InheritTypes::EventCast;
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary, Rootable}; use dom::bindings::js::Root;
use dom::bindings::utils::reflect_dom_object; use dom::bindings::utils::reflect_dom_object;
use dom::event::{Event, EventTypeId, EventBubbles, EventCancelable}; use dom::event::{Event, EventTypeId, EventBubbles, EventCancelable};
use script_task::ScriptChan; use script_task::ScriptChan;
@ -40,21 +40,23 @@ impl CloseEvent {
cancelable: EventCancelable, cancelable: EventCancelable,
wasClean: bool, wasClean: bool,
code: u16, code: u16,
reason: DOMString) -> Temporary<CloseEvent> { reason: DOMString) -> Root<CloseEvent> {
let event = box CloseEvent::new_inherited(EventTypeId::CloseEvent, let event = box CloseEvent::new_inherited(EventTypeId::CloseEvent,
wasClean, code, reason); wasClean, code, reason);
let ev = reflect_dom_object(event, global, CloseEventBinding::Wrap).root(); let ev = reflect_dom_object(event, global, CloseEventBinding::Wrap);
let event: JSRef<Event> = EventCast::from_ref(ev.r()); {
event.InitEvent(type_, let event = EventCast::from_ref(ev.r());
bubbles == EventBubbles::Bubbles, event.InitEvent(type_,
cancelable == EventCancelable::Cancelable); bubbles == EventBubbles::Bubbles,
Temporary::from_rooted(ev.r()) cancelable == EventCancelable::Cancelable);
}
ev
} }
pub fn Constructor(global: GlobalRef, pub fn Constructor(global: GlobalRef,
type_: DOMString, type_: DOMString,
init: &CloseEventBinding::CloseEventInit) init: &CloseEventBinding::CloseEventInit)
-> Fallible<Temporary<CloseEvent>> { -> Fallible<Root<CloseEvent>> {
let bubbles = if init.parent.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble }; let bubbles = if init.parent.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble };
let cancelable = if init.parent.cancelable { let cancelable = if init.parent.cancelable {
EventCancelable::Cancelable EventCancelable::Cancelable
@ -66,7 +68,7 @@ impl CloseEvent {
} }
} }
impl<'a> CloseEventMethods for JSRef<'a, CloseEvent> { impl<'a> CloseEventMethods for &'a CloseEvent {
fn WasClean(self) -> bool { fn WasClean(self) -> bool {
self.wasClean self.wasClean
} }

View file

@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::CommentDerived; use dom::bindings::codegen::InheritTypes::CommentDerived;
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::characterdata::{CharacterData, CharacterDataTypeId}; use dom::characterdata::{CharacterData, CharacterDataTypeId};
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -27,19 +27,19 @@ impl CommentDerived for EventTarget {
} }
impl Comment { impl Comment {
fn new_inherited(text: DOMString, document: JSRef<Document>) -> Comment { fn new_inherited(text: DOMString, document: &Document) -> Comment {
Comment { Comment {
characterdata: CharacterData::new_inherited(CharacterDataTypeId::Comment, text, document) characterdata: CharacterData::new_inherited(CharacterDataTypeId::Comment, text, document)
} }
} }
pub fn new(text: DOMString, document: JSRef<Document>) -> Temporary<Comment> { pub fn new(text: DOMString, document: &Document) -> Root<Comment> {
Node::reflect_node(box Comment::new_inherited(text, document), Node::reflect_node(box Comment::new_inherited(text, document),
document, CommentBinding::Wrap) document, CommentBinding::Wrap)
} }
pub fn Constructor(global: GlobalRef, data: DOMString) -> Fallible<Temporary<Comment>> { pub fn Constructor(global: GlobalRef, data: DOMString) -> Fallible<Root<Comment>> {
let document = global.as_window().Document().root(); let document = global.as_window().Document();
Ok(Comment::new(data, document.r())) Ok(Comment::new(data, document.r()))
} }
} }

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::ConsoleBinding; use dom::bindings::codegen::Bindings::ConsoleBinding;
use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods; use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::window::WindowHelpers; use dom::window::WindowHelpers;
use devtools_traits::{DevtoolsControlMsg, ConsoleMessage, LogLevel}; use devtools_traits::{DevtoolsControlMsg, ConsoleMessage, LogLevel};
@ -26,12 +26,12 @@ impl Console {
} }
} }
pub fn new(global: GlobalRef) -> Temporary<Console> { pub fn new(global: GlobalRef) -> Root<Console> {
reflect_dom_object(box Console::new_inherited(global), global, ConsoleBinding::Wrap) reflect_dom_object(box Console::new_inherited(global), global, ConsoleBinding::Wrap)
} }
} }
impl<'a> ConsoleMethods for JSRef<'a, Console> { impl<'a> ConsoleMethods for &'a Console {
// https://developer.mozilla.org/en-US/docs/Web/API/Console/log // https://developer.mozilla.org/en-US/docs/Web/API/Console/log
fn Log(self, messages: Vec<DOMString>) { fn Log(self, messages: Vec<DOMString>) {
for message in messages { for message in messages {
@ -95,7 +95,7 @@ fn prepare_message(logLevel: LogLevel, message: String) -> ConsoleMessage {
} }
} }
fn propagate_console_msg(console: &JSRef<Console>, console_message: ConsoleMessage) { fn propagate_console_msg(console: &&Console, console_message: ConsoleMessage) {
let global = console.global.root(); let global = console.global.root();
match global.r() { match global.r() {
GlobalRef::Window(window_ref) => { GlobalRef::Window(window_ref) => {

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::InheritTypes::ElementCast; use dom::bindings::codegen::InheritTypes::ElementCast;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::Element; use dom::element::Element;
use dom::element::ElementCreator; use dom::element::ElementCreator;
@ -81,8 +81,8 @@ use string_cache::{Atom, QualName};
use std::borrow::ToOwned; use std::borrow::ToOwned;
pub fn create_element(name: QualName, prefix: Option<Atom>, pub fn create_element(name: QualName, prefix: Option<Atom>,
document: JSRef<Document>, creator: ElementCreator) document: &Document, creator: ElementCreator)
-> Temporary<Element> { -> Root<Element> {
let prefix = prefix.map(|p| (*p).to_owned()); let prefix = prefix.map(|p| (*p).to_owned());
if name.ns != ns!(HTML) { if name.ns != ns!(HTML) {
@ -92,11 +92,11 @@ pub fn create_element(name: QualName, prefix: Option<Atom>,
macro_rules! make( macro_rules! make(
($ctor:ident) => ({ ($ctor:ident) => ({
let obj = $ctor::new((*name.local).to_owned(), prefix, document); let obj = $ctor::new((*name.local).to_owned(), prefix, document);
ElementCast::from_temporary(obj) ElementCast::from_root(obj)
}); });
($ctor:ident, $($arg:expr),+) => ({ ($ctor:ident, $($arg:expr),+) => ({
let obj = $ctor::new((*name.local).to_owned(), prefix, document, $($arg),+); let obj = $ctor::new((*name.local).to_owned(), prefix, document, $($arg),+);
ElementCast::from_temporary(obj) ElementCast::from_root(obj)
}) })
); );

View file

@ -6,12 +6,12 @@ use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::{self, CSSStyl
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast}; use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, OptionalRootable, Rootable, Temporary}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::document::DocumentHelpers; use dom::document::DocumentHelpers;
use dom::element::{Element, ElementHelpers, StylePriority}; use dom::element::{ElementHelpers, StylePriority};
use dom::htmlelement::HTMLElement; use dom::htmlelement::HTMLElement;
use dom::node::{window_from_node, document_from_node, NodeDamage, Node}; use dom::node::{window_from_node, document_from_node, NodeDamage};
use dom::window::{Window, WindowHelpers}; use dom::window::{Window, WindowHelpers};
use util::str::DOMString; use util::str::DOMString;
use string_cache::Atom; use string_cache::Atom;
@ -55,17 +55,17 @@ fn serialize_list(list: &Vec<PropertyDeclaration>) -> DOMString {
} }
impl CSSStyleDeclaration { impl CSSStyleDeclaration {
pub fn new_inherited(owner: JSRef<HTMLElement>, pub fn new_inherited(owner: &HTMLElement,
modification_access: CSSModificationAccess) -> CSSStyleDeclaration { modification_access: CSSModificationAccess) -> CSSStyleDeclaration {
CSSStyleDeclaration { CSSStyleDeclaration {
reflector_: Reflector::new(), reflector_: Reflector::new(),
owner: JS::from_rooted(owner), owner: JS::from_ref(owner),
readonly: modification_access == CSSModificationAccess::Readonly, readonly: modification_access == CSSModificationAccess::Readonly,
} }
} }
pub fn new(global: JSRef<Window>, owner: JSRef<HTMLElement>, pub fn new(global: &Window, owner: &HTMLElement,
modification_access: CSSModificationAccess) -> Temporary<CSSStyleDeclaration> { modification_access: CSSModificationAccess) -> Root<CSSStyleDeclaration> {
reflect_dom_object(box CSSStyleDeclaration::new_inherited(owner, modification_access), reflect_dom_object(box CSSStyleDeclaration::new_inherited(owner, modification_access),
GlobalRef::Window(global), GlobalRef::Window(global),
CSSStyleDeclarationBinding::Wrap) CSSStyleDeclarationBinding::Wrap)
@ -77,25 +77,25 @@ trait PrivateCSSStyleDeclarationHelpers {
fn get_important_declaration(self, property: &Atom) -> Option<PropertyDeclaration>; fn get_important_declaration(self, property: &Atom) -> Option<PropertyDeclaration>;
} }
impl<'a> PrivateCSSStyleDeclarationHelpers for JSRef<'a, CSSStyleDeclaration> { impl<'a> PrivateCSSStyleDeclarationHelpers for &'a CSSStyleDeclaration {
fn get_declaration(self, property: &Atom) -> Option<PropertyDeclaration> { fn get_declaration(self, property: &Atom) -> Option<PropertyDeclaration> {
let owner = self.owner.root(); let owner = self.owner.root();
let element: JSRef<Element> = ElementCast::from_ref(owner.r()); let element = ElementCast::from_ref(owner.r());
element.get_inline_style_declaration(property).map(|decl| decl.clone()) element.get_inline_style_declaration(property).map(|decl| decl.clone())
} }
fn get_important_declaration(self, property: &Atom) -> Option<PropertyDeclaration> { fn get_important_declaration(self, property: &Atom) -> Option<PropertyDeclaration> {
let owner = self.owner.root(); let owner = self.owner.root();
let element: JSRef<Element> = ElementCast::from_ref(owner.r()); let element = ElementCast::from_ref(owner.r());
element.get_important_inline_style_declaration(property).map(|decl| decl.clone()) element.get_important_inline_style_declaration(property).map(|decl| decl.clone())
} }
} }
impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> { impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
// http://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length // http://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length
fn Length(self) -> u32 { fn Length(self) -> u32 {
let owner = self.owner.root(); let owner = self.owner.root();
let elem: JSRef<Element> = ElementCast::from_ref(owner.r()); let elem = ElementCast::from_ref(owner.r());
let len = match *elem.style_attribute().borrow() { let len = match *elem.style_attribute().borrow() {
Some(ref declarations) => declarations.normal.len() + declarations.important.len(), Some(ref declarations) => declarations.normal.len() + declarations.important.len(),
None => 0 None => 0
@ -107,7 +107,7 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
fn Item(self, index: u32) -> DOMString { fn Item(self, index: u32) -> DOMString {
let index = index as usize; let index = index as usize;
let owner = self.owner.root(); let owner = self.owner.root();
let elem: JSRef<Element> = ElementCast::from_ref(owner.r()); let elem = ElementCast::from_ref(owner.r());
let style_attribute = elem.style_attribute().borrow(); let style_attribute = elem.style_attribute().borrow();
let result = style_attribute.as_ref().and_then(|declarations| { let result = style_attribute.as_ref().and_then(|declarations| {
if index > declarations.normal.len() { if index > declarations.normal.len() {
@ -216,7 +216,7 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
synthesized_declaration.push_str(&value); synthesized_declaration.push_str(&value);
let owner = self.owner.root(); let owner = self.owner.root();
let window = window_from_node(owner.r()).root(); let window = window_from_node(owner.r());
let decl_block = parse_style_attribute(&synthesized_declaration, &window.r().get_url()); let decl_block = parse_style_attribute(&synthesized_declaration, &window.r().get_url());
// Step 7 // Step 7
@ -225,7 +225,7 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
} }
let owner = self.owner.root(); let owner = self.owner.root();
let element: JSRef<Element> = ElementCast::from_ref(owner.r()); let element = ElementCast::from_ref(owner.r());
// Step 8 // Step 8
for decl in decl_block.normal.iter() { for decl in decl_block.normal.iter() {
@ -238,8 +238,8 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
element.update_inline_style(decl.clone(), style_priority); element.update_inline_style(decl.clone(), style_priority);
} }
let document = document_from_node(element).root(); let document = document_from_node(element);
let node: JSRef<Node> = NodeCast::from_ref(element); let node = NodeCast::from_ref(element);
document.r().content_changed(node, NodeDamage::NodeStyleDamaged); document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
Ok(()) Ok(())
} }
@ -266,9 +266,9 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
} }
let owner = self.owner.root(); let owner = self.owner.root();
let window = window_from_node(owner.r()).root(); let window = window_from_node(owner.r());
let decl_block = parse_style_attribute(&property, &window.r().get_url()); let decl_block = parse_style_attribute(&property, &window.r().get_url());
let element: JSRef<Element> = ElementCast::from_ref(owner.r()); let element = ElementCast::from_ref(owner.r());
// Step 5 // Step 5
for decl in decl_block.normal.iter() { for decl in decl_block.normal.iter() {
@ -281,8 +281,8 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
element.update_inline_style(decl.clone(), style_priority); element.update_inline_style(decl.clone(), style_priority);
} }
let document = document_from_node(element).root(); let document = document_from_node(element);
let node: JSRef<Node> = NodeCast::from_ref(element); let node = NodeCast::from_ref(element);
document.r().content_changed(node, NodeDamage::NodeStyleDamaged); document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
Ok(()) Ok(())
} }
@ -317,7 +317,7 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
None => { None => {
// Step 5 // Step 5
let owner = self.owner.root(); let owner = self.owner.root();
let elem: JSRef<Element> = ElementCast::from_ref(owner.r()); let elem = ElementCast::from_ref(owner.r());
elem.remove_inline_style_property(property) elem.remove_inline_style_property(property)
} }
} }

View file

@ -8,18 +8,18 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventCast, CustomEventDerived}; use dom::bindings::codegen::InheritTypes::{EventCast, CustomEventDerived};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, MutHeap, Rootable, Temporary}; use dom::bindings::js::{Root, MutHeapJSVal};
use dom::bindings::utils::reflect_dom_object; use dom::bindings::utils::reflect_dom_object;
use dom::event::{Event, EventTypeId}; use dom::event::{Event, EventTypeId};
use js::jsapi::JSContext; use js::jsapi::{JSContext, HandleValue};
use js::jsval::{JSVal, NullValue}; use js::jsval::JSVal;
use util::str::DOMString; use util::str::DOMString;
// https://dom.spec.whatwg.org/#interface-customevent // https://dom.spec.whatwg.org/#interface-customevent
#[dom_struct] #[dom_struct]
pub struct CustomEvent { pub struct CustomEvent {
event: Event, event: Event,
detail: MutHeap<JSVal>, detail: MutHeapJSVal,
} }
impl CustomEventDerived for Event { impl CustomEventDerived for Event {
@ -32,11 +32,11 @@ impl CustomEvent {
fn new_inherited(type_id: EventTypeId) -> CustomEvent { fn new_inherited(type_id: EventTypeId) -> CustomEvent {
CustomEvent { CustomEvent {
event: Event::new_inherited(type_id), event: Event::new_inherited(type_id),
detail: MutHeap::new(NullValue()), detail: MutHeapJSVal::new(),
} }
} }
pub fn new_uninitialized(global: GlobalRef) -> Temporary<CustomEvent> { pub fn new_uninitialized(global: GlobalRef) -> Root<CustomEvent> {
reflect_dom_object(box CustomEvent::new_inherited(EventTypeId::CustomEvent), reflect_dom_object(box CustomEvent::new_inherited(EventTypeId::CustomEvent),
global, global,
CustomEventBinding::Wrap) CustomEventBinding::Wrap)
@ -45,19 +45,23 @@ impl CustomEvent {
type_: DOMString, type_: DOMString,
bubbles: bool, bubbles: bool,
cancelable: bool, cancelable: bool,
detail: JSVal) -> Temporary<CustomEvent> { detail: HandleValue) -> Root<CustomEvent> {
let ev = CustomEvent::new_uninitialized(global).root(); let ev = CustomEvent::new_uninitialized(global);
ev.r().InitCustomEvent(global.get_cx(), type_, bubbles, cancelable, detail); ev.r().InitCustomEvent(global.get_cx(), type_, bubbles, cancelable, detail);
Temporary::from_rooted(ev.r()) ev
} }
pub fn Constructor(global: GlobalRef, pub fn Constructor(global: GlobalRef,
type_: DOMString, type_: DOMString,
init: &CustomEventBinding::CustomEventInit) -> Fallible<Temporary<CustomEvent>>{ init: &CustomEventBinding::CustomEventInit) -> Fallible<Root<CustomEvent>>{
Ok(CustomEvent::new(global, type_, init.parent.bubbles, init.parent.cancelable, init.detail)) Ok(CustomEvent::new(global,
type_,
init.parent.bubbles,
init.parent.cancelable,
HandleValue { ptr: &init.detail }))
} }
} }
impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> { impl<'a> CustomEventMethods for &'a CustomEvent {
// https://dom.spec.whatwg.org/#dom-customevent-detail // https://dom.spec.whatwg.org/#dom-customevent-detail
fn Detail(self, _cx: *mut JSContext) -> JSVal { fn Detail(self, _cx: *mut JSContext) -> JSVal {
self.detail.get() self.detail.get()
@ -69,13 +73,13 @@ impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> {
type_: DOMString, type_: DOMString,
can_bubble: bool, can_bubble: bool,
cancelable: bool, cancelable: bool,
detail: JSVal) { detail: HandleValue) {
let event: JSRef<Event> = EventCast::from_ref(self); let event = EventCast::from_ref(self);
if event.dispatching() { if event.dispatching() {
return; return;
} }
self.detail.set(detail); self.detail.set(detail.get());
event.InitEvent(type_, can_bubble, cancelable); event.InitEvent(type_, can_bubble, cancelable);
} }
} }

View file

@ -9,9 +9,9 @@ use dom::bindings::codegen::Bindings::ErrorEventBinding::ErrorEventMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived; use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast};
use dom::bindings::error::ErrorResult; use dom::bindings::error::{ErrorResult, report_pending_exception};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, RootCollection, Rootable, Temporary}; use dom::bindings::js::{RootCollection, Root};
use dom::bindings::refcounted::LiveDOMReferences; use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::structuredclone::StructuredCloneData; use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
@ -33,8 +33,9 @@ use util::task::spawn_named;
use util::task_state; use util::task_state;
use util::task_state::{SCRIPT, IN_WORKER}; use util::task_state::{SCRIPT, IN_WORKER};
use js::jsapi::JSContext; use js::jsapi::{JSContext, RootedValue, HandleValue};
use js::jsval::JSVal; use js::jsapi::{JSAutoRequest, JSAutoCompartment};
use js::jsval::UndefinedValue;
use js::rust::Runtime; use js::rust::Runtime;
use url::Url; use url::Url;
@ -69,12 +70,12 @@ impl ScriptChan for SendableWorkerScriptChan {
/// object only lives as long as necessary (ie. while events are being executed), while /// object only lives as long as necessary (ie. while events are being executed), while
/// providing a reference that can be cloned freely. /// providing a reference that can be cloned freely.
struct AutoWorkerReset<'a> { struct AutoWorkerReset<'a> {
workerscope: JSRef<'a, DedicatedWorkerGlobalScope>, workerscope: &'a DedicatedWorkerGlobalScope,
old_worker: Option<TrustedWorkerAddress>, old_worker: Option<TrustedWorkerAddress>,
} }
impl<'a> AutoWorkerReset<'a> { impl<'a> AutoWorkerReset<'a> {
fn new(workerscope: JSRef<'a, DedicatedWorkerGlobalScope>, worker: TrustedWorkerAddress) -> AutoWorkerReset<'a> { fn new(workerscope: &'a DedicatedWorkerGlobalScope, worker: TrustedWorkerAddress) -> AutoWorkerReset<'a> {
let reset = AutoWorkerReset { let reset = AutoWorkerReset {
workerscope: workerscope, workerscope: workerscope,
old_worker: workerscope.worker.borrow().clone() old_worker: workerscope.worker.borrow().clone()
@ -132,7 +133,7 @@ impl DedicatedWorkerGlobalScope {
parent_sender: Box<ScriptChan+Send>, parent_sender: Box<ScriptChan+Send>,
own_sender: Sender<(TrustedWorkerAddress, ScriptMsg)>, own_sender: Sender<(TrustedWorkerAddress, ScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, ScriptMsg)>) receiver: Receiver<(TrustedWorkerAddress, ScriptMsg)>)
-> Temporary<DedicatedWorkerGlobalScope> { -> Root<DedicatedWorkerGlobalScope> {
let scope = box DedicatedWorkerGlobalScope::new_inherited( let scope = box DedicatedWorkerGlobalScope::new_inherited(
worker_url, id, devtools_chan, runtime.clone(), resource_task, worker_url, id, devtools_chan, runtime.clone(), resource_task,
parent_sender, own_sender, receiver); parent_sender, own_sender, receiver);
@ -170,7 +171,7 @@ impl DedicatedWorkerGlobalScope {
let runtime = Rc::new(ScriptTask::new_rt_and_cx()); let runtime = Rc::new(ScriptTask::new_rt_and_cx());
let global = DedicatedWorkerGlobalScope::new( let global = DedicatedWorkerGlobalScope::new(
worker_url, id, devtools_chan, runtime.clone(), resource_task, worker_url, id, devtools_chan, runtime.clone(), resource_task,
parent_sender, own_sender, receiver).root(); parent_sender, own_sender, receiver);
{ {
let _ar = AutoWorkerReset::new(global.r(), worker); let _ar = AutoWorkerReset::new(global.r(), worker);
@ -178,7 +179,13 @@ impl DedicatedWorkerGlobalScope {
match runtime.evaluate_script( match runtime.evaluate_script(
global.r().reflector().get_jsobject(), source, url.serialize(), 1) { global.r().reflector().get_jsobject(), source, url.serialize(), 1) {
Ok(_) => (), Ok(_) => (),
Err(_) => println!("evaluate_script failed") Err(_) => {
// TODO: An error needs to be dispatched to the parent.
// https://github.com/servo/servo/issues/6422
println!("evaluate_script failed");
let _ar = JSAutoRequest::new(runtime.cx());
report_pending_exception(runtime.cx(), global.r().reflector().get_jsobject().get());
}
} }
} }
@ -202,7 +209,7 @@ pub trait DedicatedWorkerGlobalScopeHelpers {
fn process_event(self, msg: ScriptMsg); fn process_event(self, msg: ScriptMsg);
} }
impl<'a> DedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> { impl<'a> DedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope {
fn script_chan(self) -> Box<ScriptChan+Send> { fn script_chan(self) -> Box<ScriptChan+Send> {
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let worker = self.worker.borrow(); let worker = self.worker.borrow();
@ -232,34 +239,37 @@ impl<'a> DedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalSc
trait PrivateDedicatedWorkerGlobalScopeHelpers { trait PrivateDedicatedWorkerGlobalScopeHelpers {
fn handle_event(self, msg: ScriptMsg); fn handle_event(self, msg: ScriptMsg);
fn dispatch_error_to_worker(self, JSRef<ErrorEvent>); fn dispatch_error_to_worker(self, &ErrorEvent);
} }
impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> { impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope {
fn handle_event(self, msg: ScriptMsg) { fn handle_event(self, msg: ScriptMsg) {
match msg { match msg {
ScriptMsg::DOMMessage(data) => { ScriptMsg::DOMMessage(data) => {
let scope: JSRef<WorkerGlobalScope> = WorkerGlobalScopeCast::from_ref(self); let scope = WorkerGlobalScopeCast::from_ref(self);
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self); let target = EventTargetCast::from_ref(self);
let message = data.read(GlobalRef::Worker(scope)); let _ar = JSAutoRequest::new(scope.get_cx());
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message); let _ac = JSAutoCompartment::new(scope.get_cx(), scope.reflector().get_jsobject().get());
let mut message = RootedValue::new(scope.get_cx(), UndefinedValue());
data.read(GlobalRef::Worker(scope), message.handle_mut());
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
}, },
ScriptMsg::RunnableMsg(runnable) => { ScriptMsg::RunnableMsg(runnable) => {
runnable.handler() runnable.handler()
}, },
ScriptMsg::RefcountCleanup(addr) => { ScriptMsg::RefcountCleanup(addr) => {
let scope: JSRef<WorkerGlobalScope> = WorkerGlobalScopeCast::from_ref(self); let scope = WorkerGlobalScopeCast::from_ref(self);
LiveDOMReferences::cleanup(scope.get_cx(), addr); LiveDOMReferences::cleanup(scope.get_cx(), addr);
} }
ScriptMsg::FireTimer(TimerSource::FromWorker, timer_id) => { ScriptMsg::FireTimer(TimerSource::FromWorker, timer_id) => {
let scope: JSRef<WorkerGlobalScope> = WorkerGlobalScopeCast::from_ref(self); let scope = WorkerGlobalScopeCast::from_ref(self);
scope.handle_fire_timer(timer_id); scope.handle_fire_timer(timer_id);
} }
_ => panic!("Unexpected message"), _ => panic!("Unexpected message"),
} }
} }
fn dispatch_error_to_worker(self, errorevent: JSRef<ErrorEvent>) { fn dispatch_error_to_worker(self, errorevent: &ErrorEvent) {
let msg = errorevent.Message(); let msg = errorevent.Message();
let file_name = errorevent.Filename(); let file_name = errorevent.Filename();
let line_num = errorevent.Lineno(); let line_num = errorevent.Lineno();
@ -270,9 +280,9 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerG
} }
} }
impl<'a> DedicatedWorkerGlobalScopeMethods for JSRef<'a, DedicatedWorkerGlobalScope> { impl<'a> DedicatedWorkerGlobalScopeMethods for &'a DedicatedWorkerGlobalScope {
// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage // https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage
fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult { fn PostMessage(self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
let data = try!(StructuredCloneData::write(cx, message)); let data = try!(StructuredCloneData::write(cx, message));
let worker = self.worker.borrow().as_ref().unwrap().clone(); let worker = self.worker.borrow().as_ref().unwrap().clone();
self.parent_sender.send(ScriptMsg::RunnableMsg( self.parent_sender.send(ScriptMsg::RunnableMsg(

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::DocumentFragmentDerived; use dom::bindings::codegen::InheritTypes::DocumentFragmentDerived;
use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast};
use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::js::{JSRef, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::document::Document; use dom::document::Document;
@ -33,40 +33,39 @@ impl DocumentFragmentDerived for EventTarget {
impl DocumentFragment { impl DocumentFragment {
/// Creates a new DocumentFragment. /// Creates a new DocumentFragment.
fn new_inherited(document: JSRef<Document>) -> DocumentFragment { fn new_inherited(document: &Document) -> DocumentFragment {
DocumentFragment { DocumentFragment {
node: Node::new_inherited(NodeTypeId::DocumentFragment, document), node: Node::new_inherited(NodeTypeId::DocumentFragment, document),
} }
} }
pub fn new(document: JSRef<Document>) -> Temporary<DocumentFragment> { pub fn new(document: &Document) -> Root<DocumentFragment> {
Node::reflect_node(box DocumentFragment::new_inherited(document), Node::reflect_node(box DocumentFragment::new_inherited(document),
document, DocumentFragmentBinding::Wrap) document, DocumentFragmentBinding::Wrap)
} }
pub fn Constructor(global: GlobalRef) -> Fallible<Temporary<DocumentFragment>> { pub fn Constructor(global: GlobalRef) -> Fallible<Root<DocumentFragment>> {
let document = global.as_window().Document(); let document = global.as_window().Document();
let document = document.root();
Ok(DocumentFragment::new(document.r())) Ok(DocumentFragment::new(document.r()))
} }
} }
impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> { impl<'a> DocumentFragmentMethods for &'a DocumentFragment {
// https://dom.spec.whatwg.org/#dom-parentnode-children // https://dom.spec.whatwg.org/#dom-parentnode-children
fn Children(self) -> Temporary<HTMLCollection> { fn Children(self) -> Root<HTMLCollection> {
let window = window_from_node(self).root(); let window = window_from_node(self);
HTMLCollection::children(window.r(), NodeCast::from_ref(self)) HTMLCollection::children(window.r(), NodeCast::from_ref(self))
} }
// https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild // https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild
fn GetFirstElementChild(self) -> Option<Temporary<Element>> { fn GetFirstElementChild(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).child_elements().next() NodeCast::from_ref(self).child_elements().next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild // https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
fn GetLastElementChild(self) -> Option<Temporary<Element>> { fn GetLastElementChild(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_temporary).next() NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-childelementcount // https://dom.spec.whatwg.org/#dom-parentnode-childelementcount
@ -85,14 +84,14 @@ impl<'a> DocumentFragmentMethods for JSRef<'a, DocumentFragment> {
} }
// https://dom.spec.whatwg.org/#dom-parentnode-queryselector // https://dom.spec.whatwg.org/#dom-parentnode-queryselector
fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> { fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
let root: JSRef<Node> = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
root.query_selector(selectors) root.query_selector(selectors)
} }
// https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall // https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Temporary<NodeList>> { fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Root<NodeList>> {
let root: JSRef<Node> = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
root.query_selector_all(selectors) root.query_selector_all(selectors)
} }
} }

View file

@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::DocumentTypeBinding::DocumentTypeMethods;
use dom::bindings::codegen::InheritTypes::{DocumentTypeDerived, NodeCast}; use dom::bindings::codegen::InheritTypes::{DocumentTypeDerived, NodeCast};
use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::error::ErrorResult; use dom::bindings::error::ErrorResult;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::node::{Node, NodeHelpers, NodeTypeId}; use dom::node::{Node, NodeHelpers, NodeTypeId};
@ -35,7 +35,7 @@ impl DocumentType {
fn new_inherited(name: DOMString, fn new_inherited(name: DOMString,
public_id: Option<DOMString>, public_id: Option<DOMString>,
system_id: Option<DOMString>, system_id: Option<DOMString>,
document: JSRef<Document>) document: &Document)
-> DocumentType { -> DocumentType {
DocumentType { DocumentType {
node: Node::new_inherited(NodeTypeId::DocumentType, document), node: Node::new_inherited(NodeTypeId::DocumentType, document),
@ -48,8 +48,8 @@ impl DocumentType {
pub fn new(name: DOMString, pub fn new(name: DOMString,
public_id: Option<DOMString>, public_id: Option<DOMString>,
system_id: Option<DOMString>, system_id: Option<DOMString>,
document: JSRef<Document>) document: &Document)
-> Temporary<DocumentType> { -> Root<DocumentType> {
let documenttype = DocumentType::new_inherited(name, let documenttype = DocumentType::new_inherited(name,
public_id, public_id,
system_id, system_id,
@ -73,7 +73,7 @@ impl DocumentType {
} }
} }
impl<'a> DocumentTypeMethods for JSRef<'a, DocumentType> { impl<'a> DocumentTypeMethods for &'a DocumentType {
// https://dom.spec.whatwg.org/#dom-documenttype-name // https://dom.spec.whatwg.org/#dom-documenttype-name
fn Name(self) -> DOMString { fn Name(self) -> DOMString {
self.name.clone() self.name.clone()
@ -106,7 +106,7 @@ impl<'a> DocumentTypeMethods for JSRef<'a, DocumentType> {
// https://dom.spec.whatwg.org/#dom-childnode-remove // https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(self) { fn Remove(self) {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.remove_self(); node.remove_self();
} }
} }

View file

@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::DOMExceptionBinding;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionConstants; use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionConstants;
use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods; use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use util::str::DOMString; use util::str::DOMString;
@ -54,12 +54,12 @@ impl DOMException {
} }
} }
pub fn new(global: GlobalRef, code: DOMErrorName) -> Temporary<DOMException> { pub fn new(global: GlobalRef, code: DOMErrorName) -> Root<DOMException> {
reflect_dom_object(box DOMException::new_inherited(code), global, DOMExceptionBinding::Wrap) reflect_dom_object(box DOMException::new_inherited(code), global, DOMExceptionBinding::Wrap)
} }
} }
impl<'a> DOMExceptionMethods for JSRef<'a, DOMException> { impl<'a> DOMExceptionMethods for &'a DOMException {
// https://heycam.github.io/webidl/#dfn-DOMException // https://heycam.github.io/webidl/#dfn-DOMException
fn Code(self) -> u16 { fn Code(self) -> u16 {
match self.code { match self.code {

View file

@ -10,8 +10,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::InheritTypes::NodeCast; use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, OptionalRootable, Root, Rootable}; use dom::bindings::js::{JS, Root};
use dom::bindings::js::Temporary;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::bindings::utils::validate_qualified_name; use dom::bindings::utils::validate_qualified_name;
use dom::document::{Document, DocumentHelpers, IsHTMLDocument}; use dom::document::{Document, DocumentHelpers, IsHTMLDocument};
@ -21,7 +20,6 @@ use dom::htmlbodyelement::HTMLBodyElement;
use dom::htmlheadelement::HTMLHeadElement; use dom::htmlheadelement::HTMLHeadElement;
use dom::htmlhtmlelement::HTMLHtmlElement; use dom::htmlhtmlelement::HTMLHtmlElement;
use dom::htmltitleelement::HTMLTitleElement; use dom::htmltitleelement::HTMLTitleElement;
use dom::node::Node;
use dom::text::Text; use dom::text::Text;
use util::str::DOMString; use util::str::DOMString;
@ -35,15 +33,15 @@ pub struct DOMImplementation {
} }
impl DOMImplementation { impl DOMImplementation {
fn new_inherited(document: JSRef<Document>) -> DOMImplementation { fn new_inherited(document: &Document) -> DOMImplementation {
DOMImplementation { DOMImplementation {
reflector_: Reflector::new(), reflector_: Reflector::new(),
document: JS::from_rooted(document), document: JS::from_ref(document),
} }
} }
pub fn new(document: JSRef<Document>) -> Temporary<DOMImplementation> { pub fn new(document: &Document) -> Root<DOMImplementation> {
let window = document.window().root(); let window = document.window();
reflect_dom_object(box DOMImplementation::new_inherited(document), reflect_dom_object(box DOMImplementation::new_inherited(document),
GlobalRef::Window(window.r()), GlobalRef::Window(window.r()),
DOMImplementationBinding::Wrap) DOMImplementationBinding::Wrap)
@ -51,10 +49,10 @@ impl DOMImplementation {
} }
// https://dom.spec.whatwg.org/#domimplementation // https://dom.spec.whatwg.org/#domimplementation
impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> { impl<'a> DOMImplementationMethods for &'a DOMImplementation {
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype // https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
fn CreateDocumentType(self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString) fn CreateDocumentType(self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString)
-> Fallible<Temporary<DocumentType>> { -> Fallible<Root<DocumentType>> {
try!(validate_qualified_name(&qualified_name)); try!(validate_qualified_name(&qualified_name));
let document = self.document.root(); let document = self.document.root();
Ok(DocumentType::new(qualified_name, Some(pubid), Some(sysid), document.r())) Ok(DocumentType::new(qualified_name, Some(pubid), Some(sysid), document.r()))
@ -62,15 +60,15 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocument // https://dom.spec.whatwg.org/#dom-domimplementation-createdocument
fn CreateDocument(self, namespace: Option<DOMString>, qname: DOMString, fn CreateDocument(self, namespace: Option<DOMString>, qname: DOMString,
maybe_doctype: Option<JSRef<DocumentType>>) -> Fallible<Temporary<Document>> { maybe_doctype: Option<&DocumentType>) -> Fallible<Root<Document>> {
let doc = self.document.root(); let doc = self.document.root();
let doc = doc.r(); let doc = doc.r();
let win = doc.window().root(); let win = doc.window();
let loader = DocumentLoader::new(&*doc.loader()); let loader = DocumentLoader::new(&*doc.loader());
// Step 1. // Step 1.
let doc = Document::new(win.r(), None, IsHTMLDocument::NonHTMLDocument, let doc = Document::new(win.r(), None, IsHTMLDocument::NonHTMLDocument,
None, None, DocumentSource::NotFromParser, loader).root(); None, None, DocumentSource::NotFromParser, loader);
// Step 2-3. // Step 2-3.
let maybe_elem = if qname.is_empty() { let maybe_elem = if qname.is_empty() {
None None
@ -82,19 +80,19 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
}; };
{ {
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r()); let doc_node = NodeCast::from_ref(doc.r());
// Step 4. // Step 4.
match maybe_doctype { match maybe_doctype {
None => (), None => (),
Some(ref doctype) => { Some(ref doctype) => {
let doc_type: JSRef<Node> = NodeCast::from_ref(*doctype); let doc_type = NodeCast::from_ref(*doctype);
assert!(doc_node.AppendChild(doc_type).is_ok()) assert!(doc_node.AppendChild(doc_type).is_ok())
} }
} }
// Step 5. // Step 5.
match maybe_elem.root() { match maybe_elem {
None => (), None => (),
Some(ref elem) => { Some(ref elem) => {
assert!(doc_node.AppendChild(NodeCast::from_ref(elem.r())).is_ok()) assert!(doc_node.AppendChild(NodeCast::from_ref(elem.r())).is_ok())
@ -106,37 +104,38 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
// FIXME: https://github.com/mozilla/servo/issues/1522 // FIXME: https://github.com/mozilla/servo/issues/1522
// Step 7. // Step 7.
Ok(Temporary::from_rooted(doc.r())) Ok(doc)
} }
// https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
fn CreateHTMLDocument(self, title: Option<DOMString>) -> Temporary<Document> { fn CreateHTMLDocument(self, title: Option<DOMString>) -> Root<Document> {
let document = self.document.root(); let document = self.document.root();
let document = document.r(); let document = document.r();
let win = document.window().root(); let win = document.window();
let loader = DocumentLoader::new(&*document.loader()); let loader = DocumentLoader::new(&*document.loader());
// Step 1-2. // Step 1-2.
let doc = Document::new(win.r(), None, IsHTMLDocument::HTMLDocument, None, None, let doc = Document::new(win.r(), None, IsHTMLDocument::HTMLDocument, None, None,
DocumentSource::NotFromParser, loader).root(); DocumentSource::NotFromParser, loader);
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r());
{ {
// Step 3. // Step 3.
let doc_type = DocumentType::new("html".to_owned(), None, None, doc.r()).root(); let doc_node = NodeCast::from_ref(doc.r());
let doc_type = DocumentType::new("html".to_owned(), None, None, doc.r());
assert!(doc_node.AppendChild(NodeCast::from_ref(doc_type.r())).is_ok()); assert!(doc_node.AppendChild(NodeCast::from_ref(doc_type.r())).is_ok());
} }
{ {
// Step 4. // Step 4.
let doc_html: Root<Node> = NodeCast::from_temporary( let doc_node = NodeCast::from_ref(doc.r());
HTMLHtmlElement::new("html".to_owned(), None, doc.r())).root(); let doc_html = NodeCast::from_root(
HTMLHtmlElement::new("html".to_owned(), None, doc.r()));
assert!(doc_node.AppendChild(doc_html.r()).is_ok()); assert!(doc_node.AppendChild(doc_html.r()).is_ok());
{ {
// Step 5. // Step 5.
let doc_head: Root<Node> = NodeCast::from_temporary( let doc_head = NodeCast::from_root(
HTMLHeadElement::new("head".to_owned(), None, doc.r())).root(); HTMLHeadElement::new("head".to_owned(), None, doc.r()));
assert!(doc_html.r().AppendChild(doc_head.r()).is_ok()); assert!(doc_html.r().AppendChild(doc_head.r()).is_ok());
// Step 6. // Step 6.
@ -144,19 +143,19 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
None => (), None => (),
Some(title_str) => { Some(title_str) => {
// Step 6.1. // Step 6.1.
let doc_title: Root<Node> = NodeCast::from_temporary( let doc_title = NodeCast::from_root(
HTMLTitleElement::new("title".to_owned(), None, doc.r())).root(); HTMLTitleElement::new("title".to_owned(), None, doc.r()));
assert!(doc_head.r().AppendChild(doc_title.r()).is_ok()); assert!(doc_head.r().AppendChild(doc_title.r()).is_ok());
// Step 6.2. // Step 6.2.
let title_text: Root<Text> = Text::new(title_str, doc.r()).root(); let title_text = Text::new(title_str, doc.r());
assert!(doc_title.r().AppendChild(NodeCast::from_ref(title_text.r())).is_ok()); assert!(doc_title.r().AppendChild(NodeCast::from_ref(title_text.r())).is_ok());
} }
} }
} }
// Step 7. // Step 7.
let doc_body: Root<HTMLBodyElement> = HTMLBodyElement::new("body".to_owned(), None, doc.r()).root(); let doc_body = HTMLBodyElement::new("body".to_owned(), None, doc.r());
assert!(doc_html.r().AppendChild(NodeCast::from_ref(doc_body.r())).is_ok()); assert!(doc_html.r().AppendChild(NodeCast::from_ref(doc_body.r())).is_ok());
} }
@ -164,7 +163,7 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
// FIXME: https://github.com/mozilla/servo/issues/1522 // FIXME: https://github.com/mozilla/servo/issues/1522
// Step 9. // Step 9.
Temporary::from_rooted(doc.r()) doc
} }
// https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature // https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature

View file

@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::DOMParserBinding::SupportedType::{Text_htm
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Rootable, Temporary}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::document::{Document, DocumentHelpers, IsHTMLDocument}; use dom::document::{Document, DocumentHelpers, IsHTMLDocument};
use dom::document::DocumentSource; use dom::document::DocumentSource;
@ -27,33 +27,33 @@ pub struct DOMParser {
} }
impl DOMParser { impl DOMParser {
fn new_inherited(window: JSRef<Window>) -> DOMParser { fn new_inherited(window: &Window) -> DOMParser {
DOMParser { DOMParser {
reflector_: Reflector::new(), reflector_: Reflector::new(),
window: JS::from_rooted(window), window: JS::from_ref(window),
} }
} }
pub fn new(window: JSRef<Window>) -> Temporary<DOMParser> { pub fn new(window: &Window) -> Root<DOMParser> {
reflect_dom_object(box DOMParser::new_inherited(window), GlobalRef::Window(window), reflect_dom_object(box DOMParser::new_inherited(window), GlobalRef::Window(window),
DOMParserBinding::Wrap) DOMParserBinding::Wrap)
} }
pub fn Constructor(global: GlobalRef) -> Fallible<Temporary<DOMParser>> { pub fn Constructor(global: GlobalRef) -> Fallible<Root<DOMParser>> {
Ok(DOMParser::new(global.as_window())) Ok(DOMParser::new(global.as_window()))
} }
} }
impl<'a> DOMParserMethods for JSRef<'a, DOMParser> { impl<'a> DOMParserMethods for &'a DOMParser {
// https://domparsing.spec.whatwg.org/#the-domparser-interface // https://domparsing.spec.whatwg.org/#the-domparser-interface
fn ParseFromString(self, fn ParseFromString(self,
s: DOMString, s: DOMString,
ty: DOMParserBinding::SupportedType) ty: DOMParserBinding::SupportedType)
-> Fallible<Temporary<Document>> { -> Fallible<Root<Document>> {
let window = self.window.root(); let window = self.window.root();
let url = window.r().get_url(); let url = window.r().get_url();
let content_type = DOMParserBinding::SupportedTypeValues::strings[ty as usize].to_owned(); let content_type = DOMParserBinding::SupportedTypeValues::strings[ty as usize].to_owned();
let doc = window.r().Document().root(); let doc = window.r().Document();
let doc = doc.r(); let doc = doc.r();
let loader = DocumentLoader::new(&*doc.loader()); let loader = DocumentLoader::new(&*doc.loader());
match ty { match ty {
@ -63,10 +63,10 @@ impl<'a> DOMParserMethods for JSRef<'a, DOMParser> {
Some(content_type), Some(content_type),
None, None,
DocumentSource::FromParser, DocumentSource::FromParser,
loader).root(); loader);
parse_html(document.r(), s, &url, ParseContext::Owner(None)); parse_html(document.r(), s, &url, ParseContext::Owner(None));
document.r().set_ready_state(DocumentReadyState::Complete); document.r().set_ready_state(DocumentReadyState::Complete);
Ok(Temporary::from_rooted(document.r())) Ok(document)
} }
Text_xml => { Text_xml => {
//FIXME: this should probably be FromParser when we actually parse the string (#3756). //FIXME: this should probably be FromParser when we actually parse the string (#3756).

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::DOMRectBinding; use dom::bindings::codegen::Bindings::DOMRectBinding;
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods; use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::bindings::num::Finite; use dom::bindings::num::Finite;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::window::Window; use dom::window::Window;
@ -32,15 +32,15 @@ impl DOMRect {
} }
} }
pub fn new(window: JSRef<Window>, pub fn new(window: &Window,
top: Au, bottom: Au, top: Au, bottom: Au,
left: Au, right: Au) -> Temporary<DOMRect> { left: Au, right: Au) -> Root<DOMRect> {
reflect_dom_object(box DOMRect::new_inherited(top, bottom, left, right), reflect_dom_object(box DOMRect::new_inherited(top, bottom, left, right),
GlobalRef::Window(window), DOMRectBinding::Wrap) GlobalRef::Window(window), DOMRectBinding::Wrap)
} }
} }
impl<'a> DOMRectMethods for JSRef<'a, DOMRect> { impl<'a> DOMRectMethods for &'a DOMRect {
fn Top(self) -> Finite<f32> { fn Top(self) -> Finite<f32> {
Finite::wrap(self.top) Finite::wrap(self.top)
} }

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::DOMRectListBinding; use dom::bindings::codegen::Bindings::DOMRectListBinding;
use dom::bindings::codegen::Bindings::DOMRectListBinding::DOMRectListMethods; use dom::bindings::codegen::Bindings::DOMRectListBinding::DOMRectListMethods;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::domrect::DOMRect; use dom::domrect::DOMRect;
use dom::window::Window; use dom::window::Window;
@ -18,37 +18,37 @@ pub struct DOMRectList {
} }
impl DOMRectList { impl DOMRectList {
fn new_inherited<T>(window: JSRef<Window>, rects: T) -> DOMRectList fn new_inherited<T>(window: &Window, rects: T) -> DOMRectList
where T: Iterator<Item=Temporary<DOMRect>> { where T: Iterator<Item=Root<DOMRect>> {
DOMRectList { DOMRectList {
reflector_: Reflector::new(), reflector_: Reflector::new(),
rects: rects.map(JS::from_rooted).collect(), rects: rects.map(|r| JS::from_rooted(&r)).collect(),
window: JS::from_rooted(window), window: JS::from_ref(window),
} }
} }
pub fn new<T>(window: JSRef<Window>, rects: T) -> Temporary<DOMRectList> pub fn new<T>(window: &Window, rects: T) -> Root<DOMRectList>
where T: Iterator<Item=Temporary<DOMRect>> { where T: Iterator<Item=Root<DOMRect>> {
reflect_dom_object(box DOMRectList::new_inherited(window, rects), reflect_dom_object(box DOMRectList::new_inherited(window, rects),
GlobalRef::Window(window), DOMRectListBinding::Wrap) GlobalRef::Window(window), DOMRectListBinding::Wrap)
} }
} }
impl<'a> DOMRectListMethods for JSRef<'a, DOMRectList> { impl<'a> DOMRectListMethods for &'a DOMRectList {
fn Length(self) -> u32 { fn Length(self) -> u32 {
self.rects.len() as u32 self.rects.len() as u32
} }
fn Item(self, index: u32) -> Option<Temporary<DOMRect>> { fn Item(self, index: u32) -> Option<Root<DOMRect>> {
let rects = &self.rects; let rects = &self.rects;
if index < rects.len() as u32 { if index < rects.len() as u32 {
Some(Temporary::from_rooted(rects[index as usize].clone())) Some(rects[index as usize].root())
} else { } else {
None None
} }
} }
fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<Temporary<DOMRect>> { fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<Root<DOMRect>> {
*found = index < self.rects.len() as u32; *found = index < self.rects.len() as u32;
self.Item(index) self.Item(index)
} }

View file

@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::DOMStringMapBinding;
use dom::bindings::codegen::Bindings::DOMStringMapBinding::DOMStringMapMethods; use dom::bindings::codegen::Bindings::DOMStringMapBinding::DOMStringMapMethods;
use dom::bindings::error::ErrorResult; use dom::bindings::error::ErrorResult;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Rootable, Temporary}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::node::window_from_node; use dom::node::window_from_node;
use dom::htmlelement::{HTMLElement, HTMLElementCustomAttributeHelpers}; use dom::htmlelement::{HTMLElement, HTMLElementCustomAttributeHelpers};
@ -19,22 +19,22 @@ pub struct DOMStringMap {
} }
impl DOMStringMap { impl DOMStringMap {
fn new_inherited(element: JSRef<HTMLElement>) -> DOMStringMap { fn new_inherited(element: &HTMLElement) -> DOMStringMap {
DOMStringMap { DOMStringMap {
reflector_: Reflector::new(), reflector_: Reflector::new(),
element: JS::from_rooted(element), element: JS::from_ref(element),
} }
} }
pub fn new(element: JSRef<HTMLElement>) -> Temporary<DOMStringMap> { pub fn new(element: &HTMLElement) -> Root<DOMStringMap> {
let window = window_from_node(element).root(); let window = window_from_node(element);
reflect_dom_object(box DOMStringMap::new_inherited(element), reflect_dom_object(box DOMStringMap::new_inherited(element),
GlobalRef::Window(window.r()), DOMStringMapBinding::Wrap) GlobalRef::Window(window.r()), DOMStringMapBinding::Wrap)
} }
} }
// https://html.spec.whatwg.org/#domstringmap // https://html.spec.whatwg.org/#domstringmap
impl<'a> DOMStringMapMethods for JSRef<'a, DOMStringMap> { impl<'a> DOMStringMapMethods for &'a DOMStringMap {
fn NamedCreator(self, name: DOMString, value: DOMString) -> ErrorResult { fn NamedCreator(self, name: DOMString, value: DOMString) -> ErrorResult {
self.NamedSetter(name, value) self.NamedSetter(name, value)
} }

View file

@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods;
use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::error::Error::{InvalidCharacter, Syntax}; use dom::bindings::error::Error::{InvalidCharacter, Syntax};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, OptionalRootable, Rootable, Temporary}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers}; use dom::element::{Element, AttributeHandlers};
use dom::node::window_from_node; use dom::node::window_from_node;
@ -26,16 +26,16 @@ pub struct DOMTokenList {
} }
impl DOMTokenList { impl DOMTokenList {
pub fn new_inherited(element: JSRef<Element>, local_name: Atom) -> DOMTokenList { pub fn new_inherited(element: &Element, local_name: Atom) -> DOMTokenList {
DOMTokenList { DOMTokenList {
reflector_: Reflector::new(), reflector_: Reflector::new(),
element: JS::from_rooted(element), element: JS::from_ref(element),
local_name: local_name, local_name: local_name,
} }
} }
pub fn new(element: JSRef<Element>, local_name: &Atom) -> Temporary<DOMTokenList> { pub fn new(element: &Element, local_name: &Atom) -> Root<DOMTokenList> {
let window = window_from_node(element).root(); let window = window_from_node(element);
reflect_dom_object(box DOMTokenList::new_inherited(element, local_name.clone()), reflect_dom_object(box DOMTokenList::new_inherited(element, local_name.clone()),
GlobalRef::Window(window.r()), GlobalRef::Window(window.r()),
DOMTokenListBinding::Wrap) DOMTokenListBinding::Wrap)
@ -43,12 +43,12 @@ impl DOMTokenList {
} }
trait PrivateDOMTokenListHelpers { trait PrivateDOMTokenListHelpers {
fn attribute(self) -> Option<Temporary<Attr>>; fn attribute(self) -> Option<Root<Attr>>;
fn check_token_exceptions(self, token: &str) -> Fallible<Atom>; fn check_token_exceptions(self, token: &str) -> Fallible<Atom>;
} }
impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> { impl<'a> PrivateDOMTokenListHelpers for &'a DOMTokenList {
fn attribute(self) -> Option<Temporary<Attr>> { fn attribute(self) -> Option<Root<Attr>> {
let element = self.element.root(); let element = self.element.root();
element.r().get_attribute(&ns!(""), &self.local_name) element.r().get_attribute(&ns!(""), &self.local_name)
} }
@ -63,10 +63,10 @@ impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> {
} }
// https://dom.spec.whatwg.org/#domtokenlist // https://dom.spec.whatwg.org/#domtokenlist
impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> { impl<'a> DOMTokenListMethods for &'a DOMTokenList {
// https://dom.spec.whatwg.org/#dom-domtokenlist-length // https://dom.spec.whatwg.org/#dom-domtokenlist-length
fn Length(self) -> u32 { fn Length(self) -> u32 {
self.attribute().root().map(|attr| { self.attribute().map(|attr| {
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r(); let attr = attr.r();
let value = attr.value(); let value = attr.value();
@ -76,7 +76,7 @@ impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
// https://dom.spec.whatwg.org/#dom-domtokenlist-item // https://dom.spec.whatwg.org/#dom-domtokenlist-item
fn Item(self, index: u32) -> Option<DOMString> { fn Item(self, index: u32) -> Option<DOMString> {
self.attribute().root().and_then(|attr| { self.attribute().and_then(|attr| {
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r(); let attr = attr.r();
let value = attr.value(); let value = attr.value();
@ -95,7 +95,7 @@ impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
// https://dom.spec.whatwg.org/#dom-domtokenlist-contains // https://dom.spec.whatwg.org/#dom-domtokenlist-contains
fn Contains(self, token: DOMString) -> Fallible<bool> { fn Contains(self, token: DOMString) -> Fallible<bool> {
self.check_token_exceptions(&token).map(|token| { self.check_token_exceptions(&token).map(|token| {
self.attribute().root().map(|attr| { self.attribute().map(|attr| {
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r(); let attr = attr.r();
let value = attr.value(); let value = attr.value();

View file

@ -29,9 +29,8 @@ use dom::bindings::codegen::UnionTypes::NodeOrString;
use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::error::Error::{InvalidCharacter, Syntax}; use dom::bindings::error::Error::{InvalidCharacter, Syntax};
use dom::bindings::error::Error::NoModificationAllowed; use dom::bindings::error::Error::NoModificationAllowed;
use dom::bindings::js::{JS, JSRef, LayoutJS, MutNullableHeap}; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
use dom::bindings::js::{OptionalRootable, Rootable, RootedReference}; use dom::bindings::js::{Root, RootedReference};
use dom::bindings::js::{Temporary, TemporaryPushable};
use dom::bindings::trace::RootedVec; use dom::bindings::trace::RootedVec;
use dom::bindings::utils::{xml_name_type, validate_and_extract}; use dom::bindings::utils::{xml_name_type, validate_and_extract};
use dom::bindings::utils::XMLName::InvalidXMLName; use dom::bindings::utils::XMLName::InvalidXMLName;
@ -42,7 +41,6 @@ use dom::document::{Document, DocumentHelpers, LayoutDocumentHelpers};
use dom::domtokenlist::DOMTokenList; use dom::domtokenlist::DOMTokenList;
use dom::event::{Event, EventHelpers}; use dom::event::{Event, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlanchorelement::HTMLAnchorElement;
use dom::htmlbodyelement::{HTMLBodyElement, HTMLBodyElementHelpers}; use dom::htmlbodyelement::{HTMLBodyElement, HTMLBodyElementHelpers};
use dom::htmlcollection::HTMLCollection; use dom::htmlcollection::HTMLCollection;
use dom::htmlelement::HTMLElementTypeId; use dom::htmlelement::HTMLElementTypeId;
@ -113,6 +111,12 @@ impl ElementDerived for EventTarget {
} }
} }
impl PartialEq for Element {
fn eq(&self, other: &Element) -> bool {
self as *const Element == &*other
}
}
#[derive(Copy, Clone, PartialEq, Debug)] #[derive(Copy, Clone, PartialEq, Debug)]
#[jstraceable] #[jstraceable]
pub enum ElementTypeId { pub enum ElementTypeId {
@ -131,14 +135,14 @@ pub enum ElementCreator {
// //
impl Element { impl Element {
pub fn create(name: QualName, prefix: Option<Atom>, pub fn create(name: QualName, prefix: Option<Atom>,
document: JSRef<Document>, creator: ElementCreator) document: &Document, creator: ElementCreator)
-> Temporary<Element> { -> Root<Element> {
create_element(name, prefix, document, creator) create_element(name, prefix, document, creator)
} }
pub fn new_inherited(type_id: ElementTypeId, local_name: DOMString, pub fn new_inherited(type_id: ElementTypeId, local_name: DOMString,
namespace: Namespace, prefix: Option<DOMString>, namespace: Namespace, prefix: Option<DOMString>,
document: JSRef<Document>) -> Element { document: &Document) -> Element {
Element { Element {
node: Node::new_inherited(NodeTypeId::Element(type_id), document), node: Node::new_inherited(NodeTypeId::Element(type_id), document),
local_name: Atom::from_slice(&local_name), local_name: Atom::from_slice(&local_name),
@ -154,7 +158,7 @@ impl Element {
pub fn new(local_name: DOMString, pub fn new(local_name: DOMString,
namespace: Namespace, namespace: Namespace,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<Element> { document: &Document) -> Root<Element> {
Node::reflect_node( Node::reflect_node(
box Element::new_inherited(ElementTypeId::Element, local_name, namespace, prefix, document), box Element::new_inherited(ElementTypeId::Element, local_name, namespace, prefix, document),
document, document,
@ -181,8 +185,6 @@ pub trait RawLayoutElementHelpers {
-> Option<u32>; -> Option<u32>;
fn local_name<'a>(&'a self) -> &'a Atom; fn local_name<'a>(&'a self) -> &'a Atom;
fn namespace<'a>(&'a self) -> &'a Namespace;
fn style_attribute<'a>(&'a self) -> &'a DOMRefCell<Option<PropertyDeclarationBlock>>;
} }
#[inline] #[inline]
@ -504,14 +506,6 @@ impl RawLayoutElementHelpers for Element {
fn local_name<'a>(&'a self) -> &'a Atom { fn local_name<'a>(&'a self) -> &'a Atom {
&self.local_name &self.local_name
} }
fn namespace<'a>(&'a self) -> &'a Namespace {
&self.namespace
}
fn style_attribute<'a>(&'a self) -> &'a DOMRefCell<Option<PropertyDeclarationBlock>> {
&self.style_attribute
}
} }
pub trait LayoutElementHelpers { pub trait LayoutElementHelpers {
@ -560,18 +554,18 @@ pub trait ElementHelpers<'a> {
fn get_inline_style_declaration(self, property: &Atom) -> Option<PropertyDeclaration>; fn get_inline_style_declaration(self, property: &Atom) -> Option<PropertyDeclaration>;
fn get_important_inline_style_declaration(self, property: &Atom) -> Option<PropertyDeclaration>; fn get_important_inline_style_declaration(self, property: &Atom) -> Option<PropertyDeclaration>;
fn serialize(self, traversal_scope: TraversalScope) -> Fallible<DOMString>; fn serialize(self, traversal_scope: TraversalScope) -> Fallible<DOMString>;
fn get_root_element(self) -> Temporary<Element>; fn get_root_element(self) -> Root<Element>;
fn lookup_prefix(self, namespace: Namespace) -> Option<DOMString>; fn lookup_prefix(self, namespace: Namespace) -> Option<DOMString>;
} }
impl<'a> ElementHelpers<'a> for JSRef<'a, Element> { impl<'a> ElementHelpers<'a> for &'a Element {
fn html_element_in_html_document(self) -> bool { fn html_element_in_html_document(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
self.namespace == ns!(HTML) && node.is_in_html_doc() self.namespace == ns!(HTML) && node.is_in_html_doc()
} }
fn local_name(self) -> &'a Atom { fn local_name(self) -> &'a Atom {
&self.extended_deref().local_name &self.local_name
} }
fn parsed_name(self, name: DOMString) -> DOMString { fn parsed_name(self, name: DOMString) -> DOMString {
@ -583,30 +577,30 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
} }
fn namespace(self) -> &'a Namespace { fn namespace(self) -> &'a Namespace {
&self.extended_deref().namespace &self.namespace
} }
fn prefix(self) -> &'a Option<DOMString> { fn prefix(self) -> &'a Option<DOMString> {
&self.extended_deref().prefix &self.prefix
} }
fn attrs(&self) -> Ref<Vec<JS<Attr>>> { fn attrs(&self) -> Ref<Vec<JS<Attr>>> {
self.extended_deref().attrs.borrow() self.attrs.borrow()
} }
fn attrs_mut(&self) -> RefMut<Vec<JS<Attr>>> { fn attrs_mut(&self) -> RefMut<Vec<JS<Attr>>> {
self.extended_deref().attrs.borrow_mut() self.attrs.borrow_mut()
} }
fn style_attribute(self) -> &'a DOMRefCell<Option<PropertyDeclarationBlock>> { fn style_attribute(self) -> &'a DOMRefCell<Option<PropertyDeclarationBlock>> {
&self.extended_deref().style_attribute &self.style_attribute
} }
fn summarize(self) -> Vec<AttrInfo> { fn summarize(self) -> Vec<AttrInfo> {
let attrs = self.Attributes().root(); let attrs = self.Attributes();
let mut summarized = vec!(); let mut summarized = vec!();
for i in 0..attrs.r().Length() { for i in 0..attrs.r().Length() {
let attr = attrs.r().Item(i).unwrap().root(); let attr = attrs.r().Item(i).unwrap();
summarized.push(attr.r().summarize()); summarized.push(attr.r().summarize());
} }
summarized summarized
@ -702,7 +696,7 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
} }
fn serialize(self, traversal_scope: TraversalScope) -> Fallible<DOMString> { fn serialize(self, traversal_scope: TraversalScope) -> Fallible<DOMString> {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let mut writer = vec![]; let mut writer = vec![];
match serialize(&mut writer, &node, match serialize(&mut writer, &node,
SerializeOpts { SerializeOpts {
@ -715,10 +709,10 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
} }
// https://html.spec.whatwg.org/multipage/#root-element // https://html.spec.whatwg.org/multipage/#root-element
fn get_root_element(self) -> Temporary<Element> { fn get_root_element(self) -> Root<Element> {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.inclusive_ancestors() node.inclusive_ancestors()
.filter_map(ElementCast::to_temporary) .filter_map(ElementCast::to_root)
.last() .last()
.expect("We know inclusive_ancestors will return `self` which is an element") .expect("We know inclusive_ancestors will return `self` which is an element")
} }
@ -726,7 +720,7 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
// https://dom.spec.whatwg.org/#locate-a-namespace-prefix // https://dom.spec.whatwg.org/#locate-a-namespace-prefix
fn lookup_prefix(self, namespace: Namespace) -> Option<DOMString> { fn lookup_prefix(self, namespace: Namespace) -> Option<DOMString> {
for node in NodeCast::from_ref(self).inclusive_ancestors() { for node in NodeCast::from_ref(self).inclusive_ancestors() {
match ElementCast::to_ref(node.root().r()) { match ElementCast::to_ref(node.r()) {
Some(element) => { Some(element) => {
// Step 1. // Step 1.
if *element.namespace() == namespace { if *element.namespace() == namespace {
@ -736,9 +730,9 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
} }
// Step 2. // Step 2.
let attrs = element.Attributes().root(); let attrs = element.Attributes();
for i in 0..attrs.r().Length() { for i in 0..attrs.r().Length() {
let attr = attrs.r().Item(i).unwrap().root(); let attr = attrs.r().Item(i).unwrap();
if *attr.r().prefix() == Some(atom!("xmlns")) && if *attr.r().prefix() == Some(atom!("xmlns")) &&
**attr.r().value() == *namespace.0 { **attr.r().value() == *namespace.0 {
return Some(attr.r().LocalName()); return Some(attr.r().LocalName());
@ -760,13 +754,13 @@ pub trait FocusElementHelpers {
fn is_actually_disabled(self) -> bool; fn is_actually_disabled(self) -> bool;
} }
impl<'a> FocusElementHelpers for JSRef<'a, Element> { impl<'a> FocusElementHelpers for &'a Element {
fn is_focusable_area(self) -> bool { fn is_focusable_area(self) -> bool {
if self.is_actually_disabled() { if self.is_actually_disabled() {
return false; return false;
} }
// TODO: Check whether the element is being rendered (i.e. not hidden). // TODO: Check whether the element is being rendered (i.e. not hidden).
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
if node.get_flag(SEQUENTIALLY_FOCUSABLE) { if node.get_flag(SEQUENTIALLY_FOCUSABLE) {
return true; return true;
} }
@ -783,7 +777,7 @@ impl<'a> FocusElementHelpers for JSRef<'a, Element> {
} }
fn is_actually_disabled(self) -> bool { fn is_actually_disabled(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
match node.type_id() { match node.type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) | NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) | NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) |
@ -805,10 +799,10 @@ pub trait AttributeHandlers {
/// Returns the attribute with given namespace and case-sensitive local /// Returns the attribute with given namespace and case-sensitive local
/// name, if any. /// name, if any.
fn get_attribute(self, namespace: &Namespace, local_name: &Atom) fn get_attribute(self, namespace: &Namespace, local_name: &Atom)
-> Option<Temporary<Attr>>; -> Option<Root<Attr>>;
/// Returns the first attribute with any namespace and given case-sensitive /// Returns the first attribute with any namespace and given case-sensitive
/// name, if any. /// name, if any.
fn get_attribute_by_name(self, name: DOMString) -> Option<Temporary<Attr>>; fn get_attribute_by_name(self, name: DOMString) -> Option<Root<Attr>>;
fn get_attributes(self, local_name: &Atom, attributes: &mut RootedVec<JS<Attr>>); fn get_attributes(self, local_name: &Atom, attributes: &mut RootedVec<JS<Attr>>);
fn set_attribute_from_parser(self, fn set_attribute_from_parser(self,
name: QualName, name: QualName,
@ -819,19 +813,19 @@ pub trait AttributeHandlers {
fn do_set_attribute<F>(self, local_name: Atom, value: AttrValue, fn do_set_attribute<F>(self, local_name: Atom, value: AttrValue,
name: Atom, namespace: Namespace, name: Atom, namespace: Namespace,
prefix: Option<Atom>, cb: F) prefix: Option<Atom>, cb: F)
where F: Fn(JSRef<Attr>) -> bool; where F: Fn(&Attr) -> bool;
fn parse_attribute(self, namespace: &Namespace, local_name: &Atom, fn parse_attribute(self, namespace: &Namespace, local_name: &Atom,
value: DOMString) -> AttrValue; value: DOMString) -> AttrValue;
/// Removes the first attribute with any given namespace and case-sensitive local /// Removes the first attribute with any given namespace and case-sensitive local
/// name, if any. /// name, if any.
fn remove_attribute(self, namespace: &Namespace, local_name: &Atom) fn remove_attribute(self, namespace: &Namespace, local_name: &Atom)
-> Option<Temporary<Attr>>; -> Option<Root<Attr>>;
/// Removes the first attribute with any namespace and given case-sensitive name. /// Removes the first attribute with any namespace and given case-sensitive name.
fn remove_attribute_by_name(self, name: &Atom) -> Option<Temporary<Attr>>; fn remove_attribute_by_name(self, name: &Atom) -> Option<Root<Attr>>;
/// Removes the first attribute that satisfies `find`. /// Removes the first attribute that satisfies `find`.
fn do_remove_attribute<F>(self, find: F) -> Option<Temporary<Attr>> fn do_remove_attribute<F>(self, find: F) -> Option<Root<Attr>>
where F: Fn(JSRef<Attr>) -> bool; where F: Fn(&Attr) -> bool;
fn has_class(self, name: &Atom) -> bool; fn has_class(self, name: &Atom) -> bool;
@ -851,36 +845,34 @@ pub trait AttributeHandlers {
fn set_uint_attribute(self, local_name: &Atom, value: u32); fn set_uint_attribute(self, local_name: &Atom, value: u32);
} }
impl<'a> AttributeHandlers for JSRef<'a, Element> { impl<'a> AttributeHandlers for &'a Element {
fn get_attribute(self, namespace: &Namespace, local_name: &Atom) -> Option<Temporary<Attr>> { fn get_attribute(self, namespace: &Namespace, local_name: &Atom) -> Option<Root<Attr>> {
let mut attributes = RootedVec::new(); let mut attributes = RootedVec::new();
self.get_attributes(local_name, &mut attributes); self.get_attributes(local_name, &mut attributes);
attributes.iter() attributes.iter()
.map(|attr| attr.root()) .map(|attr| attr.root())
.find(|attr| attr.r().namespace() == namespace) .find(|attr| attr.r().namespace() == namespace)
.map(|x| Temporary::from_rooted(x.r()))
} }
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name // https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
fn get_attribute_by_name(self, name: DOMString) -> Option<Temporary<Attr>> { fn get_attribute_by_name(self, name: DOMString) -> Option<Root<Attr>> {
let name = &Atom::from_slice(&self.parsed_name(name)); let name = &Atom::from_slice(&self.parsed_name(name));
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attrs = self.attrs.borrow(); let attrs = self.attrs.borrow();
attrs.iter().map(|attr| attr.root()) attrs.iter().map(|attr| attr.root())
.find(|a| a.r().name() == name) .find(|a| a.r().name() == name)
.map(|x| Temporary::from_rooted(x.r()))
} }
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name // https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
fn get_attributes(self, local_name: &Atom, attributes: &mut RootedVec<JS<Attr>>) { fn get_attributes(self, local_name: &Atom, attributes: &mut RootedVec<JS<Attr>>) {
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attrs = self.attrs.borrow(); let attrs = self.attrs.borrow();
for ref attr in attrs.iter().map(|attr| attr.root()) { for ref attr in attrs.iter() {
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r(); let attr = attr.root();
let attr_local_name = attr.local_name(); let attr_local_name = attr.r().local_name();
if attr_local_name == local_name { if attr_local_name == local_name {
attributes.push(JS::from_rooted(attr)); attributes.push(JS::from_rooted(&attr));
} }
} }
} }
@ -938,7 +930,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
namespace: Namespace, namespace: Namespace,
prefix: Option<Atom>, prefix: Option<Atom>,
cb: F) cb: F)
where F: Fn(JSRef<Attr>) -> bool where F: Fn(&Attr) -> bool
{ {
let idx = self.attrs.borrow().iter() let idx = self.attrs.borrow().iter()
.map(|attr| attr.root()) .map(|attr| attr.root())
@ -946,10 +938,10 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
let (idx, set_type) = match idx { let (idx, set_type) = match idx {
Some(idx) => (idx, AttrSettingType::ReplacedAttr), Some(idx) => (idx, AttrSettingType::ReplacedAttr),
None => { None => {
let window = window_from_node(self).root(); let window = window_from_node(self);
let attr = Attr::new(window.r(), local_name, value.clone(), let attr = Attr::new(window.r(), local_name, value.clone(),
name, namespace.clone(), prefix, Some(self)); name, namespace.clone(), prefix, Some(self));
self.attrs.borrow_mut().push_unrooted(&attr); self.attrs.borrow_mut().push(JS::from_rooted(&attr));
(self.attrs.borrow().len() - 1, AttrSettingType::FirstSetAttr) (self.attrs.borrow().len() - 1, AttrSettingType::FirstSetAttr)
} }
}; };
@ -968,18 +960,18 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
} }
fn remove_attribute(self, namespace: &Namespace, local_name: &Atom) fn remove_attribute(self, namespace: &Namespace, local_name: &Atom)
-> Option<Temporary<Attr>> { -> Option<Root<Attr>> {
self.do_remove_attribute(|attr| { self.do_remove_attribute(|attr| {
attr.namespace() == namespace && attr.local_name() == local_name attr.namespace() == namespace && attr.local_name() == local_name
}) })
} }
fn remove_attribute_by_name(self, name: &Atom) -> Option<Temporary<Attr>> { fn remove_attribute_by_name(self, name: &Atom) -> Option<Root<Attr>> {
self.do_remove_attribute(|attr| attr.name() == name) self.do_remove_attribute(|attr| attr.name() == name)
} }
fn do_remove_attribute<F>(self, find: F) -> Option<Temporary<Attr>> fn do_remove_attribute<F>(self, find: F) -> Option<Root<Attr>>
where F: Fn(JSRef<Attr>) -> bool where F: Fn(&Attr) -> bool
{ {
let idx = self.attrs.borrow().iter() let idx = self.attrs.borrow().iter()
.map(|attr| attr.root()) .map(|attr| attr.root())
@ -997,9 +989,9 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
vtable_for(&NodeCast::from_ref(self)).after_remove_attr(attr.r().name()); vtable_for(&NodeCast::from_ref(self)).after_remove_attr(attr.r().name());
} }
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
if node.is_in_doc() { if node.is_in_doc() {
let document = document_from_node(self).root(); let document = document_from_node(self);
let damage = if attr.r().local_name() == &atom!("style") { let damage = if attr.r().local_name() == &atom!("style") {
NodeDamage::NodeStyleDamaged NodeDamage::NodeStyleDamaged
} else { } else {
@ -1007,21 +999,21 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
}; };
document.r().content_changed(node, damage); document.r().content_changed(node, damage);
} }
Temporary::from_rooted(attr.r()) attr
}) })
} }
fn has_class(self, name: &Atom) -> bool { fn has_class(self, name: &Atom) -> bool {
let quirks_mode = { let quirks_mode = {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let owner_doc = node.owner_doc().root(); let owner_doc = node.owner_doc();
owner_doc.r().quirks_mode() owner_doc.r().quirks_mode()
}; };
let is_equal = |lhs: &Atom, rhs: &Atom| match quirks_mode { let is_equal = |lhs: &Atom, rhs: &Atom| match quirks_mode {
NoQuirks | LimitedQuirks => lhs == rhs, NoQuirks | LimitedQuirks => lhs == rhs,
Quirks => lhs.eq_ignore_ascii_case(&rhs) Quirks => lhs.eq_ignore_ascii_case(&rhs)
}; };
self.get_attribute(&ns!(""), &atom!("class")).root().map(|attr| { self.get_attribute(&ns!(""), &atom!("class")).map(|attr| {
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r(); let attr = attr.r();
let value = attr.value(); let value = attr.value();
@ -1063,7 +1055,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
return "".to_owned(); return "".to_owned();
} }
let url = self.get_string_attribute(local_name); let url = self.get_string_attribute(local_name);
let doc = document_from_node(self).root(); let doc = document_from_node(self);
let base = doc.r().url(); let base = doc.r().url();
// https://html.spec.whatwg.org/multipage/#reflect // https://html.spec.whatwg.org/multipage/#reflect
// XXXManishearth this doesn't handle `javascript:` urls properly // XXXManishearth this doesn't handle `javascript:` urls properly
@ -1078,7 +1070,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
fn get_string_attribute(self, local_name: &Atom) -> DOMString { fn get_string_attribute(self, local_name: &Atom) -> DOMString {
match self.get_attribute(&ns!(""), local_name) { match self.get_attribute(&ns!(""), local_name) {
Some(x) => x.root().r().Value(), Some(x) => x.r().Value(),
None => "".to_owned() None => "".to_owned()
} }
} }
@ -1088,7 +1080,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
} }
fn get_tokenlist_attribute(self, local_name: &Atom) -> Vec<Atom> { fn get_tokenlist_attribute(self, local_name: &Atom) -> Vec<Atom> {
self.get_attribute(&ns!(""), local_name).root().map(|attr| { self.get_attribute(&ns!(""), local_name).map(|attr| {
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r(); let attr = attr.r();
let value = attr.value(); let value = attr.value();
@ -1112,7 +1104,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
assert!(local_name.chars().all(|ch| { assert!(local_name.chars().all(|ch| {
!ch.is_ascii() || ch.to_ascii_lowercase() == ch !ch.is_ascii() || ch.to_ascii_lowercase() == ch
})); }));
let attribute = self.get_attribute(&ns!(""), local_name).root(); let attribute = self.get_attribute(&ns!(""), local_name);
match attribute { match attribute {
Some(ref attribute) => { Some(ref attribute) => {
match *attribute.r().value() { match *attribute.r().value() {
@ -1130,7 +1122,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
} }
} }
impl<'a> ElementMethods for JSRef<'a, Element> { impl<'a> ElementMethods for &'a Element {
// https://dom.spec.whatwg.org/#dom-element-namespaceuri // https://dom.spec.whatwg.org/#dom-element-namespaceuri
fn GetNamespaceURI(self) -> Option<DOMString> { fn GetNamespaceURI(self) -> Option<DOMString> {
match self.namespace { match self.namespace {
@ -1185,25 +1177,25 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
} }
// https://dom.spec.whatwg.org/#dom-element-classlist // https://dom.spec.whatwg.org/#dom-element-classlist
fn ClassList(self) -> Temporary<DOMTokenList> { fn ClassList(self) -> Root<DOMTokenList> {
self.class_list.or_init(|| DOMTokenList::new(self, &atom!("class"))) self.class_list.or_init(|| DOMTokenList::new(self, &atom!("class")))
} }
// https://dom.spec.whatwg.org/#dom-element-attributes // https://dom.spec.whatwg.org/#dom-element-attributes
fn Attributes(self) -> Temporary<NamedNodeMap> { fn Attributes(self) -> Root<NamedNodeMap> {
self.attr_list.or_init(|| { self.attr_list.or_init(|| {
let doc = { let doc = {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.owner_doc().root() node.owner_doc()
}; };
let window = doc.r().window().root(); let window = doc.r().window();
NamedNodeMap::new(window.r(), self) NamedNodeMap::new(window.r(), self)
}) })
} }
// https://dom.spec.whatwg.org/#dom-element-getattribute // https://dom.spec.whatwg.org/#dom-element-getattribute
fn GetAttribute(self, name: DOMString) -> Option<DOMString> { fn GetAttribute(self, name: DOMString) -> Option<DOMString> {
self.get_attribute_by_name(name).root() self.get_attribute_by_name(name)
.map(|s| s.r().Value()) .map(|s| s.r().Value())
} }
@ -1212,7 +1204,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
namespace: Option<DOMString>, namespace: Option<DOMString>,
local_name: DOMString) -> Option<DOMString> { local_name: DOMString) -> Option<DOMString> {
let namespace = &namespace::from_domstring(namespace); let namespace = &namespace::from_domstring(namespace);
self.get_attribute(namespace, &Atom::from_slice(&local_name)).root() self.get_attribute(namespace, &Atom::from_slice(&local_name))
.map(|attr| attr.r().Value()) .map(|attr| attr.r().Value())
} }
@ -1282,28 +1274,28 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
} }
// https://dom.spec.whatwg.org/#dom-element-getelementsbytagname // https://dom.spec.whatwg.org/#dom-element-getelementsbytagname
fn GetElementsByTagName(self, localname: DOMString) -> Temporary<HTMLCollection> { fn GetElementsByTagName(self, localname: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self).root(); let window = window_from_node(self);
HTMLCollection::by_tag_name(window.r(), NodeCast::from_ref(self), localname) HTMLCollection::by_tag_name(window.r(), NodeCast::from_ref(self), localname)
} }
// https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens // https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens
fn GetElementsByTagNameNS(self, maybe_ns: Option<DOMString>, fn GetElementsByTagNameNS(self, maybe_ns: Option<DOMString>,
localname: DOMString) -> Temporary<HTMLCollection> { localname: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self).root(); let window = window_from_node(self);
HTMLCollection::by_tag_name_ns(window.r(), NodeCast::from_ref(self), localname, maybe_ns) HTMLCollection::by_tag_name_ns(window.r(), NodeCast::from_ref(self), localname, maybe_ns)
} }
// https://dom.spec.whatwg.org/#dom-element-getelementsbyclassname // https://dom.spec.whatwg.org/#dom-element-getelementsbyclassname
fn GetElementsByClassName(self, classes: DOMString) -> Temporary<HTMLCollection> { fn GetElementsByClassName(self, classes: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self).root(); let window = window_from_node(self);
HTMLCollection::by_class_name(window.r(), NodeCast::from_ref(self), classes) HTMLCollection::by_class_name(window.r(), NodeCast::from_ref(self), classes)
} }
// http://dev.w3.org/csswg/cssom-view/#dom-element-getclientrects // http://dev.w3.org/csswg/cssom-view/#dom-element-getclientrects
fn GetClientRects(self) -> Temporary<DOMRectList> { fn GetClientRects(self) -> Root<DOMRectList> {
let win = window_from_node(self).root(); let win = window_from_node(self);
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let raw_rects = node.get_content_boxes(); let raw_rects = node.get_content_boxes();
let rects = raw_rects.iter().map(|rect| { let rects = raw_rects.iter().map(|rect| {
DOMRect::new(win.r(), DOMRect::new(win.r(),
@ -1314,9 +1306,9 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
} }
// http://dev.w3.org/csswg/cssom-view/#dom-element-getboundingclientrect // http://dev.w3.org/csswg/cssom-view/#dom-element-getboundingclientrect
fn GetBoundingClientRect(self) -> Temporary<DOMRect> { fn GetBoundingClientRect(self) -> Root<DOMRect> {
let win = window_from_node(self).root(); let win = window_from_node(self);
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let rect = node.get_bounding_content_box(); let rect = node.get_bounding_content_box();
DOMRect::new( DOMRect::new(
win.r(), win.r(),
@ -1334,11 +1326,11 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML
fn SetInnerHTML(self, value: DOMString) -> Fallible<()> { fn SetInnerHTML(self, value: DOMString) -> Fallible<()> {
let context_node: JSRef<Node> = NodeCast::from_ref(self); let context_node = NodeCast::from_ref(self);
// Step 1. // Step 1.
let frag = try!(context_node.parse_fragment(value)); let frag = try!(context_node.parse_fragment(value));
// Step 2. // Step 2.
Node::replace_all(Some(NodeCast::from_ref(frag.root().r())), context_node); Node::replace_all(Some(NodeCast::from_ref(frag.r())), context_node);
Ok(()) Ok(())
} }
@ -1349,8 +1341,8 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML
fn SetOuterHTML(self, value: DOMString) -> Fallible<()> { fn SetOuterHTML(self, value: DOMString) -> Fallible<()> {
let context_document = document_from_node(self).root(); let context_document = document_from_node(self);
let context_node: JSRef<Node> = NodeCast::from_ref(self); let context_node = NodeCast::from_ref(self);
// Step 1. // Step 1.
let context_parent = match context_node.GetParentNode() { let context_parent = match context_node.GetParentNode() {
None => { None => {
@ -1358,7 +1350,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
return Ok(()); return Ok(());
}, },
Some(parent) => parent, Some(parent) => parent,
}.root(); };
let parent = match context_parent.r().type_id() { let parent = match context_parent.r().type_id() {
// Step 3. // Step 3.
@ -1369,45 +1361,45 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
let body_elem = Element::create(QualName::new(ns!(HTML), atom!(body)), let body_elem = Element::create(QualName::new(ns!(HTML), atom!(body)),
None, context_document.r(), None, context_document.r(),
ElementCreator::ScriptCreated); ElementCreator::ScriptCreated);
NodeCast::from_temporary(body_elem) NodeCast::from_root(body_elem)
}, },
_ => context_node.GetParentNode().unwrap() _ => context_node.GetParentNode().unwrap()
}.root(); };
// Step 5. // Step 5.
let frag = try!(parent.r().parse_fragment(value)); let frag = try!(parent.r().parse_fragment(value));
// Step 6. // Step 6.
try!(context_parent.r().ReplaceChild(NodeCast::from_ref(frag.root().r()), try!(context_parent.r().ReplaceChild(NodeCast::from_ref(frag.r()),
context_node)); context_node));
Ok(()) Ok(())
} }
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling // https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling
fn GetPreviousElementSibling(self) -> Option<Temporary<Element>> { fn GetPreviousElementSibling(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).preceding_siblings() NodeCast::from_ref(self).preceding_siblings()
.filter_map(ElementCast::to_temporary).next() .filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling // https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling
fn GetNextElementSibling(self) -> Option<Temporary<Element>> { fn GetNextElementSibling(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).following_siblings() NodeCast::from_ref(self).following_siblings()
.filter_map(ElementCast::to_temporary).next() .filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-children // https://dom.spec.whatwg.org/#dom-parentnode-children
fn Children(self) -> Temporary<HTMLCollection> { fn Children(self) -> Root<HTMLCollection> {
let window = window_from_node(self).root(); let window = window_from_node(self);
HTMLCollection::children(window.r(), NodeCast::from_ref(self)) HTMLCollection::children(window.r(), NodeCast::from_ref(self))
} }
// https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild // https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild
fn GetFirstElementChild(self) -> Option<Temporary<Element>> { fn GetFirstElementChild(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).child_elements().next() NodeCast::from_ref(self).child_elements().next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild // https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
fn GetLastElementChild(self) -> Option<Temporary<Element>> { fn GetLastElementChild(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_temporary).next() NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-childelementcount // https://dom.spec.whatwg.org/#dom-parentnode-childelementcount
@ -1426,14 +1418,14 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
} }
// https://dom.spec.whatwg.org/#dom-parentnode-queryselector // https://dom.spec.whatwg.org/#dom-parentnode-queryselector
fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> { fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
let root: JSRef<Node> = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
root.query_selector(selectors) root.query_selector(selectors)
} }
// https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall // https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Temporary<NodeList>> { fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Root<NodeList>> {
let root: JSRef<Node> = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
root.query_selector_all(selectors) root.query_selector_all(selectors)
} }
@ -1454,7 +1446,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
// https://dom.spec.whatwg.org/#dom-childnode-remove // https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(self) { fn Remove(self) {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.remove_self(); node.remove_self();
} }
@ -1463,23 +1455,22 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
match parse_author_origin_selector_list_from_str(&selectors) { match parse_author_origin_selector_list_from_str(&selectors) {
Err(()) => Err(Syntax), Err(()) => Err(Syntax),
Ok(ref selectors) => { Ok(ref selectors) => {
let root: JSRef<Node> = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
Ok(matches(selectors, &root, &mut None)) Ok(matches(selectors, &root, &mut None))
} }
} }
} }
// https://dom.spec.whatwg.org/#dom-element-closest // https://dom.spec.whatwg.org/#dom-element-closest
fn Closest(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> { fn Closest(self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
match parse_author_origin_selector_list_from_str(&selectors) { match parse_author_origin_selector_list_from_str(&selectors) {
Err(()) => Err(Syntax), Err(()) => Err(Syntax),
Ok(ref selectors) => { Ok(ref selectors) => {
let root: JSRef<Node> = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
for element in root.inclusive_ancestors() { for element in root.inclusive_ancestors() {
let element = element.root();
if let Some(element) = ElementCast::to_ref(element.r()) { if let Some(element) = ElementCast::to_ref(element.r()) {
if matches(selectors, &NodeCast::from_ref(element), &mut None) { if matches(selectors, &NodeCast::from_ref(element), &mut None) {
return Ok(Some(Temporary::from_rooted(element))); return Ok(Some(Root::from_ref(element)));
} }
} }
} }
@ -1489,22 +1480,22 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
} }
} }
impl<'a> VirtualMethods for JSRef<'a, Element> { impl<'a> VirtualMethods for &'a Element {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let node: &JSRef<Node> = NodeCast::from_borrowed_ref(self); let node: &&Node = NodeCast::from_borrowed_ref(self);
Some(node as &VirtualMethods) Some(node as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
match attr.local_name() { match attr.local_name() {
&atom!("style") => { &atom!("style") => {
// Modifying the `style` attribute might change style. // Modifying the `style` attribute might change style.
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
let base_url = doc.r().url(); let base_url = doc.r().url();
let value = attr.value(); let value = attr.value();
let style = Some(parse_style_attribute(&value, &base_url)); let style = Some(parse_style_attribute(&value, &base_url));
@ -1517,7 +1508,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
&atom!("class") => { &atom!("class") => {
// Modifying a class can change style. // Modifying a class can change style.
if node.is_in_doc() { if node.is_in_doc() {
let document = document_from_node(*self).root(); let document = document_from_node(*self);
document.r().content_changed(node, NodeDamage::NodeStyleDamaged); document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
} }
} }
@ -1525,7 +1516,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
// Modifying an ID might change style. // Modifying an ID might change style.
let value = attr.value(); let value = attr.value();
if node.is_in_doc() { if node.is_in_doc() {
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
if !value.is_empty() { if !value.is_empty() {
let value = value.atom().unwrap().clone(); let value = value.atom().unwrap().clone();
doc.r().register_named_element(*self, value); doc.r().register_named_element(*self, value);
@ -1536,26 +1527,26 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
_ => { _ => {
// Modifying any other attribute might change arbitrary things. // Modifying any other attribute might change arbitrary things.
if node.is_in_doc() { if node.is_in_doc() {
let document = document_from_node(*self).root(); let document = document_from_node(*self);
document.r().content_changed(node, NodeDamage::OtherNodeDamage); document.r().content_changed(node, NodeDamage::OtherNodeDamage);
} }
} }
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
match attr.local_name() { match attr.local_name() {
&atom!("style") => { &atom!("style") => {
// Modifying the `style` attribute might change style. // Modifying the `style` attribute might change style.
*self.style_attribute.borrow_mut() = None; *self.style_attribute.borrow_mut() = None;
if node.is_in_doc() { if node.is_in_doc() {
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
doc.r().content_changed(node, NodeDamage::NodeStyleDamaged); doc.r().content_changed(node, NodeDamage::NodeStyleDamaged);
} }
} }
@ -1563,7 +1554,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
// Modifying an ID can change style. // Modifying an ID can change style.
let value = attr.value(); let value = attr.value();
if node.is_in_doc() { if node.is_in_doc() {
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
if !value.is_empty() { if !value.is_empty() {
let value = value.atom().unwrap().clone(); let value = value.atom().unwrap().clone();
doc.r().unregister_named_element(*self, value); doc.r().unregister_named_element(*self, value);
@ -1574,14 +1565,14 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
&atom!("class") => { &atom!("class") => {
// Modifying a class can change style. // Modifying a class can change style.
if node.is_in_doc() { if node.is_in_doc() {
let document = document_from_node(*self).root(); let document = document_from_node(*self);
document.r().content_changed(node, NodeDamage::NodeStyleDamaged); document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
} }
} }
_ => { _ => {
// Modifying any other attribute might change arbitrary things. // Modifying any other attribute might change arbitrary things.
if node.is_in_doc() { if node.is_in_doc() {
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
doc.r().content_changed(node, NodeDamage::OtherNodeDamage); doc.r().content_changed(node, NodeDamage::OtherNodeDamage);
} }
} }
@ -1603,8 +1594,8 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
if !tree_in_doc { return; } if !tree_in_doc { return; }
if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")).root() { if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) {
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
let value = attr.r().Value(); let value = attr.r().Value();
if !value.is_empty() { if !value.is_empty() {
let value = Atom::from_slice(&value); let value = Atom::from_slice(&value);
@ -1620,8 +1611,8 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
if !tree_in_doc { return; } if !tree_in_doc { return; }
if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")).root() { if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) {
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
let value = attr.r().Value(); let value = attr.r().Value();
if !value.is_empty() { if !value.is_empty() {
let value = Atom::from_slice(&value); let value = Atom::from_slice(&value);
@ -1631,10 +1622,10 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
} }
} }
impl<'a> style::node::TElement<'a> for JSRef<'a, Element> { impl<'a> style::node::TElement<'a> for &'a Element {
fn is_link(self) -> bool { fn is_link(self) -> bool {
// FIXME: This is HTML only. // FIXME: This is HTML only.
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
match node.type_id() { match node.type_id() {
// https://html.spec.whatwg.org/multipage/#selector-link // https://html.spec.whatwg.org/multipage/#selector-link
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement)) | NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement)) |
@ -1675,19 +1666,18 @@ impl<'a> style::node::TElement<'a> for JSRef<'a, Element> {
get_namespace(self) get_namespace(self)
} }
fn get_hover_state(self) -> bool { fn get_hover_state(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_hover_state() node.get_hover_state()
} }
fn get_focus_state(self) -> bool { fn get_focus_state(self) -> bool {
// TODO: Also check whether the top-level browsing context has the system focus, // TODO: Also check whether the top-level browsing context has the system focus,
// and whether this element is a browsing context container. // and whether this element is a browsing context container.
// https://html.spec.whatwg.org/multipage/#selector-focus // https://html.spec.whatwg.org/multipage/#selector-focus
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_focus_state() node.get_focus_state()
} }
fn get_id(self) -> Option<Atom> { fn get_id(self) -> Option<Atom> {
self.get_attribute(&ns!(""), &atom!("id")).map(|attr| { self.get_attribute(&ns!(""), &atom!("id")).map(|attr| {
let attr = attr.root();
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r(); let attr = attr.r();
let value = attr.value(); let value = attr.value();
@ -1698,22 +1688,22 @@ impl<'a> style::node::TElement<'a> for JSRef<'a, Element> {
}) })
} }
fn get_disabled_state(self) -> bool { fn get_disabled_state(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_disabled_state() node.get_disabled_state()
} }
fn get_enabled_state(self) -> bool { fn get_enabled_state(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_enabled_state() node.get_enabled_state()
} }
fn get_checked_state(self) -> bool { fn get_checked_state(self) -> bool {
let input_element: Option<JSRef<HTMLInputElement>> = HTMLInputElementCast::to_ref(self); let input_element: Option<&HTMLInputElement> = HTMLInputElementCast::to_ref(self);
match input_element { match input_element {
Some(input) => input.Checked(), Some(input) => input.Checked(),
None => false, None => false,
} }
} }
fn get_indeterminate_state(self) -> bool { fn get_indeterminate_state(self) -> bool {
let input_element: Option<JSRef<HTMLInputElement>> = HTMLInputElementCast::to_ref(self); let input_element: Option<&HTMLInputElement> = HTMLInputElementCast::to_ref(self);
match input_element { match input_element {
Some(input) => input.get_indeterminate_state(), Some(input) => input.get_indeterminate_state(),
None => false, None => false,
@ -1731,7 +1721,7 @@ impl<'a> style::node::TElement<'a> for JSRef<'a, Element> {
fn each_class<F>(self, mut callback: F) fn each_class<F>(self, mut callback: F)
where F: FnMut(&Atom) where F: FnMut(&Atom)
{ {
if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("class")).root() { if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("class")) {
if let Some(tokens) = attr.r().value().tokens() { if let Some(tokens) = attr.r().value().tokens() {
for token in tokens { for token in tokens {
callback(token) callback(token)
@ -1740,7 +1730,7 @@ impl<'a> style::node::TElement<'a> for JSRef<'a, Element> {
} }
} }
fn has_nonzero_border(self) -> bool { fn has_nonzero_border(self) -> bool {
let table_element: Option<JSRef<HTMLTableElement>> = HTMLTableElementCast::to_ref(self); let table_element: Option<&HTMLTableElement> = HTMLTableElementCast::to_ref(self);
match table_element { match table_element {
None => false, None => false,
Some(this) => { Some(this) => {
@ -1757,20 +1747,20 @@ pub trait ActivationElementHelpers<'a> {
fn as_maybe_activatable(&'a self) -> Option<&'a (Activatable + 'a)>; fn as_maybe_activatable(&'a self) -> Option<&'a (Activatable + 'a)>;
fn click_in_progress(self) -> bool; fn click_in_progress(self) -> bool;
fn set_click_in_progress(self, click: bool); fn set_click_in_progress(self, click: bool);
fn nearest_activable_element(self) -> Option<Temporary<Element>>; fn nearest_activable_element(self) -> Option<Root<Element>>;
fn authentic_click_activation<'b>(self, event: JSRef<'b, Event>); fn authentic_click_activation<'b>(self, event: &'b Event);
} }
impl<'a> ActivationElementHelpers<'a> for JSRef<'a, Element> { impl<'a> ActivationElementHelpers<'a> for &'a Element {
fn as_maybe_activatable(&'a self) -> Option<&'a (Activatable + 'a)> { fn as_maybe_activatable(&'a self) -> Option<&'a (Activatable + 'a)> {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
let element = match node.type_id() { let element = match node.type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => { NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
let element: &'a JSRef<'a, HTMLInputElement> = HTMLInputElementCast::to_borrowed_ref(self).unwrap(); let element = HTMLInputElementCast::to_borrowed_ref(self).unwrap();
Some(element as &'a (Activatable + 'a)) Some(element as &'a (Activatable + 'a))
}, },
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement)) => { NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement)) => {
let element: &'a JSRef<'a, HTMLAnchorElement> = HTMLAnchorElementCast::to_borrowed_ref(self).unwrap(); let element = HTMLAnchorElementCast::to_borrowed_ref(self).unwrap();
Some(element as &'a (Activatable + 'a)) Some(element as &'a (Activatable + 'a))
}, },
_ => { _ => {
@ -1787,26 +1777,25 @@ impl<'a> ActivationElementHelpers<'a> for JSRef<'a, Element> {
} }
fn click_in_progress(self) -> bool { fn click_in_progress(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_flag(CLICK_IN_PROGRESS) node.get_flag(CLICK_IN_PROGRESS)
} }
fn set_click_in_progress(self, click: bool) { fn set_click_in_progress(self, click: bool) {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.set_flag(CLICK_IN_PROGRESS, click) node.set_flag(CLICK_IN_PROGRESS, click)
} }
// https://html.spec.whatwg.org/multipage/#nearest-activatable-element // https://html.spec.whatwg.org/multipage/#nearest-activatable-element
fn nearest_activable_element(self) -> Option<Temporary<Element>> { fn nearest_activable_element(self) -> Option<Root<Element>> {
match self.as_maybe_activatable() { match self.as_maybe_activatable() {
Some(el) => Some(Temporary::from_rooted(el.as_element().root().r())), Some(el) => Some(Root::from_ref(el.as_element())),
None => { None => {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
for node in node.ancestors() { for node in node.ancestors() {
let node = node.root();
if let Some(node) = ElementCast::to_ref(node.r()) { if let Some(node) = ElementCast::to_ref(node.r()) {
if node.as_maybe_activatable().is_some() { if node.as_maybe_activatable().is_some() {
return Some(Temporary::from_rooted(node)) return Some(Root::from_ref(node))
} }
} }
} }
@ -1821,19 +1810,19 @@ impl<'a> ActivationElementHelpers<'a> for JSRef<'a, Element> {
/// ///
/// Use an element's synthetic click activation (or handle_event) for any script-triggered clicks. /// Use an element's synthetic click activation (or handle_event) for any script-triggered clicks.
/// If the spec says otherwise, check with Manishearth first /// If the spec says otherwise, check with Manishearth first
fn authentic_click_activation<'b>(self, event: JSRef<'b, Event>) { fn authentic_click_activation<'b>(self, event: &'b Event) {
// Not explicitly part of the spec, however this helps enforce the invariants // Not explicitly part of the spec, however this helps enforce the invariants
// required to save state between pre-activation and post-activation // required to save state between pre-activation and post-activation
// since we cannot nest authentic clicks (unlike synthetic click activation, where // since we cannot nest authentic clicks (unlike synthetic click activation, where
// the script can generate more click events from the handler) // the script can generate more click events from the handler)
assert!(!self.click_in_progress()); assert!(!self.click_in_progress());
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self); let target = EventTargetCast::from_ref(self);
// Step 2 (requires canvas support) // Step 2 (requires canvas support)
// Step 3 // Step 3
self.set_click_in_progress(true); self.set_click_in_progress(true);
// Step 4 // Step 4
let e = self.nearest_activable_element().root(); let e = self.nearest_activable_element();
match e { match e {
Some(ref el) => match el.r().as_maybe_activatable() { Some(ref el) => match el.r().as_maybe_activatable() {
Some(elem) => { Some(elem) => {

View file

@ -8,8 +8,8 @@ use dom::bindings::codegen::Bindings::ErrorEventBinding::ErrorEventMethods;
use dom::bindings::codegen::InheritTypes::{EventCast, ErrorEventDerived}; use dom::bindings::codegen::InheritTypes::{EventCast, ErrorEventDerived};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, MutHeap, Rootable, Temporary}; use dom::bindings::js::{Root, MutHeapJSVal};
use js::jsapi::JSContext; use js::jsapi::{JSContext, HandleValue};
use dom::bindings::trace::JSTraceable; use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::reflect_dom_object; use dom::bindings::utils::reflect_dom_object;
@ -18,8 +18,8 @@ use util::str::DOMString;
use dom::bindings::cell::DOMRefCell; use dom::bindings::cell::DOMRefCell;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::{Cell}; use std::cell::Cell;
use js::jsval::{JSVal, NullValue}; use js::jsval::JSVal;
#[dom_struct] #[dom_struct]
pub struct ErrorEvent { pub struct ErrorEvent {
@ -28,7 +28,7 @@ pub struct ErrorEvent {
filename: DOMRefCell<DOMString>, filename: DOMRefCell<DOMString>,
lineno: Cell<u32>, lineno: Cell<u32>,
colno: Cell<u32>, colno: Cell<u32>,
error: MutHeap<JSVal>, error: MutHeapJSVal,
} }
impl ErrorEventDerived for Event { impl ErrorEventDerived for Event {
@ -45,11 +45,11 @@ impl ErrorEvent {
filename: DOMRefCell::new("".to_owned()), filename: DOMRefCell::new("".to_owned()),
lineno: Cell::new(0), lineno: Cell::new(0),
colno: Cell::new(0), colno: Cell::new(0),
error: MutHeap::new(NullValue()) error: MutHeapJSVal::new()
} }
} }
pub fn new_uninitialized(global: GlobalRef) -> Temporary<ErrorEvent> { pub fn new_uninitialized(global: GlobalRef) -> Root<ErrorEvent> {
reflect_dom_object(box ErrorEvent::new_inherited(EventTypeId::ErrorEvent), reflect_dom_object(box ErrorEvent::new_inherited(EventTypeId::ErrorEvent),
global, global,
ErrorEventBinding::Wrap) ErrorEventBinding::Wrap)
@ -63,24 +63,26 @@ impl ErrorEvent {
filename: DOMString, filename: DOMString,
lineno: u32, lineno: u32,
colno: u32, colno: u32,
error: JSVal) -> Temporary<ErrorEvent> { error: HandleValue) -> Root<ErrorEvent> {
let ev = ErrorEvent::new_uninitialized(global).root(); let ev = ErrorEvent::new_uninitialized(global);
let event: JSRef<Event> = EventCast::from_ref(ev.r());
event.InitEvent(type_, bubbles == EventBubbles::Bubbles,
cancelable == EventCancelable::Cancelable);
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let ev = ev.r(); {
*ev.message.borrow_mut() = message; let ev = ev.r();
*ev.filename.borrow_mut() = filename; let event = EventCast::from_ref(ev);
ev.lineno.set(lineno); event.InitEvent(type_, bubbles == EventBubbles::Bubbles,
ev.colno.set(colno); cancelable == EventCancelable::Cancelable);
ev.error.set(error); *ev.message.borrow_mut() = message;
Temporary::from_rooted(ev) *ev.filename.borrow_mut() = filename;
ev.lineno.set(lineno);
ev.colno.set(colno);
}
ev.error.set(error.get());
ev
} }
pub fn Constructor(global: GlobalRef, pub fn Constructor(global: GlobalRef,
type_: DOMString, type_: DOMString,
init: &ErrorEventBinding::ErrorEventInit) -> Fallible<Temporary<ErrorEvent>>{ init: &ErrorEventBinding::ErrorEventInit) -> Fallible<Root<ErrorEvent>>{
let msg = match init.message.as_ref() { let msg = match init.message.as_ref() {
Some(message) => message.clone(), Some(message) => message.clone(),
None => "".to_owned(), None => "".to_owned(),
@ -106,13 +108,14 @@ impl ErrorEvent {
let event = ErrorEvent::new(global, type_, let event = ErrorEvent::new(global, type_,
bubbles, cancelable, bubbles, cancelable,
msg, file_name, msg, file_name,
line_num, col_num, init.error); line_num, col_num,
HandleValue { ptr: &init.error });
Ok(event) Ok(event)
} }
} }
impl<'a> ErrorEventMethods for JSRef<'a, ErrorEvent> { impl<'a> ErrorEventMethods for &'a ErrorEvent {
fn Lineno(self) -> u32 { fn Lineno(self) -> u32 {
self.lineno.get() self.lineno.get()
} }

View file

@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::EventBinding;
use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethods}; use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethods};
use dom::bindings::error::Fallible; use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary}; use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::eventtarget::{EventTarget, EventTargetHelpers}; use dom::eventtarget::{EventTarget, EventTargetHelpers};
use util::str::DOMString; use util::str::DOMString;
@ -95,7 +95,7 @@ impl Event {
} }
} }
pub fn new_uninitialized(global: GlobalRef) -> Temporary<Event> { pub fn new_uninitialized(global: GlobalRef) -> Root<Event> {
reflect_dom_object(box Event::new_inherited(EventTypeId::HTMLEvent), reflect_dom_object(box Event::new_inherited(EventTypeId::HTMLEvent),
global, global,
EventBinding::Wrap) EventBinding::Wrap)
@ -104,15 +104,15 @@ impl Event {
pub fn new(global: GlobalRef, pub fn new(global: GlobalRef,
type_: DOMString, type_: DOMString,
bubbles: EventBubbles, bubbles: EventBubbles,
cancelable: EventCancelable) -> Temporary<Event> { cancelable: EventCancelable) -> Root<Event> {
let event = Event::new_uninitialized(global).root(); let event = Event::new_uninitialized(global);
event.r().InitEvent(type_, bubbles == EventBubbles::Bubbles, cancelable == EventCancelable::Cancelable); event.r().InitEvent(type_, bubbles == EventBubbles::Bubbles, cancelable == EventCancelable::Cancelable);
Temporary::from_rooted(event.r()) event
} }
pub fn Constructor(global: GlobalRef, pub fn Constructor(global: GlobalRef,
type_: DOMString, type_: DOMString,
init: &EventBinding::EventInit) -> Fallible<Temporary<Event>> { init: &EventBinding::EventInit) -> Fallible<Root<Event>> {
let bubbles = if init.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble }; let bubbles = if init.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble };
let cancelable = if init.cancelable { EventCancelable::Cancelable } else { EventCancelable::NotCancelable }; let cancelable = if init.cancelable { EventCancelable::Cancelable } else { EventCancelable::NotCancelable };
Ok(Event::new(global, type_, bubbles, cancelable)) Ok(Event::new(global, type_, bubbles, cancelable))
@ -129,13 +129,13 @@ impl Event {
} }
#[inline] #[inline]
pub fn set_current_target(&self, val: JSRef<EventTarget>) { pub fn set_current_target(&self, val: &EventTarget) {
self.current_target.set(Some(JS::from_rooted(val))); self.current_target.set(Some(JS::from_ref(val)));
} }
#[inline] #[inline]
pub fn set_target(&self, val: JSRef<EventTarget>) { pub fn set_target(&self, val: &EventTarget) {
self.target.set(Some(JS::from_rooted(val))); self.target.set(Some(JS::from_ref(val)));
} }
#[inline] #[inline]
@ -174,7 +174,7 @@ impl Event {
} }
} }
impl<'a> EventMethods for JSRef<'a, Event> { impl<'a> EventMethods for &'a Event {
// https://dom.spec.whatwg.org/#dom-event-eventphase // https://dom.spec.whatwg.org/#dom-event-eventphase
fn EventPhase(self) -> u16 { fn EventPhase(self) -> u16 {
self.phase.get() as u16 self.phase.get() as u16
@ -188,13 +188,13 @@ impl<'a> EventMethods for JSRef<'a, Event> {
} }
// https://dom.spec.whatwg.org/#dom-event-target // https://dom.spec.whatwg.org/#dom-event-target
fn GetTarget(self) -> Option<Temporary<EventTarget>> { fn GetTarget(self) -> Option<Root<EventTarget>> {
self.target.get().map(Temporary::from_rooted) self.target.get().map(Root::from_rooted)
} }
// https://dom.spec.whatwg.org/#dom-event-currenttarget // https://dom.spec.whatwg.org/#dom-event-currenttarget
fn GetCurrentTarget(self) -> Option<Temporary<EventTarget>> { fn GetCurrentTarget(self) -> Option<Root<EventTarget>> {
self.current_target.get().map(Temporary::from_rooted) self.current_target.get().map(Root::from_rooted)
} }
// https://dom.spec.whatwg.org/#dom-event-defaultprevented // https://dom.spec.whatwg.org/#dom-event-defaultprevented
@ -263,16 +263,16 @@ impl<'a> EventMethods for JSRef<'a, Event> {
pub trait EventHelpers { pub trait EventHelpers {
fn set_trusted(self, trusted: bool); fn set_trusted(self, trusted: bool);
fn fire(self, target: JSRef<EventTarget>) -> bool; fn fire(self, target: &EventTarget) -> bool;
} }
impl<'a> EventHelpers for JSRef<'a, Event> { impl<'a> EventHelpers for &'a Event {
fn set_trusted(self, trusted: bool) { fn set_trusted(self, trusted: bool) {
self.trusted.set(trusted); self.trusted.set(trusted);
} }
// https://html.spec.whatwg.org/multipage/#fire-a-simple-event // https://html.spec.whatwg.org/multipage/#fire-a-simple-event
fn fire(self, target: JSRef<EventTarget>) -> bool { fn fire(self, target: &EventTarget) -> bool {
self.set_trusted(true); self.set_trusted(true);
target.dispatch_event(self) target.dispatch_event(self)
} }

View file

@ -5,7 +5,7 @@
use dom::bindings::callback::ExceptionHandling::Report; use dom::bindings::callback::ExceptionHandling::Report;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast};
use dom::bindings::js::{JS, JSRef, OptionalRootable, Rootable}; use dom::bindings::js::JS;
use dom::bindings::trace::RootedVec; use dom::bindings::trace::RootedVec;
use dom::eventtarget::{EventTarget, ListenerPhase}; use dom::eventtarget::{EventTarget, ListenerPhase};
use dom::event::{Event, EventPhase}; use dom::event::{Event, EventPhase};
@ -13,9 +13,9 @@ use dom::node::{Node, NodeHelpers};
use dom::virtualmethods::vtable_for; use dom::virtualmethods::vtable_for;
// See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm // See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>, pub fn dispatch_event<'a, 'b>(target: &'a EventTarget,
pseudo_target: Option<JSRef<'b, EventTarget>>, pseudo_target: Option<&'b EventTarget>,
event: JSRef<Event>) -> bool { event: &Event) -> bool {
assert!(!event.dispatching()); assert!(!event.dispatching());
assert!(event.initialized()); assert!(event.initialized());
@ -31,9 +31,8 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
let mut chain: RootedVec<JS<EventTarget>> = RootedVec::new(); let mut chain: RootedVec<JS<EventTarget>> = RootedVec::new();
if let Some(target_node) = NodeCast::to_ref(target) { if let Some(target_node) = NodeCast::to_ref(target) {
for ancestor in target_node.ancestors() { for ancestor in target_node.ancestors() {
let ancestor = ancestor.root();
let ancestor_target = EventTargetCast::from_ref(ancestor.r()); let ancestor_target = EventTargetCast::from_ref(ancestor.r());
chain.push(JS::from_rooted(ancestor_target)) chain.push(JS::from_ref(ancestor_target))
} }
} }
@ -113,10 +112,10 @@ pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
} }
/* default action */ /* default action */
let target = event.GetTarget().root(); let target = event.GetTarget();
match target { match target {
Some(ref target) => { Some(ref target) => {
let node: Option<JSRef<Node>> = NodeCast::to_ref(target.r()); let node: Option<&Node> = NodeCast::to_ref(target.r());
match node { match node {
Some(node) => { Some(node) => {
let vtable = vtable_for(&node); let vtable = vtable_for(&node);

View file

@ -9,7 +9,6 @@ use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods;
use dom::bindings::error::{Fallible, report_pending_exception}; use dom::bindings::error::{Fallible, report_pending_exception};
use dom::bindings::error::Error::InvalidState; use dom::bindings::error::Error::InvalidState;
use dom::bindings::js::JSRef;
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::event::{Event, EventHelpers}; use dom::event::{Event, EventHelpers};
use dom::eventdispatcher::dispatch_event; use dom::eventdispatcher::dispatch_event;
@ -17,8 +16,10 @@ use dom::node::NodeTypeId;
use dom::workerglobalscope::WorkerGlobalScopeTypeId; use dom::workerglobalscope::WorkerGlobalScopeTypeId;
use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTargetTypeId; use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTargetTypeId;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use js::jsapi::{JS_CompileUCFunction, JS_GetFunctionObject, JS_CloneFunctionObject}; use js::jsapi::{CompileFunction, JS_GetFunctionObject};
use js::jsapi::{JSContext, JSObject}; use js::jsapi::{JSContext, RootedFunction, HandleObject};
use js::jsapi::{JSAutoCompartment, JSAutoRequest};
use js::rust::{AutoObjectVectorWrapper, CompileOptionsWrapper};
use util::str::DOMString; use util::str::DOMString;
use fnv::FnvHasher; use fnv::FnvHasher;
@ -30,6 +31,7 @@ use std::default::Default;
use std::ffi::CString; use std::ffi::CString;
use std::intrinsics; use std::intrinsics;
use std::ptr; use std::ptr;
use std::rc::Rc;
use url::Url; use url::Url;
use std::collections::HashMap; use std::collections::HashMap;
@ -88,23 +90,23 @@ impl EventTargetTypeId {
} }
} }
#[derive(Copy, Clone, PartialEq)] #[derive(Clone, PartialEq)]
#[jstraceable] #[jstraceable]
pub enum EventListenerType { pub enum EventListenerType {
Additive(EventListener), Additive(Rc<EventListener>),
Inline(EventListener), Inline(Rc<EventListener>),
} }
impl EventListenerType { impl EventListenerType {
fn get_listener(&self) -> EventListener { fn get_listener(&self) -> Rc<EventListener> {
match *self { match *self {
EventListenerType::Additive(listener) | EventListenerType::Additive(ref listener) |
EventListenerType::Inline(listener) => listener EventListenerType::Inline(ref listener) => listener.clone(),
} }
} }
} }
#[derive(Copy, Clone, PartialEq)] #[derive(Clone, PartialEq)]
#[jstraceable] #[jstraceable]
#[privatize] #[privatize]
pub struct EventListenerEntry { pub struct EventListenerEntry {
@ -128,14 +130,14 @@ impl EventTarget {
} }
} }
pub fn get_listeners(&self, type_: &str) -> Option<Vec<EventListener>> { pub fn get_listeners(&self, type_: &str) -> Option<Vec<Rc<EventListener>>> {
self.handlers.borrow().get(type_).map(|listeners| { self.handlers.borrow().get(type_).map(|listeners| {
listeners.iter().map(|entry| entry.listener.get_listener()).collect() listeners.iter().map(|entry| entry.listener.get_listener()).collect()
}) })
} }
pub fn get_listeners_for(&self, type_: &str, desired_phase: ListenerPhase) pub fn get_listeners_for(&self, type_: &str, desired_phase: ListenerPhase)
-> Option<Vec<EventListener>> { -> Option<Vec<Rc<EventListener>>> {
self.handlers.borrow().get(type_).map(|listeners| { self.handlers.borrow().get(type_).map(|listeners| {
let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase); let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase);
filtered.map(|entry| entry.listener.get_listener()).collect() filtered.map(|entry| entry.listener.get_listener()).collect()
@ -150,47 +152,47 @@ impl EventTarget {
pub trait EventTargetHelpers { pub trait EventTargetHelpers {
fn dispatch_event_with_target(self, fn dispatch_event_with_target(self,
target: JSRef<EventTarget>, target: &EventTarget,
event: JSRef<Event>) -> bool; event: &Event) -> bool;
fn dispatch_event(self, event: JSRef<Event>) -> bool; fn dispatch_event(self, event: &Event) -> bool;
fn set_inline_event_listener(self, fn set_inline_event_listener(self,
ty: DOMString, ty: DOMString,
listener: Option<EventListener>); listener: Option<Rc<EventListener>>);
fn get_inline_event_listener(self, ty: DOMString) -> Option<EventListener>; fn get_inline_event_listener(self, ty: DOMString) -> Option<Rc<EventListener>>;
fn set_event_handler_uncompiled(self, fn set_event_handler_uncompiled(self,
cx: *mut JSContext, cx: *mut JSContext,
url: Url, url: Url,
scope: *mut JSObject, scope: HandleObject,
ty: &str, ty: &str,
source: DOMString); source: DOMString);
fn set_event_handler_common<T: CallbackContainer>(self, ty: &str, fn set_event_handler_common<T: CallbackContainer>(self, ty: &str,
listener: Option<T>); listener: Option<Rc<T>>);
fn get_event_handler_common<T: CallbackContainer>(self, ty: &str) -> Option<T>; fn get_event_handler_common<T: CallbackContainer>(self, ty: &str) -> Option<Rc<T>>;
fn has_handlers(self) -> bool; fn has_handlers(self) -> bool;
} }
impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> { impl<'a> EventTargetHelpers for &'a EventTarget {
fn dispatch_event_with_target(self, fn dispatch_event_with_target(self,
target: JSRef<EventTarget>, target: &EventTarget,
event: JSRef<Event>) -> bool { event: &Event) -> bool {
dispatch_event(self, Some(target), event) dispatch_event(self, Some(target), event)
} }
fn dispatch_event(self, event: JSRef<Event>) -> bool { fn dispatch_event(self, event: &Event) -> bool {
dispatch_event(self, None, event) dispatch_event(self, None, event)
} }
fn set_inline_event_listener(self, fn set_inline_event_listener(self,
ty: DOMString, ty: DOMString,
listener: Option<EventListener>) { listener: Option<Rc<EventListener>>) {
let mut handlers = self.handlers.borrow_mut(); let mut handlers = self.handlers.borrow_mut();
let entries = match handlers.entry(ty) { let entries = match handlers.entry(ty) {
Occupied(entry) => entry.into_mut(), Occupied(entry) => entry.into_mut(),
Vacant(entry) => entry.insert(vec!()), Vacant(entry) => entry.insert(vec!()),
}; };
let idx = entries.iter().position(|&entry| { let idx = entries.iter().position(|ref entry| {
match entry.listener { match entry.listener {
EventListenerType::Inline(_) => true, EventListenerType::Inline(_) => true,
_ => false, _ => false,
@ -217,7 +219,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
} }
} }
fn get_inline_event_listener(self, ty: DOMString) -> Option<EventListener> { fn get_inline_event_listener(self, ty: DOMString) -> Option<Rc<EventListener>> {
let handlers = self.handlers.borrow(); let handlers = self.handlers.borrow();
let entries = handlers.get(&ty); let entries = handlers.get(&ty);
entries.and_then(|entries| entries.iter().find(|entry| { entries.and_then(|entries| entries.iter().find(|entry| {
@ -232,7 +234,7 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
fn set_event_handler_uncompiled(self, fn set_event_handler_uncompiled(self,
cx: *mut JSContext, cx: *mut JSContext,
url: Url, url: Url,
scope: *mut JSObject, scope: HandleObject,
ty: &str, ty: &str,
source: DOMString) { source: DOMString) {
let url = CString::new(url.serialize()).unwrap(); let url = CString::new(url.serialize()).unwrap();
@ -243,38 +245,42 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
static mut ARG_NAMES: [*const c_char; 1] = [b"event\0" as *const u8 as *const c_char]; static mut ARG_NAMES: [*const c_char; 1] = [b"event\0" as *const u8 as *const c_char];
let source: Vec<u16> = source.utf16_units().collect(); let source: Vec<u16> = source.utf16_units().collect();
let handler = unsafe { let options = CompileOptionsWrapper::new(cx, url.as_ptr(), lineno);
JS_CompileUCFunction(cx, let scopechain = AutoObjectVectorWrapper::new(cx);
ptr::null_mut(),
name.as_ptr(), let _ar = JSAutoRequest::new(cx);
nargs, let _ac = JSAutoCompartment::new(cx, scope.get());
ARG_NAMES.as_mut_ptr(), let mut handler = RootedFunction::new(cx, ptr::null_mut());
source.as_ptr(), let rv = unsafe {
source.len() as size_t, CompileFunction(cx,
url.as_ptr(), scopechain.ptr,
lineno) options.ptr,
name.as_ptr(),
nargs,
ARG_NAMES.as_mut_ptr(),
source.as_ptr() as *const i16,
source.len() as size_t,
handler.handle_mut())
}; };
if handler.is_null() { if rv == 0 || handler.ptr.is_null() {
report_pending_exception(cx, self.reflector().get_jsobject()); report_pending_exception(cx, self.reflector().get_jsobject().get());
return; return;
} }
let funobj = unsafe { let funobj = unsafe { JS_GetFunctionObject(handler.ptr) };
JS_CloneFunctionObject(cx, JS_GetFunctionObject(handler), scope)
};
assert!(!funobj.is_null()); assert!(!funobj.is_null());
self.set_event_handler_common(ty, Some(EventHandlerNonNull::new(funobj))); self.set_event_handler_common(ty, Some(EventHandlerNonNull::new(funobj)));
} }
fn set_event_handler_common<T: CallbackContainer>( fn set_event_handler_common<T: CallbackContainer>(
self, ty: &str, listener: Option<T>) self, ty: &str, listener: Option<Rc<T>>)
{ {
let event_listener = listener.map(|listener| let event_listener = listener.map(|listener|
EventListener::new(listener.callback())); EventListener::new(listener.callback()));
self.set_inline_event_listener(ty.to_owned(), event_listener); self.set_inline_event_listener(ty.to_owned(), event_listener);
} }
fn get_event_handler_common<T: CallbackContainer>(self, ty: &str) -> Option<T> { fn get_event_handler_common<T: CallbackContainer>(self, ty: &str) -> Option<Rc<T>> {
let listener = self.get_inline_event_listener(ty.to_owned()); let listener = self.get_inline_event_listener(ty.to_owned());
listener.map(|listener| CallbackContainer::new(listener.parent.callback())) listener.map(|listener| CallbackContainer::new(listener.parent.callback()))
} }
@ -286,10 +292,10 @@ impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
} }
} }
impl<'a> EventTargetMethods for JSRef<'a, EventTarget> { impl<'a> EventTargetMethods for &'a EventTarget {
fn AddEventListener(self, fn AddEventListener(self,
ty: DOMString, ty: DOMString,
listener: Option<EventListener>, listener: Option<Rc<EventListener>>,
capture: bool) { capture: bool) {
match listener { match listener {
Some(listener) => { Some(listener) => {
@ -314,17 +320,17 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
fn RemoveEventListener(self, fn RemoveEventListener(self,
ty: DOMString, ty: DOMString,
listener: Option<EventListener>, listener: Option<Rc<EventListener>>,
capture: bool) { capture: bool) {
match listener { match listener {
Some(listener) => { Some(ref listener) => {
let mut handlers = self.handlers.borrow_mut(); let mut handlers = self.handlers.borrow_mut();
let mut entry = handlers.get_mut(&ty); let mut entry = handlers.get_mut(&ty);
for entry in entry.iter_mut() { for entry in entry.iter_mut() {
let phase = if capture { ListenerPhase::Capturing } else { ListenerPhase::Bubbling }; let phase = if capture { ListenerPhase::Capturing } else { ListenerPhase::Bubbling };
let old_entry = EventListenerEntry { let old_entry = EventListenerEntry {
phase: phase, phase: phase,
listener: EventListenerType::Additive(listener) listener: EventListenerType::Additive(listener.clone())
}; };
let position = entry.position_elem(&old_entry); let position = entry.position_elem(&old_entry);
for &position in position.iter() { for &position in position.iter() {
@ -336,7 +342,7 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
} }
} }
fn DispatchEvent(self, event: JSRef<Event>) -> Fallible<bool> { fn DispatchEvent(self, event: &Event) -> Fallible<bool> {
if event.dispatching() || !event.initialized() { if event.dispatching() || !event.initialized() {
return Err(InvalidState); return Err(InvalidState);
} }
@ -345,7 +351,7 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
} }
} }
impl<'a> VirtualMethods for JSRef<'a, EventTarget> { impl<'a> VirtualMethods for &'a EventTarget {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
None None
} }

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::FileBinding; use dom::bindings::codegen::Bindings::FileBinding;
use dom::bindings::codegen::Bindings::FileBinding::FileMethods; use dom::bindings::codegen::Bindings::FileBinding::FileMethods;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::bindings::utils::reflect_dom_object; use dom::bindings::utils::reflect_dom_object;
use dom::blob::{Blob, BlobTypeId}; use dom::blob::{Blob, BlobTypeId};
use util::str::DOMString; use util::str::DOMString;
@ -18,7 +18,7 @@ pub struct File {
impl File { impl File {
fn new_inherited(global: GlobalRef, type_: BlobTypeId, fn new_inherited(global: GlobalRef, type_: BlobTypeId,
_file_bits: JSRef<Blob>, name: DOMString) -> File { _file_bits: &Blob, name: DOMString) -> File {
File { File {
//TODO: get type from the underlying filesystem instead of "".to_string() //TODO: get type from the underlying filesystem instead of "".to_string()
blob: Blob::new_inherited(global, type_, None, ""), blob: Blob::new_inherited(global, type_, None, ""),
@ -28,7 +28,7 @@ impl File {
// the relevant subfields of file_bits should be copied over // the relevant subfields of file_bits should be copied over
} }
pub fn new(global: GlobalRef, file_bits: JSRef<Blob>, name: DOMString) -> Temporary<File> { pub fn new(global: GlobalRef, file_bits: &Blob, name: DOMString) -> Root<File> {
reflect_dom_object(box File::new_inherited(global, BlobTypeId::File, file_bits, name), reflect_dom_object(box File::new_inherited(global, BlobTypeId::File, file_bits, name),
global, global,
FileBinding::Wrap) FileBinding::Wrap)
@ -39,7 +39,7 @@ impl File {
} }
} }
impl<'a> FileMethods for JSRef<'a, File> { impl<'a> FileMethods for &'a File {
fn Name(self) -> DOMString { fn Name(self) -> DOMString {
self.name.clone() self.name.clone()
} }

View file

@ -10,7 +10,7 @@ use dom::bindings::codegen::UnionTypes::FileOrString;
use dom::bindings::codegen::UnionTypes::FileOrString::{eFile, eString}; use dom::bindings::codegen::UnionTypes::FileOrString::{eFile, eString};
use dom::bindings::error::{Fallible}; use dom::bindings::error::{Fallible};
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, Temporary, Unrooted}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::blob::Blob; use dom::blob::Blob;
use dom::file::File; use dom::file::File;
@ -38,29 +38,29 @@ pub struct FormData {
} }
impl FormData { impl FormData {
fn new_inherited(form: Option<JSRef<HTMLFormElement>>, global: GlobalRef) -> FormData { fn new_inherited(form: Option<&HTMLFormElement>, global: GlobalRef) -> FormData {
FormData { FormData {
reflector_: Reflector::new(), reflector_: Reflector::new(),
data: DOMRefCell::new(HashMap::new()), data: DOMRefCell::new(HashMap::new()),
global: GlobalField::from_rooted(&global), global: GlobalField::from_rooted(&global),
form: form.map(|f| JS::from_rooted(f)), form: form.map(|f| JS::from_ref(f)),
} }
} }
pub fn new(form: Option<JSRef<HTMLFormElement>>, global: GlobalRef) -> Temporary<FormData> { pub fn new(form: Option<&HTMLFormElement>, global: GlobalRef) -> Root<FormData> {
reflect_dom_object(box FormData::new_inherited(form, global), reflect_dom_object(box FormData::new_inherited(form, global),
global, FormDataBinding::Wrap) global, FormDataBinding::Wrap)
} }
pub fn Constructor(global: GlobalRef, form: Option<JSRef<HTMLFormElement>>) -> Fallible<Temporary<FormData>> { pub fn Constructor(global: GlobalRef, form: Option<&HTMLFormElement>) -> Fallible<Root<FormData>> {
Ok(FormData::new(form, global)) Ok(FormData::new(form, global))
} }
} }
impl<'a> FormDataMethods for JSRef<'a, FormData> { impl<'a> FormDataMethods for &'a FormData {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn Append(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) { fn Append(self, name: DOMString, value: &Blob, filename: Option<DOMString>) {
let file = FormDatum::FileData(JS::from_rooted(self.get_file_from_blob(value, filename))); let file = FormDatum::FileData(JS::from_rooted(&self.get_file_from_blob(value, filename)));
let mut data = self.data.borrow_mut(); let mut data = self.data.borrow_mut();
match data.entry(name) { match data.entry(name) {
Occupied(entry) => entry.into_mut().push(file), Occupied(entry) => entry.into_mut().push(file),
@ -90,7 +90,7 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
match data[&name][0].clone() { match data[&name][0].clone() {
FormDatum::StringData(ref s) => Some(eString(s.clone())), FormDatum::StringData(ref s) => Some(eString(s.clone())),
FormDatum::FileData(ref f) => { FormDatum::FileData(ref f) => {
Some(eFile(Unrooted::from_js(*f))) Some(eFile(f.root()))
} }
} }
} else { } else {
@ -104,8 +104,8 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
data.contains_key(&name) data.contains_key(&name)
} }
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
fn Set(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) { fn Set(self, name: DOMString, value: &Blob, filename: Option<DOMString>) {
let file = FormDatum::FileData(JS::from_rooted(self.get_file_from_blob(value, filename))); let file = FormDatum::FileData(JS::from_rooted(&self.get_file_from_blob(value, filename)));
self.data.borrow_mut().insert(name, vec!(file)); self.data.borrow_mut().insert(name, vec!(file));
} }
@ -115,13 +115,13 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
} }
trait PrivateFormDataHelpers{ trait PrivateFormDataHelpers{
fn get_file_from_blob(&self, value: JSRef<Blob>, filename: Option<DOMString>) -> Temporary<File>; fn get_file_from_blob(self, value: &Blob, filename: Option<DOMString>) -> Root<File>;
} }
impl PrivateFormDataHelpers for FormData { impl<'a> PrivateFormDataHelpers for &'a FormData {
fn get_file_from_blob(&self, value: JSRef<Blob>, filename: Option<DOMString>) -> Temporary<File> { fn get_file_from_blob(self, value: &Blob, filename: Option<DOMString>) -> Root<File> {
let global = self.global.root(); let global = self.global.root();
let f: Option<JSRef<File>> = FileCast::to_ref(value); let f: Option<&File> = FileCast::to_ref(value);
let name = filename.unwrap_or(f.map(|inner| inner.name().clone()).unwrap_or("blob".to_owned())); let name = filename.unwrap_or(f.map(|inner| inner.name().clone()).unwrap_or("blob".to_owned()));
File::new(global.r(), value, name) File::new(global.r(), value, name)
} }

View file

@ -13,8 +13,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLImageElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLImageElementDerived};
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::codegen::InheritTypes::{MouseEventCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{MouseEventCast, NodeCast};
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary}; use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::js::OptionalRootable;
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::domtokenlist::DOMTokenList; use dom::domtokenlist::DOMTokenList;
use dom::element::{Element, AttributeHandlers, ElementTypeId}; use dom::element::{Element, AttributeHandlers, ElementTypeId};
@ -47,7 +46,7 @@ impl HTMLAnchorElementDerived for EventTarget {
impl HTMLAnchorElement { impl HTMLAnchorElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLAnchorElement { document: &Document) -> HTMLAnchorElement {
HTMLAnchorElement { HTMLAnchorElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLAnchorElement, localName, prefix, document), HTMLElement::new_inherited(HTMLElementTypeId::HTMLAnchorElement, localName, prefix, document),
@ -58,19 +57,19 @@ impl HTMLAnchorElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLAnchorElement> { document: &Document) -> Root<HTMLAnchorElement> {
let element = HTMLAnchorElement::new_inherited(localName, prefix, document); let element = HTMLAnchorElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLAnchorElementBinding::Wrap) Node::reflect_node(box element, document, HTMLAnchorElementBinding::Wrap)
} }
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLAnchorElement> { impl<'a> VirtualMethods for &'a HTMLAnchorElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn handle_event(&self, event: JSRef<Event>) { fn handle_event(&self, event: &Event) {
match self.super_type() { match self.super_type() {
Some(s) => { Some(s) => {
s.handle_event(event); s.handle_event(event);
@ -87,27 +86,27 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLAnchorElement> {
} }
} }
impl<'a> HTMLAnchorElementMethods for JSRef<'a, HTMLAnchorElement> { impl<'a> HTMLAnchorElementMethods for &'a HTMLAnchorElement {
fn Text(self) -> DOMString { fn Text(self) -> DOMString {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.GetTextContent().unwrap() node.GetTextContent().unwrap()
} }
fn SetText(self, value: DOMString) { fn SetText(self, value: DOMString) {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.SetTextContent(Some(value)) node.SetTextContent(Some(value))
} }
fn RelList(self) -> Temporary<DOMTokenList> { fn RelList(self) -> Root<DOMTokenList> {
self.rel_list.or_init(|| { self.rel_list.or_init(|| {
DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel")) DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel"))
}) })
} }
} }
impl<'a> Activatable for JSRef<'a, HTMLAnchorElement> { impl<'a> Activatable for &'a HTMLAnchorElement {
fn as_element(&self) -> Temporary<Element> { fn as_element<'b>(&'b self) -> &'b Element {
Temporary::from_rooted(ElementCast::from_ref(*self)) ElementCast::from_ref(*self)
} }
fn is_instance_activatable(&self) -> bool { fn is_instance_activatable(&self) -> bool {
@ -125,22 +124,22 @@ impl<'a> Activatable for JSRef<'a, HTMLAnchorElement> {
} }
//https://html.spec.whatwg.org/multipage/#the-a-element:activation-behaviour //https://html.spec.whatwg.org/multipage/#the-a-element:activation-behaviour
fn activation_behavior(&self, event: JSRef<Event>, target: JSRef<EventTarget>) { fn activation_behavior(&self, event: &Event, target: &EventTarget) {
//Step 1. If the node document is not fully active, abort. //Step 1. If the node document is not fully active, abort.
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
if !doc.r().is_fully_active() { if !doc.r().is_fully_active() {
return; return;
} }
//TODO: Step 2. Check if browsing context is specified and act accordingly. //TODO: Step 2. Check if browsing context is specified and act accordingly.
//Step 3. Handle <img ismap/>. //Step 3. Handle <img ismap/>.
let element: JSRef<Element> = ElementCast::from_ref(*self); let element = ElementCast::from_ref(*self);
let mouse_event = MouseEventCast::to_ref(event).unwrap(); let mouse_event = MouseEventCast::to_ref(event).unwrap();
let mut ismap_suffix = None; let mut ismap_suffix = None;
if let Some(element) = ElementCast::to_ref(target) { if let Some(element) = ElementCast::to_ref(target) {
if target.is_htmlimageelement() && element.has_attribute(&atom!("ismap")) { if target.is_htmlimageelement() && element.has_attribute(&atom!("ismap")) {
let target_node = NodeCast::to_ref(target).unwrap(); let target_node = NodeCast::to_ref(target).unwrap();
let rect = window_from_node(target_node).root().r().content_box_query( let rect = window_from_node(target_node).r().content_box_query(
target_node.to_trusted_node_address()); target_node.to_trusted_node_address());
ismap_suffix = Some( ismap_suffix = Some(
format!("?{},{}", mouse_event.ClientX().to_f32().unwrap() - rect.origin.x.to_f32_px(), format!("?{},{}", mouse_event.ClientX().to_f32().unwrap() - rect.origin.x.to_f32_px(),
@ -151,7 +150,7 @@ impl<'a> Activatable for JSRef<'a, HTMLAnchorElement> {
//TODO: Step 4. Download the link is `download` attribute is set. //TODO: Step 4. Download the link is `download` attribute is set.
let attr = element.get_attribute(&ns!(""), &atom!("href")).root(); let attr = element.get_attribute(&ns!(""), &atom!("href"));
match attr { match attr {
Some(ref href) => { Some(ref href) => {
let value = href.r().Value() + ismap_suffix.as_ref().map(|s| &**s).unwrap_or(""); let value = href.r().Value() + ismap_suffix.as_ref().map(|s| &**s).unwrap_or("");

View file

@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::HTMLAppletElementBinding::HTMLAppletElemen
use dom::attr::AttrValue; use dom::attr::AttrValue;
use dom::bindings::codegen::InheritTypes::HTMLAppletElementDerived; use dom::bindings::codegen::InheritTypes::HTMLAppletElementDerived;
use dom::bindings::codegen::InheritTypes::HTMLElementCast; use dom::bindings::codegen::InheritTypes::HTMLElementCast;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::{AttributeHandlers, ElementTypeId}; use dom::element::{AttributeHandlers, ElementTypeId};
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -35,7 +35,7 @@ impl HTMLAppletElementDerived for EventTarget {
impl HTMLAppletElement { impl HTMLAppletElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLAppletElement { document: &Document) -> HTMLAppletElement {
HTMLAppletElement { HTMLAppletElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLAppletElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLAppletElement, localName, prefix, document)
@ -45,19 +45,19 @@ impl HTMLAppletElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLAppletElement> { document: &Document) -> Root<HTMLAppletElement> {
let element = HTMLAppletElement::new_inherited(localName, prefix, document); let element = HTMLAppletElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLAppletElementBinding::Wrap) Node::reflect_node(box element, document, HTMLAppletElementBinding::Wrap)
} }
} }
impl<'a> HTMLAppletElementMethods for JSRef<'a, HTMLAppletElement> { impl<'a> HTMLAppletElementMethods for &'a HTMLAppletElement {
// https://html.spec.whatwg.org/#the-applet-element:dom-applet-name // https://html.spec.whatwg.org/#the-applet-element:dom-applet-name
make_getter!(Name); make_getter!(Name);
make_atomic_setter!(SetName, "name"); make_atomic_setter!(SetName, "name");
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLAppletElement> { impl<'a> VirtualMethods for &'a HTMLAppletElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
Some(HTMLElementCast::from_borrowed_ref(self) as &VirtualMethods) Some(HTMLElementCast::from_borrowed_ref(self) as &VirtualMethods)
} }

View file

@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::HTMLAreaElementBinding;
use dom::bindings::codegen::Bindings::HTMLAreaElementBinding::HTMLAreaElementMethods; use dom::bindings::codegen::Bindings::HTMLAreaElementBinding::HTMLAreaElementMethods;
use dom::bindings::codegen::InheritTypes::{HTMLAreaElementDerived, HTMLElementCast}; use dom::bindings::codegen::InheritTypes::{HTMLAreaElementDerived, HTMLElementCast};
use dom::bindings::codegen::InheritTypes::ElementCast; use dom::bindings::codegen::InheritTypes::ElementCast;
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Temporary}; use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
use dom::document::Document; use dom::document::Document;
use dom::domtokenlist::DOMTokenList; use dom::domtokenlist::DOMTokenList;
@ -36,7 +36,7 @@ impl HTMLAreaElementDerived for EventTarget {
} }
impl HTMLAreaElement { impl HTMLAreaElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLAreaElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLAreaElement {
HTMLAreaElement { HTMLAreaElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLAreaElement, localName, prefix, document), htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLAreaElement, localName, prefix, document),
rel_list: Default::default(), rel_list: Default::default(),
@ -46,15 +46,15 @@ impl HTMLAreaElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLAreaElement> { document: &Document) -> Root<HTMLAreaElement> {
let element = HTMLAreaElement::new_inherited(localName, prefix, document); let element = HTMLAreaElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLAreaElementBinding::Wrap) Node::reflect_node(box element, document, HTMLAreaElementBinding::Wrap)
} }
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLAreaElement> { impl<'a> VirtualMethods for &'a HTMLAreaElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
@ -66,8 +66,8 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLAreaElement> {
} }
} }
impl<'a> HTMLAreaElementMethods for JSRef<'a, HTMLAreaElement> { impl<'a> HTMLAreaElementMethods for &'a HTMLAreaElement {
fn RelList(self) -> Temporary<DOMTokenList> { fn RelList(self) -> Root<DOMTokenList> {
self.rel_list.or_init(|| { self.rel_list.or_init(|| {
DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel")) DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel"))
}) })

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLAudioElementBinding; use dom::bindings::codegen::Bindings::HTMLAudioElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLAudioElementDerived; use dom::bindings::codegen::InheritTypes::HTMLAudioElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -30,7 +30,7 @@ impl HTMLAudioElementDerived for EventTarget {
impl HTMLAudioElement { impl HTMLAudioElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLAudioElement { document: &Document) -> HTMLAudioElement {
HTMLAudioElement { HTMLAudioElement {
htmlmediaelement: htmlmediaelement:
HTMLMediaElement::new_inherited(HTMLMediaElementTypeId::HTMLAudioElement, localName, prefix, document) HTMLMediaElement::new_inherited(HTMLMediaElementTypeId::HTMLAudioElement, localName, prefix, document)
@ -40,7 +40,7 @@ impl HTMLAudioElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLAudioElement> { document: &Document) -> Root<HTMLAudioElement> {
let element = HTMLAudioElement::new_inherited(localName, prefix, document); let element = HTMLAudioElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLAudioElementBinding::Wrap) Node::reflect_node(box element, document, HTMLAudioElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLBaseElementBinding; use dom::bindings::codegen::Bindings::HTMLBaseElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLBaseElementDerived; use dom::bindings::codegen::InheritTypes::HTMLBaseElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLBaseElementDerived for EventTarget {
} }
impl HTMLBaseElement { impl HTMLBaseElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLBaseElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLBaseElement {
HTMLBaseElement { HTMLBaseElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLBaseElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLBaseElement, localName, prefix, document)
} }
@ -35,7 +35,7 @@ impl HTMLBaseElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLBaseElement> { document: &Document) -> Root<HTMLBaseElement> {
let element = HTMLBaseElement::new_inherited(localName, prefix, document); let element = HTMLBaseElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLBaseElementBinding::Wrap) Node::reflect_node(box element, document, HTMLBaseElementBinding::Wrap)
} }

View file

@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{self, HTMLBodyEle
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; 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::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLElementCast};
use dom::bindings::js::{JSRef, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -25,6 +25,7 @@ use util::str::{self, DOMString};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::Cell; use std::cell::Cell;
use std::rc::Rc;
use time; use time;
/// How long we should wait before performing the initial reflow after `<body>` is parsed, in /// How long we should wait before performing the initial reflow after `<body>` is parsed, in
@ -45,7 +46,7 @@ impl HTMLBodyElementDerived for EventTarget {
} }
impl HTMLBodyElement { impl HTMLBodyElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document)
-> HTMLBodyElement { -> HTMLBodyElement {
HTMLBodyElement { HTMLBodyElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLBodyElement, htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLBodyElement,
@ -57,43 +58,43 @@ impl HTMLBodyElement {
} }
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) pub fn new(localName: DOMString, prefix: Option<DOMString>, document: &Document)
-> Temporary<HTMLBodyElement> { -> Root<HTMLBodyElement> {
let element = HTMLBodyElement::new_inherited(localName, prefix, document); let element = HTMLBodyElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLBodyElementBinding::Wrap) Node::reflect_node(box element, document, HTMLBodyElementBinding::Wrap)
} }
} }
impl<'a> HTMLBodyElementMethods for JSRef<'a, HTMLBodyElement> { impl<'a> HTMLBodyElementMethods for &'a HTMLBodyElement {
// https://html.spec.whatwg.org/#dom-body-bgcolor // https://html.spec.whatwg.org/#dom-body-bgcolor
make_getter!(BgColor, "bgcolor"); make_getter!(BgColor, "bgcolor");
make_setter!(SetBgColor, "bgcolor"); make_setter!(SetBgColor, "bgcolor");
fn GetOnunload(self) -> Option<EventHandlerNonNull> { fn GetOnunload(self) -> Option<Rc<EventHandlerNonNull>> {
let win = window_from_node(self).root(); let win = window_from_node(self);
win.r().GetOnunload() win.r().GetOnunload()
} }
fn SetOnunload(self, listener: Option<EventHandlerNonNull>) { fn SetOnunload(self, listener: Option<Rc<EventHandlerNonNull>>) {
let win = window_from_node(self).root(); let win = window_from_node(self);
win.r().SetOnunload(listener) win.r().SetOnunload(listener)
} }
} }
pub trait HTMLBodyElementHelpers { pub trait HTMLBodyElementHelpers {
fn get_background_color(&self) -> Option<RGBA>; fn get_background_color(self) -> Option<RGBA>;
} }
impl HTMLBodyElementHelpers for HTMLBodyElement { impl<'a> HTMLBodyElementHelpers for &'a HTMLBodyElement {
fn get_background_color(&self) -> Option<RGBA> { fn get_background_color(self) -> Option<RGBA> {
self.background_color.get() self.background_color.get()
} }
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> { impl<'a> VirtualMethods for &'a HTMLBodyElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let element: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let element: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(element as &VirtualMethods) Some(element as &VirtualMethods)
} }
@ -106,15 +107,15 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
return return
} }
let window = window_from_node(*self).root(); let window = window_from_node(*self);
let document = window.r().Document().root(); let document = window.r().Document();
document.r().set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY); document.r().set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY);
let ConstellationChan(ref chan) = window.r().constellation_chan(); let ConstellationChan(ref chan) = window.r().constellation_chan();
let event = ConstellationMsg::HeadParsed; let event = ConstellationMsg::HeadParsed;
chan.send(event).unwrap(); chan.send(event).unwrap();
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
@ -126,11 +127,11 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
"onbeforeunload", "onhashchange", "onlanguagechange", "onmessage", "onbeforeunload", "onhashchange", "onlanguagechange", "onmessage",
"onoffline", "ononline", "onpagehide", "onpageshow", "onpopstate", "onoffline", "ononline", "onpagehide", "onpageshow", "onpopstate",
"onstorage", "onresize", "onunload", "onerror"]; "onstorage", "onresize", "onunload", "onerror"];
let window = window_from_node(*self).root(); let window = window_from_node(*self);
let (cx, url, reflector) = (window.r().get_cx(), let (cx, url, reflector) = (window.r().get_cx(),
window.r().get_url(), window.r().get_url(),
window.r().reflector().get_jsobject()); window.r().reflector().get_jsobject());
let evtarget: JSRef<EventTarget> = let evtarget =
if FORWARDED_EVENTS.iter().any(|&event| &**name == event) { if FORWARDED_EVENTS.iter().any(|&event| &**name == event) {
EventTargetCast::from_ref(window.r()) EventTargetCast::from_ref(window.r())
} else { } else {
@ -149,7 +150,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
match self.super_type() { match self.super_type() {
Some(ref s) => s.before_remove_attr(attr), Some(ref s) => s.before_remove_attr(attr),
_ => {} _ => {}

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLBRElementBinding; use dom::bindings::codegen::Bindings::HTMLBRElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLBRElementDerived; use dom::bindings::codegen::InheritTypes::HTMLBRElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLBRElementDerived for EventTarget {
} }
impl HTMLBRElement { impl HTMLBRElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLBRElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLBRElement {
HTMLBRElement { HTMLBRElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLBRElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLBRElement, localName, prefix, document)
} }
@ -35,7 +35,7 @@ impl HTMLBRElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLBRElement> { document: &Document) -> Root<HTMLBRElement> {
let element = HTMLBRElement::new_inherited(localName, prefix, document); let element = HTMLBRElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLBRElementBinding::Wrap) Node::reflect_node(box element, document, HTMLBRElementBinding::Wrap)
} }

View file

@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods; use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLButtonElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLButtonElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLButtonElementDerived, HTMLFieldSetElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLButtonElementDerived, HTMLFieldSetElementDerived};
use dom::bindings::js::{JSRef, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::{AttributeHandlers, Element, ElementTypeId}; use dom::element::{AttributeHandlers, Element, ElementTypeId};
use dom::element::ActivationElementHelpers; use dom::element::ActivationElementHelpers;
@ -54,7 +54,7 @@ impl HTMLButtonElementDerived for EventTarget {
impl HTMLButtonElement { impl HTMLButtonElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLButtonElement { document: &Document) -> HTMLButtonElement {
HTMLButtonElement { HTMLButtonElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLButtonElement, localName, prefix, document), HTMLElement::new_inherited(HTMLElementTypeId::HTMLButtonElement, localName, prefix, document),
@ -66,15 +66,15 @@ impl HTMLButtonElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLButtonElement> { document: &Document) -> Root<HTMLButtonElement> {
let element = HTMLButtonElement::new_inherited(localName, prefix, document); let element = HTMLButtonElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLButtonElementBinding::Wrap) Node::reflect_node(box element, document, HTMLButtonElementBinding::Wrap)
} }
} }
impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> { impl<'a> HTMLButtonElementMethods for &'a HTMLButtonElement {
fn Validity(self) -> Temporary<ValidityState> { fn Validity(self) -> Root<ValidityState> {
let window = window_from_node(self).root(); let window = window_from_node(self);
ValidityState::new(window.r()) ValidityState::new(window.r())
} }
@ -86,7 +86,7 @@ impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
// https://html.spec.whatwg.org/multipage/#dom-button-type // https://html.spec.whatwg.org/multipage/#dom-button-type
fn Type(self) -> DOMString { fn Type(self) -> DOMString {
let elem: JSRef<Element> = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
let ty = elem.get_string_attribute(&atom!("type")).into_ascii_lowercase(); let ty = elem.get_string_attribute(&atom!("type")).into_ascii_lowercase();
// https://html.spec.whatwg.org/multipage/#attr-button-type // https://html.spec.whatwg.org/multipage/#attr-button-type
match &*ty { match &*ty {
@ -129,20 +129,20 @@ impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
make_setter!(SetValue, "value"); make_setter!(SetValue, "value");
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLButtonElement> { impl<'a> VirtualMethods for &'a HTMLButtonElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(true); node.set_disabled_state(true);
node.set_enabled_state(false); node.set_enabled_state(false);
}, },
@ -150,14 +150,14 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLButtonElement> {
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(false); node.set_disabled_state(false);
node.set_enabled_state(true); node.set_enabled_state(true);
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
@ -171,7 +171,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLButtonElement> {
s.bind_to_tree(tree_in_doc); s.bind_to_tree(tree_in_doc);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} }
@ -180,8 +180,8 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLButtonElement> {
s.unbind_from_tree(tree_in_doc); s.unbind_from_tree(tree_in_doc);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.root().r().is_htmlfieldsetelement()) { if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) {
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} else { } else {
node.check_disabled_attribute(); node.check_disabled_attribute();
@ -189,20 +189,20 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLButtonElement> {
} }
} }
impl<'a> FormControl<'a> for JSRef<'a, HTMLButtonElement> { impl<'a> FormControl<'a> for &'a HTMLButtonElement {
fn to_element(self) -> JSRef<'a, Element> { fn to_element(self) -> &'a Element {
ElementCast::from_ref(self) ElementCast::from_ref(self)
} }
} }
impl<'a> Activatable for JSRef<'a, HTMLButtonElement> { impl<'a> Activatable for &'a HTMLButtonElement {
fn as_element(&self) -> Temporary<Element> { fn as_element<'b>(&'b self) -> &'b Element {
Temporary::from_rooted(ElementCast::from_ref(*self)) ElementCast::from_ref(*self)
} }
fn is_instance_activatable(&self) -> bool { fn is_instance_activatable(&self) -> bool {
//https://html.spec.whatwg.org/multipage/#the-button-element //https://html.spec.whatwg.org/multipage/#the-button-element
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
!(node.get_disabled_state()) !(node.get_disabled_state())
} }
@ -216,14 +216,14 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> {
} }
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps // https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
fn activation_behavior(&self, _event: JSRef<Event>, _target: JSRef<EventTarget>) { fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
let ty = self.button_type.get(); let ty = self.button_type.get();
match ty { match ty {
//https://html.spec.whatwg.org/multipage/#attr-button-type-submit-state //https://html.spec.whatwg.org/multipage/#attr-button-type-submit-state
ButtonType::ButtonSubmit => { ButtonType::ButtonSubmit => {
self.form_owner().map(|o| { self.form_owner().map(|o| {
o.root().r().submit(SubmittedFrom::NotFromFormSubmitMethod, o.r().submit(SubmittedFrom::NotFromFormSubmitMethod,
FormSubmitter::ButtonElement(self.clone())) FormSubmitter::ButtonElement(self.clone()))
}); });
}, },
_ => () _ => ()
@ -233,10 +233,10 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> {
// https://html.spec.whatwg.org/multipage/#implicit-submission // https://html.spec.whatwg.org/multipage/#implicit-submission
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) { fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) {
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
let node: JSRef<Node> = NodeCast::from_ref(doc.r()); let node = NodeCast::from_ref(doc.r());
let owner = self.form_owner(); let owner = self.form_owner();
let elem: JSRef<Element> = ElementCast::from_ref(*self); let elem = ElementCast::from_ref(*self);
if owner.is_none() || elem.click_in_progress() { if owner.is_none() || elem.click_in_progress() {
return; return;
} }
@ -244,8 +244,7 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> {
// and only then performing actions which may modify the DOM tree // and only then performing actions which may modify the DOM tree
unsafe { unsafe {
node.query_selector_iter("button[type=submit]".to_owned()).unwrap() node.query_selector_iter("button[type=submit]".to_owned()).unwrap()
.filter_map(HTMLButtonElementCast::to_temporary) .filter_map(HTMLButtonElementCast::to_root)
.map(|t| t.root())
.find(|r| r.r().form_owner() == owner) .find(|r| r.r().form_owner() == owner)
.map(|s| s.r().synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey)); .map(|s| s.r().synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey));
} }

View file

@ -12,13 +12,11 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, LayoutJS, MutNullableHeap, HeapGCValue, Rootable}; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, HeapGCValue, Root};
use dom::bindings::js::Temporary;
use dom::bindings::js::Unrooted;
use dom::bindings::utils::{Reflectable}; use dom::bindings::utils::{Reflectable};
use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
use dom::document::Document; use dom::document::Document;
use dom::element::{Element, AttributeHandlers}; use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@ -27,7 +25,7 @@ use dom::virtualmethods::VirtualMethods;
use dom::webglrenderingcontext::{WebGLRenderingContext, LayoutCanvasWebGLRenderingContextHelpers}; use dom::webglrenderingcontext::{WebGLRenderingContext, LayoutCanvasWebGLRenderingContextHelpers};
use util::str::{DOMString, parse_unsigned_integer}; use util::str::{DOMString, parse_unsigned_integer};
use js::jsapi::{JSContext}; use js::jsapi::{JSContext, HandleValue};
use js::jsval::JSVal; use js::jsval::JSVal;
use offscreen_gl_context::GLContextAttributes; use offscreen_gl_context::GLContextAttributes;
@ -58,6 +56,12 @@ pub struct HTMLCanvasElement {
height: Cell<u32>, height: Cell<u32>,
} }
impl PartialEq for HTMLCanvasElement {
fn eq(&self, other: &HTMLCanvasElement) -> bool {
self as *const HTMLCanvasElement == &*other
}
}
impl HTMLCanvasElementDerived for EventTarget { impl HTMLCanvasElementDerived for EventTarget {
fn is_htmlcanvaselement(&self) -> bool { fn is_htmlcanvaselement(&self) -> bool {
*self.type_id() == *self.type_id() ==
@ -69,7 +73,7 @@ impl HTMLCanvasElementDerived for EventTarget {
impl HTMLCanvasElement { impl HTMLCanvasElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLCanvasElement { document: &Document) -> HTMLCanvasElement {
HTMLCanvasElement { HTMLCanvasElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLCanvasElement, localName, prefix, document), HTMLElement::new_inherited(HTMLElementTypeId::HTMLCanvasElement, localName, prefix, document),
@ -82,7 +86,7 @@ impl HTMLCanvasElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLCanvasElement> { document: &Document) -> Root<HTMLCanvasElement> {
let element = HTMLCanvasElement::new_inherited(localName, prefix, document); let element = HTMLCanvasElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap)
} }
@ -139,37 +143,37 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> {
} }
pub trait HTMLCanvasElementHelpers { pub trait HTMLCanvasElementHelpers {
fn get_or_init_2d_context(self) -> Option<Temporary<CanvasRenderingContext2D>>; fn get_or_init_2d_context(self) -> Option<Root<CanvasRenderingContext2D>>;
fn get_or_init_webgl_context(self, fn get_or_init_webgl_context(self,
cx: *mut JSContext, cx: *mut JSContext,
attrs: Option<&JSVal>) -> Option<Temporary<WebGLRenderingContext>>; attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>>;
fn is_valid(self) -> bool; fn is_valid(self) -> bool;
} }
impl<'a> HTMLCanvasElementHelpers for JSRef<'a, HTMLCanvasElement> { impl<'a> HTMLCanvasElementHelpers for &'a HTMLCanvasElement {
fn get_or_init_2d_context(self) -> Option<Temporary<CanvasRenderingContext2D>> { fn get_or_init_2d_context(self) -> Option<Root<CanvasRenderingContext2D>> {
if self.context.get().is_none() { if self.context.get().is_none() {
let window = window_from_node(self).root(); let window = window_from_node(self);
let size = self.get_size(); let size = self.get_size();
let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size);
self.context.set(Some(CanvasContext::Context2d(JS::from_rooted(context)))); self.context.set(Some(CanvasContext::Context2d(JS::from_rooted(&context))));
} }
match self.context.get().unwrap() { match self.context.get().unwrap() {
CanvasContext::Context2d(context) => Some(Temporary::from_rooted(context)), CanvasContext::Context2d(context) => Some(context.root()),
_ => None, _ => None,
} }
} }
fn get_or_init_webgl_context(self, fn get_or_init_webgl_context(self,
cx: *mut JSContext, cx: *mut JSContext,
attrs: Option<&JSVal>) -> Option<Temporary<WebGLRenderingContext>> { attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> {
if self.context.get().is_none() { if self.context.get().is_none() {
let window = window_from_node(self).root(); let window = window_from_node(self);
let size = self.get_size(); let size = self.get_size();
let attrs = if let Some(webgl_attributes) = attrs { let attrs = if let Some(webgl_attributes) = attrs {
if let Ok(ref attrs) = WebGLContextAttributes::new(cx, *webgl_attributes) { if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) {
From::from(attrs) From::from(attrs)
} else { } else {
debug!("Unexpected error on conversion of WebGLContextAttributes"); debug!("Unexpected error on conversion of WebGLContextAttributes");
@ -181,12 +185,12 @@ impl<'a> HTMLCanvasElementHelpers for JSRef<'a, HTMLCanvasElement> {
let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs);
self.context.set(maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(ctx)))); self.context.set(maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))));
} }
if let Some(context) = self.context.get() { if let Some(context) = self.context.get() {
match context { match context {
CanvasContext::WebGL(context) => Some(Temporary::from_rooted(context)), CanvasContext::WebGL(context) => Some(context.root()),
_ => None, _ => None,
} }
} else { } else {
@ -199,13 +203,13 @@ impl<'a> HTMLCanvasElementHelpers for JSRef<'a, HTMLCanvasElement> {
} }
} }
impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> { impl<'a> HTMLCanvasElementMethods for &'a HTMLCanvasElement {
fn Width(self) -> u32 { fn Width(self) -> u32 {
self.width.get() self.width.get()
} }
fn SetWidth(self, width: u32) { fn SetWidth(self, width: u32) {
let elem: JSRef<Element> = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
elem.set_uint_attribute(&atom!("width"), width) elem.set_uint_attribute(&atom!("width"), width)
} }
@ -214,38 +218,38 @@ impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> {
} }
fn SetHeight(self, height: u32) { fn SetHeight(self, height: u32) {
let elem: JSRef<Element> = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
elem.set_uint_attribute(&atom!("height"), height) elem.set_uint_attribute(&atom!("height"), height)
} }
fn GetContext(self, fn GetContext(self,
cx: *mut JSContext, cx: *mut JSContext,
id: DOMString, id: DOMString,
attributes: Vec<JSVal>) attributes: Vec<HandleValue>)
-> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> {
match &*id { match &*id {
"2d" => { "2d" => {
self.get_or_init_2d_context() self.get_or_init_2d_context()
.map(|ctx| CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D( .map(|ctx| CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D(
Unrooted::from_temporary(ctx))) ctx))
} }
"webgl" | "experimental-webgl" => { "webgl" | "experimental-webgl" => {
self.get_or_init_webgl_context(cx, attributes.get(0)) self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p))
.map(|ctx| CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext( .map(|ctx| CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext(
Unrooted::from_temporary(ctx))) ctx))
} }
_ => None _ => None
} }
} }
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLCanvasElement> { impl<'a> VirtualMethods for &'a HTMLCanvasElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let element: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let element: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(element as &VirtualMethods) Some(element as &VirtualMethods)
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
@ -267,7 +271,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLCanvasElement> {
} }
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }

View file

@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::HTMLCollectionBinding;
use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods; use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Rootable, Temporary}; use dom::bindings::js::{JS, Root};
use dom::bindings::trace::JSTraceable; use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers, ElementHelpers}; use dom::element::{Element, AttributeHandlers, ElementHelpers};
@ -20,7 +20,7 @@ use std::iter::{FilterMap, Skip};
use string_cache::{Atom, Namespace}; use string_cache::{Atom, Namespace};
pub trait CollectionFilter : JSTraceable { pub trait CollectionFilter : JSTraceable {
fn filter<'a>(&self, elem: JSRef<'a, Element>, root: JSRef<'a, Node>) -> bool; fn filter<'a>(&self, elem: &'a Element, root: &'a Node) -> bool;
} }
#[jstraceable] #[jstraceable]
@ -44,26 +44,26 @@ impl HTMLCollection {
} }
} }
pub fn new(window: JSRef<Window>, collection: CollectionTypeId) -> Temporary<HTMLCollection> { pub fn new(window: &Window, collection: CollectionTypeId) -> Root<HTMLCollection> {
reflect_dom_object(box HTMLCollection::new_inherited(collection), reflect_dom_object(box HTMLCollection::new_inherited(collection),
GlobalRef::Window(window), HTMLCollectionBinding::Wrap) GlobalRef::Window(window), HTMLCollectionBinding::Wrap)
} }
} }
impl HTMLCollection { impl HTMLCollection {
pub fn create(window: JSRef<Window>, root: JSRef<Node>, pub fn create(window: &Window, root: &Node,
filter: Box<CollectionFilter+'static>) -> Temporary<HTMLCollection> { filter: Box<CollectionFilter+'static>) -> Root<HTMLCollection> {
HTMLCollection::new(window, CollectionTypeId::Live(JS::from_rooted(root), filter)) HTMLCollection::new(window, CollectionTypeId::Live(JS::from_ref(root), filter))
} }
fn all_elements(window: JSRef<Window>, root: JSRef<Node>, fn all_elements(window: &Window, root: &Node,
namespace_filter: Option<Namespace>) -> Temporary<HTMLCollection> { namespace_filter: Option<Namespace>) -> Root<HTMLCollection> {
#[jstraceable] #[jstraceable]
struct AllElementFilter { struct AllElementFilter {
namespace_filter: Option<Namespace> namespace_filter: Option<Namespace>
} }
impl CollectionFilter for AllElementFilter { impl CollectionFilter for AllElementFilter {
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool { fn filter(&self, elem: &Element, _root: &Node) -> bool {
match self.namespace_filter { match self.namespace_filter {
None => true, None => true,
Some(ref namespace) => *elem.namespace() == *namespace Some(ref namespace) => *elem.namespace() == *namespace
@ -74,8 +74,8 @@ impl HTMLCollection {
HTMLCollection::create(window, root, box filter) HTMLCollection::create(window, root, box filter)
} }
pub fn by_tag_name(window: JSRef<Window>, root: JSRef<Node>, tag: DOMString) pub fn by_tag_name(window: &Window, root: &Node, tag: DOMString)
-> Temporary<HTMLCollection> { -> Root<HTMLCollection> {
if tag == "*" { if tag == "*" {
return HTMLCollection::all_elements(window, root, None); return HTMLCollection::all_elements(window, root, None);
} }
@ -86,7 +86,7 @@ impl HTMLCollection {
ascii_lower_tag: Atom, ascii_lower_tag: Atom,
} }
impl CollectionFilter for TagNameFilter { impl CollectionFilter for TagNameFilter {
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool { fn filter(&self, elem: &Element, _root: &Node) -> bool {
if elem.html_element_in_html_document() { if elem.html_element_in_html_document() {
*elem.local_name() == self.ascii_lower_tag *elem.local_name() == self.ascii_lower_tag
} else { } else {
@ -101,8 +101,8 @@ impl HTMLCollection {
HTMLCollection::create(window, root, box filter) HTMLCollection::create(window, root, box filter)
} }
pub fn by_tag_name_ns(window: JSRef<Window>, root: JSRef<Node>, tag: DOMString, pub fn by_tag_name_ns(window: &Window, root: &Node, tag: DOMString,
maybe_ns: Option<DOMString>) -> Temporary<HTMLCollection> { maybe_ns: Option<DOMString>) -> Root<HTMLCollection> {
let namespace_filter = match maybe_ns { let namespace_filter = match maybe_ns {
Some(ref namespace) if namespace == &"*" => None, Some(ref namespace) if namespace == &"*" => None,
ns => Some(namespace::from_domstring(ns)), ns => Some(namespace::from_domstring(ns)),
@ -117,7 +117,7 @@ impl HTMLCollection {
namespace_filter: Option<Namespace> namespace_filter: Option<Namespace>
} }
impl CollectionFilter for TagNameNSFilter { impl CollectionFilter for TagNameNSFilter {
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool { fn filter(&self, elem: &Element, _root: &Node) -> bool {
let ns_match = match self.namespace_filter { let ns_match = match self.namespace_filter {
Some(ref namespace) => { Some(ref namespace) => {
*elem.namespace() == *namespace *elem.namespace() == *namespace
@ -134,14 +134,14 @@ impl HTMLCollection {
HTMLCollection::create(window, root, box filter) HTMLCollection::create(window, root, box filter)
} }
pub fn by_class_name(window: JSRef<Window>, root: JSRef<Node>, classes: DOMString) pub fn by_class_name(window: &Window, root: &Node, classes: DOMString)
-> Temporary<HTMLCollection> { -> Root<HTMLCollection> {
#[jstraceable] #[jstraceable]
struct ClassNameFilter { struct ClassNameFilter {
classes: Vec<Atom> classes: Vec<Atom>
} }
impl CollectionFilter for ClassNameFilter { impl CollectionFilter for ClassNameFilter {
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool { fn filter(&self, elem: &Element, _root: &Node) -> bool {
self.classes.iter().all(|class| elem.has_class(class)) self.classes.iter().all(|class| elem.has_class(class))
} }
} }
@ -153,30 +153,30 @@ impl HTMLCollection {
HTMLCollection::create(window, root, box filter) HTMLCollection::create(window, root, box filter)
} }
pub fn children(window: JSRef<Window>, root: JSRef<Node>) -> Temporary<HTMLCollection> { pub fn children(window: &Window, root: &Node) -> Root<HTMLCollection> {
#[jstraceable] #[jstraceable]
struct ElementChildFilter; struct ElementChildFilter;
impl CollectionFilter for ElementChildFilter { impl CollectionFilter for ElementChildFilter {
fn filter(&self, elem: JSRef<Element>, root: JSRef<Node>) -> bool { fn filter(&self, elem: &Element, root: &Node) -> bool {
root.is_parent_of(NodeCast::from_ref(elem)) root.is_parent_of(NodeCast::from_ref(elem))
} }
} }
HTMLCollection::create(window, root, box ElementChildFilter) HTMLCollection::create(window, root, box ElementChildFilter)
} }
fn traverse(root: JSRef<Node>) fn traverse(root: &Node)
-> FilterMap<Skip<TreeIterator>, -> FilterMap<Skip<TreeIterator>,
fn(Temporary<Node>) -> Option<Temporary<Element>>> { fn(Root<Node>) -> Option<Root<Element>>> {
fn to_temporary(node: Temporary<Node>) -> Option<Temporary<Element>> { fn to_temporary(node: Root<Node>) -> Option<Root<Element>> {
ElementCast::to_temporary(node) ElementCast::to_root(node)
} }
root.traverse_preorder() root.traverse_preorder()
.skip(1) .skip(1)
.filter_map(to_temporary as fn(Temporary<Node>) -> Option<Temporary<Element>>) .filter_map(to_temporary)
} }
} }
impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> { impl<'a> HTMLCollectionMethods for &'a HTMLCollection {
// https://dom.spec.whatwg.org/#dom-htmlcollection-length // https://dom.spec.whatwg.org/#dom-htmlcollection-length
fn Length(self) -> u32 { fn Length(self) -> u32 {
match self.collection { match self.collection {
@ -184,30 +184,29 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
CollectionTypeId::Live(ref root, ref filter) => { CollectionTypeId::Live(ref root, ref filter) => {
let root = root.root(); let root = root.root();
HTMLCollection::traverse(root.r()) HTMLCollection::traverse(root.r())
.filter(|element| filter.filter(element.root().r(), root.r())) .filter(|element| filter.filter(element.r(), root.r()))
.count() as u32 .count() as u32
} }
} }
} }
// https://dom.spec.whatwg.org/#dom-htmlcollection-item // https://dom.spec.whatwg.org/#dom-htmlcollection-item
fn Item(self, index: u32) -> Option<Temporary<Element>> { fn Item(self, index: u32) -> Option<Root<Element>> {
let index = index as usize; let index = index as usize;
match self.collection { match self.collection {
CollectionTypeId::Static(ref elems) => elems CollectionTypeId::Static(ref elems) => elems
.get(index) .get(index).map(|t| t.root()),
.map(|elem| Temporary::from_rooted(elem.clone())),
CollectionTypeId::Live(ref root, ref filter) => { CollectionTypeId::Live(ref root, ref filter) => {
let root = root.root(); let root = root.root();
HTMLCollection::traverse(root.r()) HTMLCollection::traverse(root.r())
.filter(|element| filter.filter(element.root().r(), root.r())) .filter(|element| filter.filter(element.r(), root.r()))
.nth(index) .nth(index)
} }
} }
} }
// https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem // https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem
fn NamedItem(self, key: DOMString) -> Option<Temporary<Element>> { fn NamedItem(self, key: DOMString) -> Option<Root<Element>> {
// Step 1. // Step 1.
if key.is_empty() { if key.is_empty() {
return None; return None;
@ -219,28 +218,25 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
.map(|elem| elem.root()) .map(|elem| elem.root())
.find(|elem| { .find(|elem| {
elem.r().get_string_attribute(&atom!("name")) == key || elem.r().get_string_attribute(&atom!("name")) == key ||
elem.r().get_string_attribute(&atom!("id")) == key }) elem.r().get_string_attribute(&atom!("id")) == key }),
.map(|maybe_elem| Temporary::from_rooted(maybe_elem.r())),
CollectionTypeId::Live(ref root, ref filter) => { CollectionTypeId::Live(ref root, ref filter) => {
let root = root.root(); let root = root.root();
HTMLCollection::traverse(root.r()) HTMLCollection::traverse(root.r())
.map(|element| element.root())
.filter(|element| filter.filter(element.r(), root.r())) .filter(|element| filter.filter(element.r(), root.r()))
.find(|elem| { .find(|elem| {
elem.r().get_string_attribute(&atom!("name")) == key || elem.r().get_string_attribute(&atom!("name")) == key ||
elem.r().get_string_attribute(&atom!("id")) == key }) elem.r().get_string_attribute(&atom!("id")) == key })
.map(|elem| Temporary::from_rooted(elem.r()))
} }
} }
} }
fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<Temporary<Element>> { fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<Root<Element>> {
let maybe_elem = self.Item(index); let maybe_elem = self.Item(index);
*found = maybe_elem.is_some(); *found = maybe_elem.is_some();
maybe_elem maybe_elem
} }
fn NamedGetter(self, name: DOMString, found: &mut bool) -> Option<Temporary<Element>> { fn NamedGetter(self, name: DOMString, found: &mut bool) -> Option<Root<Element>> {
let maybe_elem = self.NamedItem(name); let maybe_elem = self.NamedItem(name);
*found = maybe_elem.is_some(); *found = maybe_elem.is_some();
maybe_elem maybe_elem

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLDataElementBinding; use dom::bindings::codegen::Bindings::HTMLDataElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLDataElementDerived; use dom::bindings::codegen::InheritTypes::HTMLDataElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLDataElementDerived for EventTarget {
impl HTMLDataElement { impl HTMLDataElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLDataElement { document: &Document) -> HTMLDataElement {
HTMLDataElement { HTMLDataElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLDataElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLDataElement, localName, prefix, document)
} }
@ -37,7 +37,7 @@ impl HTMLDataElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDataElement> { document: &Document) -> Root<HTMLDataElement> {
let element = HTMLDataElement::new_inherited(localName, prefix, document); let element = HTMLDataElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLDataElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDataElementBinding::Wrap)
} }

View file

@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::HTMLDataListElementBinding;
use dom::bindings::codegen::Bindings::HTMLDataListElementBinding::HTMLDataListElementMethods; use dom::bindings::codegen::Bindings::HTMLDataListElementBinding::HTMLDataListElementMethods;
use dom::bindings::codegen::InheritTypes::{HTMLDataListElementDerived, HTMLOptionElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLDataListElementDerived, HTMLOptionElementDerived};
use dom::bindings::codegen::InheritTypes::NodeCast; use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::js::{JSRef, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::Element; use dom::element::Element;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -32,7 +32,7 @@ impl HTMLDataListElementDerived for EventTarget {
impl HTMLDataListElement { impl HTMLDataListElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLDataListElement { document: &Document) -> HTMLDataListElement {
HTMLDataListElement { HTMLDataListElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLDataListElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLDataListElement, localName, prefix, document)
@ -42,24 +42,24 @@ impl HTMLDataListElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDataListElement> { document: &Document) -> Root<HTMLDataListElement> {
let element = HTMLDataListElement::new_inherited(localName, prefix, document); let element = HTMLDataListElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLDataListElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDataListElementBinding::Wrap)
} }
} }
impl<'a> HTMLDataListElementMethods for JSRef<'a, HTMLDataListElement> { impl<'a> HTMLDataListElementMethods for &'a HTMLDataListElement {
fn Options(self) -> Temporary<HTMLCollection> { fn Options(self) -> Root<HTMLCollection> {
#[jstraceable] #[jstraceable]
struct HTMLDataListOptionsFilter; struct HTMLDataListOptionsFilter;
impl CollectionFilter for HTMLDataListOptionsFilter { impl CollectionFilter for HTMLDataListOptionsFilter {
fn filter(&self, elem: JSRef<Element>, _root: JSRef<Node>) -> bool { fn filter(&self, elem: &Element, _root: &Node) -> bool {
elem.is_htmloptionelement() elem.is_htmloptionelement()
} }
} }
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let filter = box HTMLDataListOptionsFilter; let filter = box HTMLDataListOptionsFilter;
let window = window_from_node(node).root(); let window = window_from_node(node);
HTMLCollection::create(window.r(), node, filter) HTMLCollection::create(window.r(), node, filter)
} }
} }

View file

@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::HTMLDialogElementBinding;
use dom::bindings::codegen::Bindings::HTMLDialogElementBinding::HTMLDialogElementMethods; use dom::bindings::codegen::Bindings::HTMLDialogElementBinding::HTMLDialogElementMethods;
use dom::bindings::codegen::InheritTypes::HTMLDialogElementDerived; use dom::bindings::codegen::InheritTypes::HTMLDialogElementDerived;
use dom::bindings::cell::DOMRefCell; use dom::bindings::cell::DOMRefCell;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -34,7 +34,7 @@ impl HTMLDialogElementDerived for EventTarget {
impl HTMLDialogElement { impl HTMLDialogElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLDialogElement { document: &Document) -> HTMLDialogElement {
HTMLDialogElement { HTMLDialogElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLDialogElement, localName, prefix, document), HTMLElement::new_inherited(HTMLElementTypeId::HTMLDialogElement, localName, prefix, document),
@ -45,13 +45,13 @@ impl HTMLDialogElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDialogElement> { document: &Document) -> Root<HTMLDialogElement> {
let element = HTMLDialogElement::new_inherited(localName, prefix, document); let element = HTMLDialogElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLDialogElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDialogElementBinding::Wrap)
} }
} }
impl<'a> HTMLDialogElementMethods for JSRef<'a, HTMLDialogElement> { impl<'a> HTMLDialogElementMethods for &'a HTMLDialogElement {
// https://html.spec.whatwg.org/multipage/#dom-dialog-open // https://html.spec.whatwg.org/multipage/#dom-dialog-open
make_bool_getter!(Open); make_bool_getter!(Open);

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLDirectoryElementBinding; use dom::bindings::codegen::Bindings::HTMLDirectoryElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLDirectoryElementDerived; use dom::bindings::codegen::InheritTypes::HTMLDirectoryElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -28,7 +28,7 @@ impl HTMLDirectoryElementDerived for EventTarget {
impl HTMLDirectoryElement { impl HTMLDirectoryElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLDirectoryElement { document: &Document) -> HTMLDirectoryElement {
HTMLDirectoryElement { HTMLDirectoryElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLDirectoryElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLDirectoryElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLDirectoryElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDirectoryElement> { document: &Document) -> Root<HTMLDirectoryElement> {
let element = HTMLDirectoryElement::new_inherited(localName, prefix, document); let element = HTMLDirectoryElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLDirectoryElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDirectoryElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLDivElementBinding; use dom::bindings::codegen::Bindings::HTMLDivElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLDivElementDerived; use dom::bindings::codegen::InheritTypes::HTMLDivElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -28,7 +28,7 @@ impl HTMLDivElementDerived for EventTarget {
impl HTMLDivElement { impl HTMLDivElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLDivElement { document: &Document) -> HTMLDivElement {
HTMLDivElement { HTMLDivElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLDivElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLDivElement, localName, prefix, document)
} }
@ -37,7 +37,7 @@ impl HTMLDivElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDivElement> { document: &Document) -> Root<HTMLDivElement> {
let element = HTMLDivElement::new_inherited(localName, prefix, document); let element = HTMLDivElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLDivElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDivElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLDListElementBinding; use dom::bindings::codegen::Bindings::HTMLDListElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLDListElementDerived; use dom::bindings::codegen::InheritTypes::HTMLDListElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -26,7 +26,7 @@ impl HTMLDListElementDerived for EventTarget {
} }
impl HTMLDListElement { impl HTMLDListElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLDListElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLDListElement {
HTMLDListElement { HTMLDListElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLDListElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLDListElement, localName, prefix, document)
@ -36,7 +36,7 @@ impl HTMLDListElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDListElement> { document: &Document) -> Root<HTMLDListElement> {
let element = HTMLDListElement::new_inherited(localName, prefix, document); let element = HTMLDListElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLDListElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDListElementBinding::Wrap)
} }

View file

@ -13,7 +13,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFrameSetElementDerived}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLFrameSetElementDerived};
use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLInputElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLInputElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementDerived, HTMLBodyElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLElementDerived, HTMLBodyElementDerived};
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary}; use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::error::ErrorResult; use dom::bindings::error::ErrorResult;
use dom::bindings::error::Error::Syntax; use dom::bindings::error::Error::Syntax;
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
@ -37,6 +37,7 @@ use string_cache::Atom;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::default::Default; use std::default::Default;
use std::intrinsics; use std::intrinsics;
use std::rc::Rc;
#[dom_struct] #[dom_struct]
pub struct HTMLElement { pub struct HTMLElement {
@ -45,6 +46,12 @@ pub struct HTMLElement {
dataset: MutNullableHeap<JS<DOMStringMap>>, dataset: MutNullableHeap<JS<DOMStringMap>>,
} }
impl PartialEq for HTMLElement {
fn eq(&self, other: &HTMLElement) -> bool {
self as *const HTMLElement == &*other
}
}
impl HTMLElementDerived for EventTarget { impl HTMLElementDerived for EventTarget {
fn is_htmlelement(&self) -> bool { fn is_htmlelement(&self) -> bool {
match *self.type_id() { match *self.type_id() {
@ -58,7 +65,7 @@ impl HTMLElement {
pub fn new_inherited(type_id: HTMLElementTypeId, pub fn new_inherited(type_id: HTMLElementTypeId,
tag_name: DOMString, tag_name: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLElement { document: &Document) -> HTMLElement {
HTMLElement { HTMLElement {
element: element:
Element::new_inherited(ElementTypeId::HTMLElement(type_id), tag_name, ns!(HTML), prefix, document), Element::new_inherited(ElementTypeId::HTMLElement(type_id), tag_name, ns!(HTML), prefix, document),
@ -68,7 +75,7 @@ impl HTMLElement {
} }
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> Temporary<HTMLElement> { pub fn new(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> Root<HTMLElement> {
let element = HTMLElement::new_inherited(HTMLElementTypeId::HTMLElement, localName, prefix, document); let element = HTMLElement::new_inherited(HTMLElementTypeId::HTMLElement, localName, prefix, document);
Node::reflect_node(box element, document, HTMLElementBinding::Wrap) Node::reflect_node(box element, document, HTMLElementBinding::Wrap)
} }
@ -79,9 +86,9 @@ trait PrivateHTMLElementHelpers {
fn update_sequentially_focusable_status(self); fn update_sequentially_focusable_status(self);
} }
impl<'a> PrivateHTMLElementHelpers for JSRef<'a, HTMLElement> { impl<'a> PrivateHTMLElementHelpers for &'a HTMLElement {
fn is_body_or_frameset(self) -> bool { fn is_body_or_frameset(self) -> bool {
let eventtarget: JSRef<EventTarget> = EventTargetCast::from_ref(self); let eventtarget = EventTargetCast::from_ref(self);
eventtarget.is_htmlbodyelement() || eventtarget.is_htmlframesetelement() eventtarget.is_htmlbodyelement() || eventtarget.is_htmlframesetelement()
} }
@ -105,7 +112,6 @@ impl<'a> PrivateHTMLElementHelpers for JSRef<'a, HTMLElement> {
}, },
_ => { _ => {
if let Some(attr) = element.get_attribute(&ns!(""), &atom!("draggable")) { if let Some(attr) = element.get_attribute(&ns!(""), &atom!("draggable")) {
let attr = attr.root();
let attr = attr.r(); let attr = attr.r();
let value = attr.value(); let value = attr.value();
let is_true = match *value { let is_true = match *value {
@ -124,10 +130,10 @@ impl<'a> PrivateHTMLElementHelpers for JSRef<'a, HTMLElement> {
} }
} }
impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> { impl<'a> HTMLElementMethods for &'a HTMLElement {
fn Style(self) -> Temporary<CSSStyleDeclaration> { fn Style(self) -> Root<CSSStyleDeclaration> {
self.style_decl.or_init(|| { self.style_decl.or_init(|| {
let global = window_from_node(self).root(); let global = window_from_node(self);
CSSStyleDeclaration::new(global.r(), self, CSSModificationAccess::ReadWrite) CSSStyleDeclaration::new(global.r(), self, CSSModificationAccess::ReadWrite)
}) })
} }
@ -145,39 +151,39 @@ impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> {
global_event_handlers!(NoOnload); global_event_handlers!(NoOnload);
// https://html.spec.whatwg.org/multipage/#dom-dataset // https://html.spec.whatwg.org/multipage/#dom-dataset
fn Dataset(self) -> Temporary<DOMStringMap> { fn Dataset(self) -> Root<DOMStringMap> {
self.dataset.or_init(|| DOMStringMap::new(self)) self.dataset.or_init(|| DOMStringMap::new(self))
} }
fn GetOnload(self) -> Option<EventHandlerNonNull> { fn GetOnload(self) -> Option<Rc<EventHandlerNonNull>> {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
let win = window_from_node(self).root(); let win = window_from_node(self);
win.r().GetOnload() win.r().GetOnload()
} else { } else {
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self); let target = EventTargetCast::from_ref(self);
target.get_event_handler_common("load") target.get_event_handler_common("load")
} }
} }
fn SetOnload(self, listener: Option<EventHandlerNonNull>) { fn SetOnload(self, listener: Option<Rc<EventHandlerNonNull>>) {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
let win = window_from_node(self).root(); let win = window_from_node(self);
win.r().SetOnload(listener) win.r().SetOnload(listener)
} else { } else {
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self); let target = EventTargetCast::from_ref(self);
target.set_event_handler_common("load", listener) target.set_event_handler_common("load", listener)
} }
} }
// https://html.spec.whatwg.org/multipage/#dom-click // https://html.spec.whatwg.org/multipage/#dom-click
fn Click(self) { fn Click(self) {
let maybe_input: Option<JSRef<HTMLInputElement>> = HTMLInputElementCast::to_ref(self); let maybe_input: Option<&HTMLInputElement> = HTMLInputElementCast::to_ref(self);
if let Some(i) = maybe_input { if let Some(i) = maybe_input {
if i.Disabled() { if i.Disabled() {
return; return;
} }
} }
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=27430 ? // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27430 ?
element.as_maybe_activatable().map(|a| a.synthetic_click_activation(false, false, false, false)); element.as_maybe_activatable().map(|a| a.synthetic_click_activation(false, false, false, false));
} }
@ -186,8 +192,8 @@ impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> {
fn Focus(self) { fn Focus(self) {
// TODO: Mark the element as locked for focus and run the focusing steps. // TODO: Mark the element as locked for focus and run the focusing steps.
// https://html.spec.whatwg.org/multipage/#focusing-steps // https://html.spec.whatwg.org/multipage/#focusing-steps
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
let document = document_from_node(self).root(); let document = document_from_node(self);
let document = document.r(); let document = document.r();
document.begin_focus_transaction(); document.begin_focus_transaction();
document.request_focus(element); document.request_focus(element);
@ -197,12 +203,12 @@ impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> {
// https://html.spec.whatwg.org/multipage/#dom-blur // https://html.spec.whatwg.org/multipage/#dom-blur
fn Blur(self) { fn Blur(self) {
// TODO: Run the unfocusing steps. // TODO: Run the unfocusing steps.
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
if !node.get_focus_state() { if !node.get_focus_state() {
return; return;
} }
// https://html.spec.whatwg.org/multipage/#unfocusing-steps // https://html.spec.whatwg.org/multipage/#unfocusing-steps
let document = document_from_node(self).root(); let document = document_from_node(self);
document.r().begin_focus_transaction(); document.r().begin_focus_transaction();
// If `request_focus` is not called, focus will be set to None. // If `request_focus` is not called, focus will be set to None.
document.r().commit_focus_transaction(FocusType::Element); document.r().commit_focus_transaction(FocusType::Element);
@ -229,22 +235,21 @@ fn to_snake_case(name: DOMString) -> DOMString {
attr_name attr_name
} }
impl<'a> HTMLElementCustomAttributeHelpers for JSRef<'a, HTMLElement> { impl<'a> HTMLElementCustomAttributeHelpers for &'a HTMLElement {
fn set_custom_attr(self, name: DOMString, value: DOMString) -> ErrorResult { fn set_custom_attr(self, name: DOMString, value: DOMString) -> ErrorResult {
if name.chars() if name.chars()
.skip_while(|&ch| ch != '\u{2d}') .skip_while(|&ch| ch != '\u{2d}')
.nth(1).map_or(false, |ch| ch >= 'a' && ch <= 'z') { .nth(1).map_or(false, |ch| ch >= 'a' && ch <= 'z') {
return Err(Syntax); return Err(Syntax);
} }
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
element.set_custom_attribute(to_snake_case(name), value) element.set_custom_attribute(to_snake_case(name), value)
} }
fn get_custom_attr(self, local_name: DOMString) -> Option<DOMString> { fn get_custom_attr(self, local_name: DOMString) -> Option<DOMString> {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
let local_name = Atom::from_slice(&to_snake_case(local_name)); let local_name = Atom::from_slice(&to_snake_case(local_name));
element.get_attribute(&ns!(""), &local_name).map(|attr| { element.get_attribute(&ns!(""), &local_name).map(|attr| {
let attr = attr.root();
// FIXME(https://github.com/rust-lang/rust/issues/23338) // FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r(); let attr = attr.r();
let value = attr.value(); let value = attr.value();
@ -253,19 +258,19 @@ impl<'a> HTMLElementCustomAttributeHelpers for JSRef<'a, HTMLElement> {
} }
fn delete_custom_attr(self, local_name: DOMString) { fn delete_custom_attr(self, local_name: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
let local_name = Atom::from_slice(&to_snake_case(local_name)); let local_name = Atom::from_slice(&to_snake_case(local_name));
element.remove_attribute(&ns!(""), &local_name); element.remove_attribute(&ns!(""), &local_name);
} }
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLElement> { impl<'a> VirtualMethods for &'a HTMLElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let element: &JSRef<Element> = ElementCast::from_borrowed_ref(self); let element: &&Element = ElementCast::from_borrowed_ref(self);
Some(element as &VirtualMethods) Some(element as &VirtualMethods)
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
@ -278,18 +283,18 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLElement> {
self.update_sequentially_focusable_status(); self.update_sequentially_focusable_status();
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
let name = attr.local_name(); let name = attr.local_name();
if name.starts_with("on") { if name.starts_with("on") {
let window = window_from_node(*self).root(); let window = window_from_node(*self);
let (cx, url, reflector) = (window.r().get_cx(), let (cx, url, reflector) = (window.r().get_cx(),
window.r().get_url(), window.r().get_url(),
window.r().reflector().get_jsobject()); window.r().reflector().get_jsobject());
let evtarget: JSRef<EventTarget> = EventTargetCast::from_ref(*self); let evtarget = EventTargetCast::from_ref(*self);
evtarget.set_event_handler_uncompiled(cx, url, reflector, evtarget.set_event_handler_uncompiled(cx, url, reflector,
&name[2..], &name[2..],
(**attr.value()).to_owned()); (**attr.value()).to_owned());

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLEmbedElementBinding; use dom::bindings::codegen::Bindings::HTMLEmbedElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLEmbedElementDerived; use dom::bindings::codegen::InheritTypes::HTMLEmbedElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -26,7 +26,7 @@ impl HTMLEmbedElementDerived for EventTarget {
} }
impl HTMLEmbedElement { impl HTMLEmbedElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLEmbedElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLEmbedElement {
HTMLEmbedElement { HTMLEmbedElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLEmbedElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLEmbedElement, localName, prefix, document)
} }
@ -35,7 +35,7 @@ impl HTMLEmbedElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLEmbedElement> { document: &Document) -> Root<HTMLEmbedElement> {
let element = HTMLEmbedElement::new_inherited(localName, prefix, document); let element = HTMLEmbedElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLEmbedElementBinding::Wrap) Node::reflect_node(box element, document, HTMLEmbedElementBinding::Wrap)
} }

View file

@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding;
use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods; use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods;
use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, NodeCast}; use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLLegendElementDerived};
use dom::bindings::js::{JSRef, Rootable, RootedReference, Temporary}; use dom::bindings::js::{Root, RootedReference};
use dom::document::Document; use dom::document::Document;
use dom::element::{AttributeHandlers, Element, ElementHelpers}; use dom::element::{AttributeHandlers, Element, ElementHelpers};
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -37,7 +37,7 @@ impl HTMLFieldSetElementDerived for EventTarget {
impl HTMLFieldSetElement { impl HTMLFieldSetElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLFieldSetElement { document: &Document) -> HTMLFieldSetElement {
HTMLFieldSetElement { HTMLFieldSetElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLFieldSetElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLFieldSetElement, localName, prefix, document)
@ -47,32 +47,32 @@ impl HTMLFieldSetElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLFieldSetElement> { document: &Document) -> Root<HTMLFieldSetElement> {
let element = HTMLFieldSetElement::new_inherited(localName, prefix, document); let element = HTMLFieldSetElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLFieldSetElementBinding::Wrap) Node::reflect_node(box element, document, HTMLFieldSetElementBinding::Wrap)
} }
} }
impl<'a> HTMLFieldSetElementMethods for JSRef<'a, HTMLFieldSetElement> { impl<'a> HTMLFieldSetElementMethods for &'a HTMLFieldSetElement {
// https://www.whatwg.org/html/#dom-fieldset-elements // https://www.whatwg.org/html/#dom-fieldset-elements
fn Elements(self) -> Temporary<HTMLCollection> { fn Elements(self) -> Root<HTMLCollection> {
#[jstraceable] #[jstraceable]
struct ElementsFilter; struct ElementsFilter;
impl CollectionFilter for ElementsFilter { impl CollectionFilter for ElementsFilter {
fn filter<'a>(&self, elem: JSRef<'a, Element>, _root: JSRef<'a, Node>) -> bool { fn filter<'a>(&self, elem: &'a Element, _root: &'a Node) -> bool {
static TAG_NAMES: StaticStringVec = &["button", "fieldset", "input", static TAG_NAMES: StaticStringVec = &["button", "fieldset", "input",
"keygen", "object", "output", "select", "textarea"]; "keygen", "object", "output", "select", "textarea"];
TAG_NAMES.iter().any(|&tag_name| tag_name == &**elem.local_name()) TAG_NAMES.iter().any(|&tag_name| tag_name == &**elem.local_name())
} }
} }
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let filter = box ElementsFilter; let filter = box ElementsFilter;
let window = window_from_node(node).root(); let window = window_from_node(node);
HTMLCollection::create(window.r(), node, filter) HTMLCollection::create(window.r(), node, filter)
} }
fn Validity(self) -> Temporary<ValidityState> { fn Validity(self) -> Root<ValidityState> {
let window = window_from_node(self).root(); let window = window_from_node(self);
ValidityState::new(window.r()) ValidityState::new(window.r())
} }
@ -83,34 +83,31 @@ impl<'a> HTMLFieldSetElementMethods for JSRef<'a, HTMLFieldSetElement> {
make_bool_setter!(SetDisabled, "disabled"); make_bool_setter!(SetDisabled, "disabled");
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> { impl<'a> VirtualMethods for &'a HTMLFieldSetElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(true); node.set_disabled_state(true);
node.set_enabled_state(false); node.set_enabled_state(false);
let maybe_legend = node.children() let maybe_legend = node.children()
.map(|node| node.root())
.find(|node| node.r().is_htmllegendelement()); .find(|node| node.r().is_htmllegendelement());
for child in node.children() { for child in node.children() {
let child = child.root();
if Some(child.r()) == maybe_legend.r() { if Some(child.r()) == maybe_legend.r() {
continue; continue;
} }
for descendant in child.r().traverse_preorder() { for descendant in child.r().traverse_preorder() {
let descendant = descendant.root();
match descendant.r().type_id() { match descendant.r().type_id() {
NodeTypeId::Element( NodeTypeId::Element(
ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) | ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
@ -132,28 +129,25 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLFieldSetElement> {
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(false); node.set_disabled_state(false);
node.set_enabled_state(true); node.set_enabled_state(true);
let maybe_legend = node.children() let maybe_legend = node.children()
.map(|node| node.root())
.find(|node| node.r().is_htmllegendelement()); .find(|node| node.r().is_htmllegendelement());
for child in node.children() { for child in node.children() {
let child = child.root();
if Some(child.r()) == maybe_legend.r() { if Some(child.r()) == maybe_legend.r() {
continue; continue;
} }
for descendant in child.r().traverse_preorder() { for descendant in child.r().traverse_preorder() {
let descendant = descendant.root();
match descendant.r().type_id() { match descendant.r().type_id() {
NodeTypeId::Element( NodeTypeId::Element(
ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) | ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |

View file

@ -6,7 +6,7 @@ use dom::attr::{Attr, AttrHelpers};
use dom::bindings::codegen::Bindings::HTMLFontElementBinding; use dom::bindings::codegen::Bindings::HTMLFontElementBinding;
use dom::bindings::codegen::Bindings::HTMLFontElementBinding::HTMLFontElementMethods; use dom::bindings::codegen::Bindings::HTMLFontElementBinding::HTMLFontElementMethods;
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLFontElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLFontElementDerived};
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -33,7 +33,7 @@ impl HTMLFontElementDerived for EventTarget {
} }
impl HTMLFontElement { impl HTMLFontElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLFontElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLFontElement {
HTMLFontElement { HTMLFontElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLFontElement, localName, prefix, document), htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLFontElement, localName, prefix, document),
color: Cell::new(None), color: Cell::new(None),
@ -43,24 +43,24 @@ impl HTMLFontElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLFontElement> { document: &Document) -> Root<HTMLFontElement> {
let element = HTMLFontElement::new_inherited(localName, prefix, document); let element = HTMLFontElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLFontElementBinding::Wrap) Node::reflect_node(box element, document, HTMLFontElementBinding::Wrap)
} }
} }
impl<'a> HTMLFontElementMethods for JSRef<'a, HTMLFontElement> { impl<'a> HTMLFontElementMethods for &'a HTMLFontElement {
make_getter!(Color, "color"); make_getter!(Color, "color");
make_setter!(SetColor, "color"); make_setter!(SetColor, "color");
} }
impl<'a> VirtualMethods for JSRef<'a,HTMLFontElement> { impl<'a> VirtualMethods for &'a HTMLFontElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
@ -73,7 +73,7 @@ impl<'a> VirtualMethods for JSRef<'a,HTMLFontElement> {
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }

View file

@ -17,7 +17,7 @@ use dom::bindings::codegen::InheritTypes::HTMLFormElementDerived;
use dom::bindings::codegen::InheritTypes::HTMLInputElementCast; use dom::bindings::codegen::InheritTypes::HTMLInputElementCast;
use dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{HTMLTextAreaElementCast, NodeCast};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, OptionalRootable, Rootable, Temporary}; use dom::bindings::js::{Root};
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::element::{Element, AttributeHandlers}; use dom::element::{Element, AttributeHandlers};
use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable}; use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable};
@ -49,6 +49,12 @@ pub struct HTMLFormElement {
marked_for_reset: Cell<bool>, marked_for_reset: Cell<bool>,
} }
impl PartialEq for HTMLFormElement {
fn eq(&self, other: &HTMLFormElement) -> bool {
self as *const HTMLFormElement == &*other
}
}
impl HTMLFormElementDerived for EventTarget { impl HTMLFormElementDerived for EventTarget {
fn is_htmlformelement(&self) -> bool { fn is_htmlformelement(&self) -> bool {
*self.type_id() == *self.type_id() ==
@ -60,7 +66,7 @@ impl HTMLFormElementDerived for EventTarget {
impl HTMLFormElement { impl HTMLFormElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLFormElement { document: &Document) -> HTMLFormElement {
HTMLFormElement { HTMLFormElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLFormElement, localName, prefix, document), htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLFormElement, localName, prefix, document),
marked_for_reset: Cell::new(false), marked_for_reset: Cell::new(false),
@ -70,13 +76,13 @@ impl HTMLFormElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLFormElement> { document: &Document) -> Root<HTMLFormElement> {
let element = HTMLFormElement::new_inherited(localName, prefix, document); let element = HTMLFormElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLFormElementBinding::Wrap) Node::reflect_node(box element, document, HTMLFormElementBinding::Wrap)
} }
} }
impl<'a> HTMLFormElementMethods for JSRef<'a, HTMLFormElement> { impl<'a> HTMLFormElementMethods for &'a HTMLFormElement {
// https://html.spec.whatwg.org/multipage/#dom-form-acceptcharset // https://html.spec.whatwg.org/multipage/#dom-form-acceptcharset
make_getter!(AcceptCharset, "accept-charset"); make_getter!(AcceptCharset, "accept-charset");
@ -165,19 +171,19 @@ pub trait HTMLFormElementHelpers {
fn reset(self, submit_method_flag: ResetFrom); fn reset(self, submit_method_flag: ResetFrom);
} }
impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> { impl<'a> HTMLFormElementHelpers for &'a HTMLFormElement {
fn submit(self, _submit_method_flag: SubmittedFrom, submitter: FormSubmitter) { fn submit(self, _submit_method_flag: SubmittedFrom, submitter: FormSubmitter) {
// Step 1 // Step 1
let doc = document_from_node(self).root(); let doc = document_from_node(self);
let win = window_from_node(self).root(); let win = window_from_node(self);
let base = doc.r().url(); let base = doc.r().url();
// TODO: Handle browsing contexts // TODO: Handle browsing contexts
// TODO: Handle validation // TODO: Handle validation
let event = Event::new(GlobalRef::Window(win.r()), let event = Event::new(GlobalRef::Window(win.r()),
"submit".to_owned(), "submit".to_owned(),
EventBubbles::Bubbles, EventBubbles::Bubbles,
EventCancelable::Cancelable).root(); EventCancelable::Cancelable);
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self); let target = EventTargetCast::from_ref(self);
event.r().fire(target); event.r().fire(target);
if event.r().DefaultPrevented() { if event.r().DefaultPrevented() {
return; return;
@ -262,16 +268,15 @@ impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> {
buf buf
} }
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
// TODO: This is an incorrect way of getting controls owned // TODO: This is an incorrect way of getting controls owned
// by the form, but good enough until html5ever lands // by the form, but good enough until html5ever lands
let data_set = node.traverse_preorder().filter_map(|child| { let data_set = node.traverse_preorder().filter_map(|child| {
let child = child.root();
if child.r().get_disabled_state() { if child.r().get_disabled_state() {
return None; return None;
} }
if child.r().ancestors() if child.r().ancestors()
.any(|a| HTMLDataListElementCast::to_temporary(a).is_some()) { .any(|a| HTMLDataListElementCast::to_root(a).is_some()) {
return None; return None;
} }
// XXXManishearth don't include it if it is a button but not the submitter // XXXManishearth don't include it if it is a button but not the submitter
@ -365,23 +370,22 @@ impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> {
self.marked_for_reset.set(true); self.marked_for_reset.set(true);
} }
let win = window_from_node(self).root(); let win = window_from_node(self);
let event = Event::new(GlobalRef::Window(win.r()), let event = Event::new(GlobalRef::Window(win.r()),
"reset".to_owned(), "reset".to_owned(),
EventBubbles::Bubbles, EventBubbles::Bubbles,
EventCancelable::Cancelable).root(); EventCancelable::Cancelable);
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self); let target = EventTargetCast::from_ref(self);
event.r().fire(target); event.r().fire(target);
if event.r().DefaultPrevented() { if event.r().DefaultPrevented() {
return; return;
} }
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
// TODO: This is an incorrect way of getting controls owned // TODO: This is an incorrect way of getting controls owned
// by the form, but good enough until html5ever lands // by the form, but good enough until html5ever lands
for child in node.traverse_preorder() { for child in node.traverse_preorder() {
let child = child.root();
match child.r().type_id() { match child.r().type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => { NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
let input = HTMLInputElementCast::to_ref(child.r()).unwrap(); let input = HTMLInputElementCast::to_ref(child.r()).unwrap();
@ -434,9 +438,9 @@ pub enum FormMethod {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum FormSubmitter<'a> { pub enum FormSubmitter<'a> {
FormElement(JSRef<'a, HTMLFormElement>), FormElement(&'a HTMLFormElement),
InputElement(JSRef<'a, HTMLInputElement>), InputElement(&'a HTMLInputElement),
ButtonElement(JSRef<'a, HTMLButtonElement>) ButtonElement(&'a HTMLButtonElement)
// TODO: image submit, etc etc // TODO: image submit, etc etc
} }
@ -525,28 +529,27 @@ impl<'a> FormSubmitter<'a> {
pub trait FormControl<'a> : Copy + Sized { pub trait FormControl<'a> : Copy + Sized {
// FIXME: This is wrong (https://github.com/servo/servo/issues/3553) // FIXME: This is wrong (https://github.com/servo/servo/issues/3553)
// but we need html5ever to do it correctly // but we need html5ever to do it correctly
fn form_owner(self) -> Option<Temporary<HTMLFormElement>> { fn form_owner(self) -> Option<Root<HTMLFormElement>> {
// https://html.spec.whatwg.org/multipage/#reset-the-form-owner // https://html.spec.whatwg.org/multipage/#reset-the-form-owner
let elem = self.to_element(); let elem = self.to_element();
let owner = elem.get_string_attribute(&atom!("form")); let owner = elem.get_string_attribute(&atom!("form"));
if !owner.is_empty() { if !owner.is_empty() {
let doc = document_from_node(elem).root(); let doc = document_from_node(elem);
let owner = doc.r().GetElementById(owner).root(); let owner = doc.r().GetElementById(owner);
match owner { match owner {
Some(ref o) => { Some(ref o) => {
let maybe_form: Option<JSRef<HTMLFormElement>> = HTMLFormElementCast::to_ref(o.r()); let maybe_form = HTMLFormElementCast::to_ref(o.r());
if maybe_form.is_some() { if maybe_form.is_some() {
return maybe_form.map(Temporary::from_rooted); return maybe_form.map(Root::from_ref);
} }
}, },
_ => () _ => ()
} }
} }
let node: JSRef<Node> = NodeCast::from_ref(elem); let node = NodeCast::from_ref(elem);
for ancestor in node.ancestors() { for ancestor in node.ancestors() {
let ancestor = ancestor.root();
if let Some(ancestor) = HTMLFormElementCast::to_ref(ancestor.r()) { if let Some(ancestor) = HTMLFormElementCast::to_ref(ancestor.r()) {
return Some(Temporary::from_rooted(ancestor)) return Some(Root::from_ref(ancestor))
} }
} }
None None
@ -558,19 +561,19 @@ pub trait FormControl<'a> : Copy + Sized {
owner: OwnerFn) owner: OwnerFn)
-> DOMString -> DOMString
where InputFn: Fn(Self) -> DOMString, where InputFn: Fn(Self) -> DOMString,
OwnerFn: Fn(JSRef<HTMLFormElement>) -> DOMString OwnerFn: Fn(&HTMLFormElement) -> DOMString
{ {
if self.to_element().has_attribute(attr) { if self.to_element().has_attribute(attr) {
input(self) input(self)
} else { } else {
self.form_owner().map_or("".to_owned(), |t| owner(t.root().r())) self.form_owner().map_or("".to_owned(), |t| owner(t.r()))
} }
} }
fn to_element(self) -> JSRef<'a, Element>; fn to_element(self) -> &'a Element;
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLFormElement> { impl<'a> VirtualMethods for &'a HTMLFormElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
Some(HTMLElementCast::from_borrowed_ref(self) as &VirtualMethods) Some(HTMLElementCast::from_borrowed_ref(self) as &VirtualMethods)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLFrameElementBinding; use dom::bindings::codegen::Bindings::HTMLFrameElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLFrameElementDerived; use dom::bindings::codegen::InheritTypes::HTMLFrameElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLFrameElementDerived for EventTarget {
} }
impl HTMLFrameElement { impl HTMLFrameElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLFrameElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLFrameElement {
HTMLFrameElement { HTMLFrameElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLFrameElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLFrameElement, localName, prefix, document)
} }
@ -35,7 +35,7 @@ impl HTMLFrameElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLFrameElement> { document: &Document) -> Root<HTMLFrameElement> {
let element = HTMLFrameElement::new_inherited(localName, prefix, document); let element = HTMLFrameElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLFrameElementBinding::Wrap) Node::reflect_node(box element, document, HTMLFrameElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLFrameSetElementBinding; use dom::bindings::codegen::Bindings::HTMLFrameSetElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLFrameSetElementDerived; use dom::bindings::codegen::InheritTypes::HTMLFrameSetElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLFrameSetElementDerived for EventTarget {
impl HTMLFrameSetElement { impl HTMLFrameSetElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLFrameSetElement { document: &Document) -> HTMLFrameSetElement {
HTMLFrameSetElement { HTMLFrameSetElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLFrameSetElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLFrameSetElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLFrameSetElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLFrameSetElement> { document: &Document) -> Root<HTMLFrameSetElement> {
let element = HTMLFrameSetElement::new_inherited(localName, prefix, document); let element = HTMLFrameSetElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLFrameSetElementBinding::Wrap) Node::reflect_node(box element, document, HTMLFrameSetElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLHeadElementBinding; use dom::bindings::codegen::Bindings::HTMLHeadElementBinding;
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLHeadElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLHeadElementDerived};
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -30,7 +30,7 @@ impl HTMLHeadElementDerived for EventTarget {
impl HTMLHeadElement { impl HTMLHeadElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLHeadElement { document: &Document) -> HTMLHeadElement {
HTMLHeadElement { HTMLHeadElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLHeadElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLHeadElement, localName, prefix, document)
} }
@ -39,15 +39,15 @@ impl HTMLHeadElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLHeadElement> { document: &Document) -> Root<HTMLHeadElement> {
let element = HTMLHeadElement::new_inherited(localName, prefix, document); let element = HTMLHeadElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLHeadElementBinding::Wrap) Node::reflect_node(box element, document, HTMLHeadElementBinding::Wrap)
} }
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLHeadElement> { impl<'a> VirtualMethods for &'a HTMLHeadElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn bind_to_tree(&self, _tree_in_doc: bool) { fn bind_to_tree(&self, _tree_in_doc: bool) {

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLHeadingElementBinding; use dom::bindings::codegen::Bindings::HTMLHeadingElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLHeadingElementDerived; use dom::bindings::codegen::InheritTypes::HTMLHeadingElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -39,7 +39,7 @@ impl HTMLHeadingElementDerived for EventTarget {
impl HTMLHeadingElement { impl HTMLHeadingElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>, document: &Document,
level: HeadingLevel) -> HTMLHeadingElement { level: HeadingLevel) -> HTMLHeadingElement {
HTMLHeadingElement { HTMLHeadingElement {
htmlelement: htmlelement:
@ -51,8 +51,8 @@ impl HTMLHeadingElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>, document: &Document,
level: HeadingLevel) -> Temporary<HTMLHeadingElement> { level: HeadingLevel) -> Root<HTMLHeadingElement> {
let element = HTMLHeadingElement::new_inherited(localName, prefix, document, level); let element = HTMLHeadingElement::new_inherited(localName, prefix, document, level);
Node::reflect_node(box element, document, HTMLHeadingElementBinding::Wrap) Node::reflect_node(box element, document, HTMLHeadingElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLHRElementBinding; use dom::bindings::codegen::Bindings::HTMLHRElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLHRElementDerived; use dom::bindings::codegen::InheritTypes::HTMLHRElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLHRElementDerived for EventTarget {
} }
impl HTMLHRElement { impl HTMLHRElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLHRElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLHRElement {
HTMLHRElement { HTMLHRElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLHRElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLHRElement, localName, prefix, document)
} }
@ -35,7 +35,7 @@ impl HTMLHRElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLHRElement> { document: &Document) -> Root<HTMLHRElement> {
let element = HTMLHRElement::new_inherited(localName, prefix, document); let element = HTMLHRElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLHRElementBinding::Wrap) Node::reflect_node(box element, document, HTMLHRElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLHtmlElementBinding; use dom::bindings::codegen::Bindings::HTMLHtmlElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLHtmlElementDerived; use dom::bindings::codegen::InheritTypes::HTMLHtmlElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLHtmlElementDerived for EventTarget {
} }
impl HTMLHtmlElement { impl HTMLHtmlElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLHtmlElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLHtmlElement {
HTMLHtmlElement { HTMLHtmlElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLHtmlElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLHtmlElement, localName, prefix, document)
} }
@ -35,7 +35,7 @@ impl HTMLHtmlElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLHtmlElement> { document: &Document) -> Root<HTMLHtmlElement> {
let element = HTMLHtmlElement::new_inherited(localName, prefix, document); let element = HTMLHtmlElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLHtmlElementBinding::Wrap) Node::reflect_node(box element, document, HTMLHtmlElementBinding::Wrap)
} }

View file

@ -13,11 +13,11 @@ use dom::bindings::conversions::ToJSValConvertible;
use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::error::Error::NotSupported; use dom::bindings::error::Error::NotSupported;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, OptionalRootable, Rootable, Temporary}; use dom::bindings::js::{Root};
use dom::customevent::CustomEvent; use dom::customevent::CustomEvent;
use dom::document::Document; use dom::document::Document;
use dom::element::{self, AttributeHandlers, Element}; use dom::element::{self, AttributeHandlers};
use dom::event::{Event, EventHelpers}; use dom::event::EventHelpers;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@ -39,6 +39,8 @@ use std::borrow::ToOwned;
use std::cell::Cell; use std::cell::Cell;
use url::{Url, UrlParser}; use url::{Url, UrlParser};
use util::str::{self, LengthOrPercentageOrAuto}; use util::str::{self, LengthOrPercentageOrAuto};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;
enum SandboxAllowance { enum SandboxAllowance {
AllowNothing = 0x00, AllowNothing = 0x00,
@ -82,19 +84,19 @@ pub trait RawHTMLIFrameElementHelpers {
fn get_height(&self) -> LengthOrPercentageOrAuto; fn get_height(&self) -> LengthOrPercentageOrAuto;
} }
impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> { impl<'a> HTMLIFrameElementHelpers for &'a HTMLIFrameElement {
fn is_sandboxed(self) -> bool { fn is_sandboxed(self) -> bool {
self.sandbox.get().is_some() self.sandbox.get().is_some()
} }
fn get_url(self) -> Option<Url> { fn get_url(self) -> Option<Url> {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
element.get_attribute(&ns!(""), &atom!("src")).root().and_then(|src| { element.get_attribute(&ns!(""), &atom!("src")).and_then(|src| {
let url = src.r().value(); let url = src.r().value();
if url.is_empty() { if url.is_empty() {
None None
} else { } else {
let window = window_from_node(self).root(); let window = window_from_node(self);
UrlParser::new().base_url(&window.r().get_url()) UrlParser::new().base_url(&window.r().get_url())
.parse(&url).ok() .parse(&url).ok()
} }
@ -103,7 +105,7 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
fn generate_new_subpage_id(self) -> (SubpageId, Option<SubpageId>) { fn generate_new_subpage_id(self) -> (SubpageId, Option<SubpageId>) {
let old_subpage_id = self.subpage_id.get(); let old_subpage_id = self.subpage_id.get();
let win = window_from_node(self).root(); let win = window_from_node(self);
let subpage_id = win.r().get_next_subpage_id(); let subpage_id = win.r().get_next_subpage_id();
self.subpage_id.set(Some(subpage_id)); self.subpage_id.set(Some(subpage_id));
(subpage_id, old_subpage_id) (subpage_id, old_subpage_id)
@ -116,7 +118,7 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
IFrameUnsandboxed IFrameUnsandboxed
}; };
let window = window_from_node(self).root(); let window = window_from_node(self);
let window = window.r(); let window = window.r();
let (new_subpage_id, old_subpage_id) = self.generate_new_subpage_id(); let (new_subpage_id, old_subpage_id) = self.generate_new_subpage_id();
@ -151,15 +153,17 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
assert!(opts::experimental_enabled()); assert!(opts::experimental_enabled());
if self.Mozbrowser() { if self.Mozbrowser() {
let window = window_from_node(self).root(); let window = window_from_node(self);
let cx = window.r().get_cx(); let cx = window.r().get_cx();
let mut detail = RootedValue::new(cx, UndefinedValue());
event.detail().to_jsval(cx, detail.handle_mut());
let custom_event = CustomEvent::new(GlobalRef::Window(window.r()), let custom_event = CustomEvent::new(GlobalRef::Window(window.r()),
event.name().to_owned(), event.name().to_owned(),
true, true,
true, true,
event.detail().to_jsval(cx)).root(); detail.handle());
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self); let target = EventTargetCast::from_ref(self);
let event: JSRef<Event> = EventCast::from_ref(custom_event.r()); let event = EventCast::from_ref(custom_event.r());
event.fire(target); event.fire(target);
} }
} }
@ -176,7 +180,7 @@ impl RawHTMLIFrameElementHelpers for HTMLIFrameElement {
element::get_attr_for_layout(ElementCast::from_actual(&*self), element::get_attr_for_layout(ElementCast::from_actual(&*self),
&ns!(""), &ns!(""),
&atom!("width")).map(|attribute| { &atom!("width")).map(|attribute| {
str::parse_length(&**(*attribute.unsafe_get()).value()) str::parse_length(&**(*attribute.unsafe_get()).value_for_layout())
}).unwrap_or(LengthOrPercentageOrAuto::Auto) }).unwrap_or(LengthOrPercentageOrAuto::Auto)
} }
} }
@ -187,7 +191,7 @@ impl RawHTMLIFrameElementHelpers for HTMLIFrameElement {
element::get_attr_for_layout(ElementCast::from_actual(&*self), element::get_attr_for_layout(ElementCast::from_actual(&*self),
&ns!(""), &ns!(""),
&atom!("height")).map(|attribute| { &atom!("height")).map(|attribute| {
str::parse_length(&**(*attribute.unsafe_get()).value()) str::parse_length(&**(*attribute.unsafe_get()).value_for_layout())
}).unwrap_or(LengthOrPercentageOrAuto::Auto) }).unwrap_or(LengthOrPercentageOrAuto::Auto)
} }
} }
@ -196,7 +200,7 @@ impl RawHTMLIFrameElementHelpers for HTMLIFrameElement {
impl HTMLIFrameElement { impl HTMLIFrameElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLIFrameElement { document: &Document) -> HTMLIFrameElement {
HTMLIFrameElement { HTMLIFrameElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLIFrameElement, localName, prefix, document), HTMLElement::new_inherited(HTMLElementTypeId::HTMLIFrameElement, localName, prefix, document),
@ -209,7 +213,7 @@ impl HTMLIFrameElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLIFrameElement> { document: &Document) -> Root<HTMLIFrameElement> {
let element = HTMLIFrameElement::new_inherited(localName, prefix, document); let element = HTMLIFrameElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLIFrameElementBinding::Wrap) Node::reflect_node(box element, document, HTMLIFrameElementBinding::Wrap)
} }
@ -225,46 +229,46 @@ impl HTMLIFrameElement {
} }
} }
impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> { impl<'a> HTMLIFrameElementMethods for &'a HTMLIFrameElement {
fn Src(self) -> DOMString { fn Src(self) -> DOMString {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
element.get_string_attribute(&atom!("src")) element.get_string_attribute(&atom!("src"))
} }
fn SetSrc(self, src: DOMString) { fn SetSrc(self, src: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
element.set_url_attribute(&atom!("src"), src) element.set_url_attribute(&atom!("src"), src)
} }
fn Sandbox(self) -> DOMString { fn Sandbox(self) -> DOMString {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
element.get_string_attribute(&atom!("sandbox")) element.get_string_attribute(&atom!("sandbox"))
} }
fn SetSandbox(self, sandbox: DOMString) { fn SetSandbox(self, sandbox: DOMString) {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
element.set_tokenlist_attribute(&atom!("sandbox"), sandbox); element.set_tokenlist_attribute(&atom!("sandbox"), sandbox);
} }
fn GetContentWindow(self) -> Option<Temporary<Window>> { fn GetContentWindow(self) -> Option<Root<Window>> {
self.subpage_id.get().and_then(|subpage_id| { self.subpage_id.get().and_then(|subpage_id| {
let window = window_from_node(self).root(); let window = window_from_node(self);
let window = window.r(); let window = window.r();
let children = window.page().children.borrow(); let children = window.page().children.borrow();
children.iter().find(|page| { children.iter().find(|page| {
let window = page.window().root(); let window = page.window();
window.r().subpage() == Some(subpage_id) window.r().subpage() == Some(subpage_id)
}).map(|page| page.window()) }).map(|page| page.window())
}) })
} }
fn GetContentDocument(self) -> Option<Temporary<Document>> { fn GetContentDocument(self) -> Option<Root<Document>> {
self.GetContentWindow().root().and_then(|window| { self.GetContentWindow().and_then(|window| {
let self_url = match self.get_url() { let self_url = match self.get_url() {
Some(self_url) => self_url, Some(self_url) => self_url,
None => return None, None => return None,
}; };
let win_url = window_from_node(self).root().r().get_url(); let win_url = window_from_node(self).r().get_url();
if UrlHelper::SameOrigin(&self_url, &win_url) { if UrlHelper::SameOrigin(&self_url, &win_url) {
Some(window.r().Document()) Some(window.r().Document())
@ -284,7 +288,7 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-mozbrowser // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-mozbrowser
fn Mozbrowser(self) -> bool { fn Mozbrowser(self) -> bool {
if opts::experimental_enabled() { if opts::experimental_enabled() {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
element.has_attribute(&Atom::from_slice("mozbrowser")) element.has_attribute(&Atom::from_slice("mozbrowser"))
} else { } else {
false false
@ -293,7 +297,7 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
fn SetMozbrowser(self, value: bool) -> ErrorResult { fn SetMozbrowser(self, value: bool) -> ErrorResult {
if opts::experimental_enabled() { if opts::experimental_enabled() {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
element.set_bool_attribute(&Atom::from_slice("mozbrowser"), value); element.set_bool_attribute(&Atom::from_slice("mozbrowser"), value);
} }
Ok(()) Ok(())
@ -302,9 +306,9 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goBack // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goBack
fn GoBack(self) -> Fallible<()> { fn GoBack(self) -> Fallible<()> {
if self.Mozbrowser() { if self.Mozbrowser() {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
if node.is_in_doc() { if node.is_in_doc() {
let window = window_from_node(self).root(); let window = window_from_node(self);
let window = window.r(); let window = window.r();
let pipeline_info = Some((self.containing_page_pipeline_id().unwrap(), let pipeline_info = Some((self.containing_page_pipeline_id().unwrap(),
@ -324,9 +328,9 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goForward // https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goForward
fn GoForward(self) -> Fallible<()> { fn GoForward(self) -> Fallible<()> {
if self.Mozbrowser() { if self.Mozbrowser() {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
if node.is_in_doc() { if node.is_in_doc() {
let window = window_from_node(self).root(); let window = window_from_node(self);
let window = window.r(); let window = window.r();
let pipeline_info = Some((self.containing_page_pipeline_id().unwrap(), let pipeline_info = Some((self.containing_page_pipeline_id().unwrap(),
@ -362,13 +366,13 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
make_setter!(SetHeight, "height"); make_setter!(SetHeight, "height");
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> { impl<'a> VirtualMethods for &'a HTMLIFrameElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
@ -392,7 +396,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
self.sandbox.set(Some(modes)); self.sandbox.set(Some(modes));
} }
&atom!("src") => { &atom!("src") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
if node.is_in_doc() { if node.is_in_doc() {
self.process_the_iframe_attributes() self.process_the_iframe_attributes()
} }
@ -408,7 +412,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
@ -437,7 +441,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
// https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded // https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded
match (self.containing_page_pipeline_id(), self.subpage_id()) { match (self.containing_page_pipeline_id(), self.subpage_id()) {
(Some(containing_pipeline_id), Some(subpage_id)) => { (Some(containing_pipeline_id), Some(subpage_id)) => {
let window = window_from_node(*self).root(); let window = window_from_node(*self);
let window = window.r(); let window = window.r();
let ConstellationChan(ref chan) = window.constellation_chan(); let ConstellationChan(ref chan) = window.constellation_chan();

View file

@ -10,10 +10,9 @@ use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementM
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast, HTMLElementCast, use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast, HTMLElementCast,
HTMLImageElementDerived}; HTMLImageElementDerived};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, LayoutJS, Rootable, Temporary}; use dom::bindings::js::{LayoutJS, Root};
use dom::bindings::refcounted::Trusted; use dom::bindings::refcounted::Trusted;
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::element::Element;
use dom::element::AttributeHandlers; use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -51,7 +50,7 @@ pub trait HTMLImageElementHelpers {
fn get_url(&self) -> Option<Url>; fn get_url(&self) -> Option<Url>;
} }
impl<'a> HTMLImageElementHelpers for JSRef<'a, HTMLImageElement> { impl<'a> HTMLImageElementHelpers for &'a HTMLImageElement {
fn get_url(&self) -> Option<Url>{ fn get_url(&self) -> Option<Url>{
self.url.borrow().clone() self.url.borrow().clone()
} }
@ -79,7 +78,7 @@ impl Responder {
impl ImageResponder for Responder { impl ImageResponder for Responder {
fn respond(&self, image: ImageResponse) { fn respond(&self, image: ImageResponse) {
// Update the image field // Update the image field
let element = self.element.to_temporary().root(); let element = self.element.root();
let element_ref = element.r(); let element_ref = element.r();
*element_ref.image.borrow_mut() = match image { *element_ref.image.borrow_mut() = match image {
ImageResponse::Loaded(image) | ImageResponse::PlaceholderLoaded(image) => { ImageResponse::Loaded(image) | ImageResponse::PlaceholderLoaded(image) => {
@ -90,17 +89,17 @@ impl ImageResponder for Responder {
// Mark the node dirty // Mark the node dirty
let node = NodeCast::from_ref(element.r()); let node = NodeCast::from_ref(element.r());
let document = document_from_node(node).root(); let document = document_from_node(node);
document.r().content_changed(node, NodeDamage::OtherNodeDamage); document.r().content_changed(node, NodeDamage::OtherNodeDamage);
// Fire image.onload // Fire image.onload
let window = window_from_node(document.r()).root(); let window = window_from_node(document.r());
let event = Event::new(GlobalRef::Window(window.r()), let event = Event::new(GlobalRef::Window(window.r()),
"load".to_owned(), "load".to_owned(),
EventBubbles::DoesNotBubble, EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable).root(); EventCancelable::NotCancelable);
let event = event.r(); let event = event.r();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(node); let target = EventTargetCast::from_ref(node);
event.fire(target); event.fire(target);
// Trigger reflow // Trigger reflow
@ -108,13 +107,13 @@ impl ImageResponder for Responder {
} }
} }
impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> { impl<'a> PrivateHTMLImageElementHelpers for &'a HTMLImageElement {
/// Makes the local `image` member match the status of the `src` attribute and starts /// Makes the local `image` member match the status of the `src` attribute and starts
/// prefetching the image. This method must be called after `src` is changed. /// prefetching the image. This method must be called after `src` is changed.
fn update_image(self, value: Option<(DOMString, &Url)>) { fn update_image(self, value: Option<(DOMString, &Url)>) {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let document = node.owner_doc().root(); let document = node.owner_doc();
let window = document.r().window().root(); let window = document.r().window();
let window = window.r(); let window = window.r();
let image_cache = window.image_cache_task(); let image_cache = window.image_cache_task();
match value { match value {
@ -137,7 +136,7 @@ impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, HTMLImageElement> {
} }
impl HTMLImageElement { impl HTMLImageElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLImageElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLImageElement {
HTMLImageElement { HTMLImageElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLImageElement, localName, prefix, document), htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLImageElement, localName, prefix, document),
url: DOMRefCell::new(None), url: DOMRefCell::new(None),
@ -148,7 +147,7 @@ impl HTMLImageElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLImageElement> { document: &Document) -> Root<HTMLImageElement> {
let element = HTMLImageElement::new_inherited(localName, prefix, document); let element = HTMLImageElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLImageElementBinding::Wrap) Node::reflect_node(box element, document, HTMLImageElementBinding::Wrap)
} }
@ -174,7 +173,7 @@ impl LayoutHTMLImageElementHelpers for LayoutJS<HTMLImageElement> {
} }
} }
impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> { impl<'a> HTMLImageElementMethods for &'a HTMLImageElement {
make_getter!(Alt); make_getter!(Alt);
make_setter!(SetAlt, "alt"); make_setter!(SetAlt, "alt");
@ -190,29 +189,29 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
make_bool_getter!(IsMap); make_bool_getter!(IsMap);
fn SetIsMap(self, is_map: bool) { fn SetIsMap(self, is_map: bool) {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
element.set_string_attribute(&atom!("ismap"), is_map.to_string()) element.set_string_attribute(&atom!("ismap"), is_map.to_string())
} }
fn Width(self) -> u32 { fn Width(self) -> u32 {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let rect = node.get_bounding_content_box(); let rect = node.get_bounding_content_box();
rect.size.width.to_px() as u32 rect.size.width.to_px() as u32
} }
fn SetWidth(self, width: u32) { fn SetWidth(self, width: u32) {
let elem: JSRef<Element> = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
elem.set_uint_attribute(&atom!("width"), width) elem.set_uint_attribute(&atom!("width"), width)
} }
fn Height(self) -> u32 { fn Height(self) -> u32 {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let rect = node.get_bounding_content_box(); let rect = node.get_bounding_content_box();
rect.size.height.to_px() as u32 rect.size.height.to_px() as u32
} }
fn SetHeight(self, height: u32) { fn SetHeight(self, height: u32) {
let elem: JSRef<Element> = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
elem.set_uint_attribute(&atom!("height"), height) elem.set_uint_attribute(&atom!("height"), height)
} }
@ -264,20 +263,20 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
make_setter!(SetBorder, "border"); make_setter!(SetBorder, "border");
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> { impl<'a> VirtualMethods for &'a HTMLImageElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("src") => { &atom!("src") => {
let window = window_from_node(*self).root(); let window = window_from_node(*self);
let url = window.r().get_url(); let url = window.r().get_url();
self.update_image(Some(((**attr.value()).to_owned(), &url))); self.update_image(Some(((**attr.value()).to_owned(), &url)));
}, },
@ -285,7 +284,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLImageElement> {
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }

View file

@ -15,9 +15,9 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLInp
use dom::bindings::codegen::InheritTypes::{HTMLInputElementDerived, HTMLFieldSetElementDerived, EventTargetCast}; use dom::bindings::codegen::InheritTypes::{HTMLInputElementDerived, HTMLFieldSetElementDerived, EventTargetCast};
use dom::bindings::codegen::InheritTypes::KeyboardEventCast; use dom::bindings::codegen::InheritTypes::KeyboardEventCast;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, LayoutJS, MutNullableHeap}; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
use dom::bindings::js::{OptionalRootable, ResultRootable, Root, Rootable}; use dom::bindings::js::{Root};
use dom::bindings::js::{RootedReference, Temporary}; use dom::bindings::js::RootedReference;
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::element::{AttributeHandlers, Element}; use dom::element::{AttributeHandlers, Element};
use dom::element::{RawLayoutElementHelpers, ActivationElementHelpers}; use dom::element::{RawLayoutElementHelpers, ActivationElementHelpers};
@ -77,6 +77,12 @@ pub struct HTMLInputElement {
activation_state: DOMRefCell<InputActivationState>, activation_state: DOMRefCell<InputActivationState>,
} }
impl PartialEq for HTMLInputElement {
fn eq(&self, other: &HTMLInputElement) -> bool {
self as *const HTMLInputElement == &*other
}
}
#[jstraceable] #[jstraceable]
#[must_root] #[must_root]
struct InputActivationState { struct InputActivationState {
@ -114,8 +120,8 @@ impl HTMLInputElementDerived for EventTarget {
static DEFAULT_INPUT_SIZE: u32 = 20; static DEFAULT_INPUT_SIZE: u32 = 20;
impl HTMLInputElement { impl HTMLInputElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLInputElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLInputElement {
let chan = document.window().root().r().constellation_chan(); let chan = document.window().r().constellation_chan();
HTMLInputElement { HTMLInputElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLInputElement, localName, prefix, document), htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLInputElement, localName, prefix, document),
input_type: Cell::new(InputType::InputText), input_type: Cell::new(InputType::InputText),
@ -133,7 +139,7 @@ impl HTMLInputElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLInputElement> { document: &Document) -> Root<HTMLInputElement> {
let element = HTMLInputElement::new_inherited(localName, prefix, document); let element = HTMLInputElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLInputElementBinding::Wrap) Node::reflect_node(box element, document, HTMLInputElementBinding::Wrap)
} }
@ -217,7 +223,7 @@ impl RawLayoutHTMLInputElementHelpers for HTMLInputElement {
} }
} }
impl<'a> HTMLInputElementMethods for JSRef<'a, HTMLInputElement> { impl<'a> HTMLInputElementMethods for &'a HTMLInputElement {
// https://www.whatwg.org/html/#dom-fe-disabled // https://www.whatwg.org/html/#dom-fe-disabled
make_bool_getter!(Disabled); make_bool_getter!(Disabled);
@ -335,27 +341,26 @@ pub trait HTMLInputElementHelpers {
fn radio_group_updated(self, group: Option<&str>); fn radio_group_updated(self, group: Option<&str>);
fn get_radio_group_name(self) -> Option<String>; fn get_radio_group_name(self) -> Option<String>;
fn update_checked_state(self, checked: bool, dirty: bool); fn update_checked_state(self, checked: bool, dirty: bool);
fn get_size(&self) -> u32; fn get_size(self) -> u32;
fn get_indeterminate_state(self) -> bool; fn get_indeterminate_state(self) -> bool;
fn mutable(self) -> bool; fn mutable(self) -> bool;
fn reset(self); fn reset(self);
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn broadcast_radio_checked(broadcaster: JSRef<HTMLInputElement>, group: Option<&str>) { fn broadcast_radio_checked(broadcaster: &HTMLInputElement, group: Option<&str>) {
//TODO: if not in document, use root ancestor instead of document //TODO: if not in document, use root ancestor instead of document
let owner = broadcaster.form_owner().root(); let owner = broadcaster.form_owner();
let doc = document_from_node(broadcaster).root(); let doc = document_from_node(broadcaster);
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r()); let doc_node = NodeCast::from_ref(doc.r());
// This function is a workaround for lifetime constraint difficulties. // This function is a workaround for lifetime constraint difficulties.
fn do_broadcast<'a>(doc_node: JSRef<'a, Node>, broadcaster: JSRef<'a, HTMLInputElement>, fn do_broadcast(doc_node: &Node, broadcaster: &HTMLInputElement,
owner: Option<JSRef<'a, HTMLFormElement>>, group: Option<&str>) { owner: Option<&HTMLFormElement>, group: Option<&str>) {
// There is no DOM tree manipulation here, so this is safe // There is no DOM tree manipulation here, so this is safe
let iter = unsafe { let iter = unsafe {
doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap() doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_temporary) .filter_map(HTMLInputElementCast::to_root)
.map(|t| t.root())
.filter(|r| in_same_group(r.r(), owner, group) && broadcaster != r.r()) .filter(|r| in_same_group(r.r(), owner, group) && broadcaster != r.r())
}; };
for ref r in iter { for ref r in iter {
@ -368,10 +373,10 @@ fn broadcast_radio_checked(broadcaster: JSRef<HTMLInputElement>, group: Option<&
do_broadcast(doc_node, broadcaster, owner.r(), group) do_broadcast(doc_node, broadcaster, owner.r(), group)
} }
fn in_same_group<'a,'b>(other: JSRef<'a, HTMLInputElement>, fn in_same_group<'a,'b>(other: &'a HTMLInputElement,
owner: Option<JSRef<'b, HTMLFormElement>>, owner: Option<&'b HTMLFormElement>,
group: Option<&str>) -> bool { group: Option<&str>) -> bool {
let other_owner = other.form_owner().root(); let other_owner = other.form_owner();
let other_owner = other_owner.r(); let other_owner = other_owner.r();
other.input_type.get() == InputType::InputRadio && other.input_type.get() == InputType::InputRadio &&
// TODO Both a and b are in the same home subtree. // TODO Both a and b are in the same home subtree.
@ -384,10 +389,10 @@ fn in_same_group<'a,'b>(other: JSRef<'a, HTMLInputElement>,
} }
} }
impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> { impl<'a> HTMLInputElementHelpers for &'a HTMLInputElement {
fn force_relayout(self) { fn force_relayout(self) {
let doc = document_from_node(self).root(); let doc = document_from_node(self);
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
doc.r().content_changed(node, NodeDamage::OtherNodeDamage) doc.r().content_changed(node, NodeDamage::OtherNodeDamage)
} }
@ -399,9 +404,8 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> {
fn get_radio_group_name(self) -> Option<String> { fn get_radio_group_name(self) -> Option<String> {
//TODO: determine form owner //TODO: determine form owner
let elem: JSRef<Element> = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
elem.get_attribute(&ns!(""), &atom!("name")) elem.get_attribute(&ns!(""), &atom!("name"))
.root()
.map(|name| name.r().Value()) .map(|name| name.r().Value())
} }
@ -423,7 +427,7 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> {
//TODO: dispatch change event //TODO: dispatch change event
} }
fn get_size(&self) -> u32 { fn get_size(self) -> u32 {
self.size.get() self.size.get()
} }
@ -435,7 +439,7 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> {
fn mutable(self) -> bool { fn mutable(self) -> bool {
// https://html.spec.whatwg.org/multipage/#the-input-element:concept-fe-mutable // https://html.spec.whatwg.org/multipage/#the-input-element:concept-fe-mutable
// https://html.spec.whatwg.org/multipage/#the-readonly-attribute:concept-fe-mutable // https://html.spec.whatwg.org/multipage/#the-readonly-attribute:concept-fe-mutable
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
!(node.get_disabled_state() || self.ReadOnly()) !(node.get_disabled_state() || self.ReadOnly())
} }
@ -456,20 +460,20 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> {
} }
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> { impl<'a> VirtualMethods for &'a HTMLInputElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(true); node.set_disabled_state(true);
node.set_enabled_state(false); node.set_enabled_state(false);
} }
@ -525,14 +529,14 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(false); node.set_disabled_state(false);
node.set_enabled_state(true); node.set_enabled_state(true);
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
@ -584,7 +588,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
s.bind_to_tree(tree_in_doc); s.bind_to_tree(tree_in_doc);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} }
@ -593,15 +597,15 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
s.unbind_from_tree(tree_in_doc); s.unbind_from_tree(tree_in_doc);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.root().r().is_htmlfieldsetelement()) { if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) {
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} else { } else {
node.check_disabled_attribute(); node.check_disabled_attribute();
} }
} }
fn handle_event(&self, event: JSRef<Event>) { fn handle_event(&self, event: &Event) {
if let Some(s) = self.super_type() { if let Some(s) = self.super_type() {
s.handle_event(event); s.handle_event(event);
} }
@ -617,12 +621,12 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
//TODO: set the editing position for text inputs //TODO: set the editing position for text inputs
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
doc.r().request_focus(ElementCast::from_ref(*self)); doc.r().request_focus(ElementCast::from_ref(*self));
} else if &*event.Type() == "keydown" && !event.DefaultPrevented() && } else if &*event.Type() == "keydown" && !event.DefaultPrevented() &&
(self.input_type.get() == InputType::InputText || (self.input_type.get() == InputType::InputText ||
self.input_type.get() == InputType::InputPassword) { self.input_type.get() == InputType::InputPassword) {
let keyevent: Option<JSRef<KeyboardEvent>> = KeyboardEventCast::to_ref(event); let keyevent: Option<&KeyboardEvent> = KeyboardEventCast::to_ref(event);
keyevent.map(|keyevent| { keyevent.map(|keyevent| {
// This can't be inlined, as holding on to textinput.borrow_mut() // This can't be inlined, as holding on to textinput.borrow_mut()
// during self.implicit_submission will cause a panic. // during self.implicit_submission will cause a panic.
@ -646,15 +650,15 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
} }
} }
impl<'a> FormControl<'a> for JSRef<'a, HTMLInputElement> { impl<'a> FormControl<'a> for &'a HTMLInputElement {
fn to_element(self) -> JSRef<'a, Element> { fn to_element(self) -> &'a Element {
ElementCast::from_ref(self) ElementCast::from_ref(self)
} }
} }
impl<'a> Activatable for JSRef<'a, HTMLInputElement> { impl<'a> Activatable for &'a HTMLInputElement {
fn as_element(&self) -> Temporary<Element> { fn as_element<'b>(&'b self) -> &'b Element {
Temporary::from_rooted(ElementCast::from_ref(*self)) ElementCast::from_ref(*self)
} }
fn is_instance_activatable(&self) -> bool { fn is_instance_activatable(&self) -> bool {
@ -697,22 +701,21 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):pre-click-activation-steps // https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):pre-click-activation-steps
InputType::InputRadio => { InputType::InputRadio => {
//TODO: if not in document, use root ancestor instead of document //TODO: if not in document, use root ancestor instead of document
let owner = self.form_owner().root(); let owner = self.form_owner();
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r()); let doc_node = NodeCast::from_ref(doc.r());
let group = self.get_radio_group_name();; let group = self.get_radio_group_name();;
// Safe since we only manipulate the DOM tree after finding an element // Safe since we only manipulate the DOM tree after finding an element
let checked_member = unsafe { let checked_member = unsafe {
doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap() doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_temporary) .filter_map(HTMLInputElementCast::to_root)
.map(|t| t.root())
.find(|r| { .find(|r| {
in_same_group(r.r(), owner.r(), group.as_ref().map(|gr| &**gr)) && in_same_group(r.r(), owner.r(), group.as_ref().map(|gr| &**gr)) &&
r.r().Checked() r.r().Checked()
}) })
}; };
cache.checked_radio.set(checked_member.r().map(JS::from_rooted)); cache.checked_radio.set(checked_member.r().map(JS::from_ref));
cache.checked_changed = self.checked_changed.get(); cache.checked_changed = self.checked_changed.get();
self.SetChecked(true); self.SetChecked(true);
} }
@ -748,7 +751,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
InputType::InputRadio => { InputType::InputRadio => {
// We want to restore state only if the element had been changed in the first place // We want to restore state only if the element had been changed in the first place
if cache.was_mutable { if cache.was_mutable {
let old_checked: Option<Root<HTMLInputElement>> = cache.checked_radio.get().root(); let old_checked: Option<Root<HTMLInputElement>> = cache.checked_radio.get().map(|t| t.root());
let name = self.get_radio_group_name(); let name = self.get_radio_group_name();
match old_checked { match old_checked {
Some(ref o) => { Some(ref o) => {
@ -773,7 +776,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
} }
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps // https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
fn activation_behavior(&self, _event: JSRef<Event>, _target: JSRef<EventTarget>) { fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
let ty = self.input_type.get(); let ty = self.input_type.get();
if self.activation_state.borrow().old_type != ty { if self.activation_state.borrow().old_type != ty {
// Type changed, abandon ship // Type changed, abandon ship
@ -786,8 +789,8 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// FIXME (Manishearth): support document owners (needs ability to get parent browsing context) // FIXME (Manishearth): support document owners (needs ability to get parent browsing context)
if self.mutable() /* and document owner is fully active */ { if self.mutable() /* and document owner is fully active */ {
self.form_owner().map(|o| { self.form_owner().map(|o| {
o.root().r().submit(SubmittedFrom::NotFromFormSubmitMethod, o.r().submit(SubmittedFrom::NotFromFormSubmitMethod,
FormSubmitter::InputElement(self.clone())) FormSubmitter::InputElement(self.clone()))
}); });
} }
}, },
@ -796,7 +799,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// FIXME (Manishearth): support document owners (needs ability to get parent browsing context) // FIXME (Manishearth): support document owners (needs ability to get parent browsing context)
if self.mutable() /* and document owner is fully active */ { if self.mutable() /* and document owner is fully active */ {
self.form_owner().map(|o| { self.form_owner().map(|o| {
o.root().r().reset(ResetFrom::NotFromFormResetMethod) o.r().reset(ResetFrom::NotFromFormResetMethod)
}); });
} }
}, },
@ -804,19 +807,19 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox):activation-behavior // https://html.spec.whatwg.org/multipage/#checkbox-state-(type=checkbox):activation-behavior
// https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):activation-behavior // https://html.spec.whatwg.org/multipage/#radio-button-state-(type=radio):activation-behavior
if self.mutable() { if self.mutable() {
let win = window_from_node(*self).root(); let win = window_from_node(*self);
let event = Event::new(GlobalRef::Window(win.r()), let event = Event::new(GlobalRef::Window(win.r()),
"input".to_owned(), "input".to_owned(),
EventBubbles::Bubbles, EventBubbles::Bubbles,
EventCancelable::NotCancelable).root(); EventCancelable::NotCancelable);
let target: JSRef<EventTarget> = EventTargetCast::from_ref(*self); let target = EventTargetCast::from_ref(*self);
event.r().fire(target); event.r().fire(target);
let event = Event::new(GlobalRef::Window(win.r()), let event = Event::new(GlobalRef::Window(win.r()),
"change".to_owned(), "change".to_owned(),
EventBubbles::Bubbles, EventBubbles::Bubbles,
EventCancelable::NotCancelable).root(); EventCancelable::NotCancelable);
let target: JSRef<EventTarget> = EventTargetCast::from_ref(*self); let target = EventTargetCast::from_ref(*self);
event.r().fire(target); event.r().fire(target);
} }
}, },
@ -827,15 +830,15 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// https://html.spec.whatwg.org/multipage/#implicit-submission // https://html.spec.whatwg.org/multipage/#implicit-submission
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) { fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) {
let doc = document_from_node(*self).root(); let doc = document_from_node(*self);
let node: JSRef<Node> = NodeCast::from_ref(doc.r()); let node = NodeCast::from_ref(doc.r());
let owner = self.form_owner(); let owner = self.form_owner();
let form = match owner { let form = match owner {
None => return, None => return,
Some(ref f) => f.root() Some(ref f) => f
}; };
let elem: JSRef<Element> = ElementCast::from_ref(*self); let elem = ElementCast::from_ref(*self);
if elem.click_in_progress() { if elem.click_in_progress() {
return; return;
} }
@ -844,8 +847,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
let submit_button; let submit_button;
unsafe { unsafe {
submit_button = node.query_selector_iter("input[type=submit]".to_owned()).unwrap() submit_button = node.query_selector_iter("input[type=submit]".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_temporary) .filter_map(HTMLInputElementCast::to_root)
.map(|t| t.root())
.find(|r| r.r().form_owner() == owner); .find(|r| r.r().form_owner() == owner);
} }
match submit_button { match submit_button {
@ -859,9 +861,8 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// Safe because we don't perform any DOM modification // Safe because we don't perform any DOM modification
// until we're done with the iterator. // until we're done with the iterator.
let inputs = node.query_selector_iter("input".to_owned()).unwrap() let inputs = node.query_selector_iter("input".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_temporary) .filter_map(HTMLInputElementCast::to_root)
.filter(|input| { .filter(|input| {
let input = input.root();
input.r().form_owner() == owner && match &*input.r().Type() { input.r().form_owner() == owner && match &*input.r().Type() {
"text" | "search" | "url" | "tel" | "text" | "search" | "url" | "tel" |
"email" | "password" | "datetime" | "email" | "password" | "datetime" |

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding; use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLLabelElementDerived; use dom::bindings::codegen::InheritTypes::HTMLLabelElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLLabelElementDerived for EventTarget {
impl HTMLLabelElement { impl HTMLLabelElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLLabelElement { document: &Document) -> HTMLLabelElement {
HTMLLabelElement { HTMLLabelElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLLabelElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLLabelElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLLabelElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLLabelElement> { document: &Document) -> Root<HTMLLabelElement> {
let element = HTMLLabelElement::new_inherited(localName, prefix, document); let element = HTMLLabelElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLLabelElementBinding::Wrap) Node::reflect_node(box element, document, HTMLLabelElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLLegendElementBinding; use dom::bindings::codegen::Bindings::HTMLLegendElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLLegendElementDerived; use dom::bindings::codegen::InheritTypes::HTMLLegendElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLLegendElementDerived for EventTarget {
impl HTMLLegendElement { impl HTMLLegendElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLLegendElement { document: &Document) -> HTMLLegendElement {
HTMLLegendElement { HTMLLegendElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLLegendElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLLegendElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLLegendElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLLegendElement> { document: &Document) -> Root<HTMLLegendElement> {
let element = HTMLLegendElement::new_inherited(localName, prefix, document); let element = HTMLLegendElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLLegendElementBinding::Wrap) Node::reflect_node(box element, document, HTMLLegendElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLLIElementBinding; use dom::bindings::codegen::Bindings::HTMLLIElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLLIElementDerived; use dom::bindings::codegen::InheritTypes::HTMLLIElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLLIElementDerived for EventTarget {
} }
impl HTMLLIElement { impl HTMLLIElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLLIElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLLIElement {
HTMLLIElement { HTMLLIElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLLIElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLLIElement, localName, prefix, document)
} }
@ -35,7 +35,7 @@ impl HTMLLIElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLLIElement> { document: &Document) -> Root<HTMLLIElement> {
let element = HTMLLIElement::new_inherited(localName, prefix, document); let element = HTMLLIElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLLIElementBinding::Wrap) Node::reflect_node(box element, document, HTMLLIElementBinding::Wrap)
} }

View file

@ -11,8 +11,8 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLLinkElementDerived}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLLinkElementDerived};
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary}; use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::js::{OptionalRootable, RootedReference}; use dom::bindings::js::{RootedReference};
use dom::bindings::refcounted::Trusted; use dom::bindings::refcounted::Trusted;
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::domtokenlist::DOMTokenList; use dom::domtokenlist::DOMTokenList;
@ -53,7 +53,7 @@ impl HTMLLinkElementDerived for EventTarget {
} }
impl HTMLLinkElement { impl HTMLLinkElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLLinkElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLLinkElement {
HTMLLinkElement { HTMLLinkElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLLinkElement, localName, prefix, document), htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLLinkElement, localName, prefix, document),
rel_list: Default::default(), rel_list: Default::default(),
@ -63,14 +63,14 @@ impl HTMLLinkElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLLinkElement> { document: &Document) -> Root<HTMLLinkElement> {
let element = HTMLLinkElement::new_inherited(localName, prefix, document); let element = HTMLLinkElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLLinkElementBinding::Wrap) Node::reflect_node(box element, document, HTMLLinkElementBinding::Wrap)
} }
} }
fn get_attr(element: JSRef<Element>, local_name: &Atom) -> Option<String> { fn get_attr(element: &Element, local_name: &Atom) -> Option<String> {
let elem = element.get_attribute(&ns!(""), local_name).root(); let elem = element.get_attribute(&ns!(""), local_name);
elem.r().map(|e| { elem.r().map(|e| {
let value = e.value(); let value = e.value();
(**value).to_owned() (**value).to_owned()
@ -100,23 +100,23 @@ fn is_favicon(value: &Option<String>) -> bool {
} }
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> { impl<'a> VirtualMethods for &'a HTMLLinkElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
if !node.is_in_doc() { if !node.is_in_doc() {
return; return;
} }
let element: JSRef<Element> = ElementCast::from_ref(*self); let element = ElementCast::from_ref(*self);
let rel = get_attr(element, &atom!("rel")); let rel = get_attr(element, &atom!("rel"));
match (rel, attr.local_name()) { match (rel, attr.local_name()) {
@ -149,7 +149,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
} }
if tree_in_doc { if tree_in_doc {
let element: JSRef<Element> = ElementCast::from_ref(*self); let element = ElementCast::from_ref(*self);
let rel = get_attr(element, &atom!("rel")); let rel = get_attr(element, &atom!("rel"));
let href = get_attr(element, &atom!("href")); let href = get_attr(element, &atom!("href"));
@ -172,15 +172,15 @@ trait PrivateHTMLLinkElementHelpers {
fn handle_favicon_url(self, href: &str); fn handle_favicon_url(self, href: &str);
} }
impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> { impl<'a> PrivateHTMLLinkElementHelpers for &'a HTMLLinkElement {
fn handle_stylesheet_url(self, href: &str) { fn handle_stylesheet_url(self, href: &str) {
let window = window_from_node(self).root(); let window = window_from_node(self);
let window = window.r(); let window = window.r();
match UrlParser::new().base_url(&window.get_url()).parse(href) { match UrlParser::new().base_url(&window.get_url()).parse(href) {
Ok(url) => { Ok(url) => {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
let mq_attribute = element.get_attribute(&ns!(""), &atom!("media")).root(); let mq_attribute = element.get_attribute(&ns!(""), &atom!("media"));
let value = mq_attribute.r().map(|a| a.value()); let value = mq_attribute.r().map(|a| a.value());
let mq_str = match value { let mq_str = match value {
Some(ref value) => &***value, Some(ref value) => &***value,
@ -189,7 +189,7 @@ impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
let mut css_parser = CssParser::new(&mq_str); let mut css_parser = CssParser::new(&mq_str);
let media = parse_media_query_list(&mut css_parser); let media = parse_media_query_list(&mut css_parser);
let doc = window.Document().root(); let doc = window.Document();
let link_element = Trusted::new(window.get_cx(), self, window.script_chan().clone()); let link_element = Trusted::new(window.get_cx(), self, window.script_chan().clone());
let load_dispatcher = StylesheetLoadDispatcher::new(link_element); let load_dispatcher = StylesheetLoadDispatcher::new(link_element);
@ -202,7 +202,7 @@ impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
} }
fn handle_favicon_url(self, href: &str) { fn handle_favicon_url(self, href: &str) {
let window = window_from_node(self).root(); let window = window_from_node(self);
let window = window.r(); let window = window.r();
match UrlParser::new().base_url(&window.get_url()).parse(href) { match UrlParser::new().base_url(&window.get_url()).parse(href) {
Ok(url) => { Ok(url) => {
@ -215,7 +215,7 @@ impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
} }
} }
impl<'a> HTMLLinkElementMethods for JSRef<'a, HTMLLinkElement> { impl<'a> HTMLLinkElementMethods for &'a HTMLLinkElement {
make_url_getter!(Href); make_url_getter!(Href);
make_setter!(SetHref, "href"); make_setter!(SetHref, "href");
@ -231,7 +231,7 @@ impl<'a> HTMLLinkElementMethods for JSRef<'a, HTMLLinkElement> {
make_getter!(Type); make_getter!(Type);
make_setter!(SetType, "type"); make_setter!(SetType, "type");
fn RelList(self) -> Temporary<DOMTokenList> { fn RelList(self) -> Root<DOMTokenList> {
self.rel_list.or_init(|| { self.rel_list.or_init(|| {
DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel")) DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel"))
}) })
@ -252,11 +252,11 @@ impl StylesheetLoadDispatcher {
impl StylesheetLoadResponder for StylesheetLoadDispatcher { impl StylesheetLoadResponder for StylesheetLoadDispatcher {
fn respond(self: Box<StylesheetLoadDispatcher>) { fn respond(self: Box<StylesheetLoadDispatcher>) {
let elem = self.elem.to_temporary().root(); let elem = self.elem.root();
let window = window_from_node(elem.r()).root(); let window = window_from_node(elem.r());
let event = Event::new(GlobalRef::Window(window.r()), "load".to_owned(), let event = Event::new(GlobalRef::Window(window.r()), "load".to_owned(),
EventBubbles::DoesNotBubble, EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable).root(); EventCancelable::NotCancelable);
let target = EventTargetCast::from_ref(elem.r()); let target = EventTargetCast::from_ref(elem.r());
event.r().fire(target); event.r().fire(target);
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLMapElementBinding; use dom::bindings::codegen::Bindings::HTMLMapElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLMapElementDerived; use dom::bindings::codegen::InheritTypes::HTMLMapElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLMapElementDerived for EventTarget {
impl HTMLMapElement { impl HTMLMapElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLMapElement { document: &Document) -> HTMLMapElement {
HTMLMapElement { HTMLMapElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLMapElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLMapElement, localName, prefix, document)
} }
@ -37,7 +37,7 @@ impl HTMLMapElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLMapElement> { document: &Document) -> Root<HTMLMapElement> {
let element = HTMLMapElement::new_inherited(localName, prefix, document); let element = HTMLMapElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLMapElementBinding::Wrap) Node::reflect_node(box element, document, HTMLMapElementBinding::Wrap)
} }

View file

@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::js::{JSRef};
use dom::bindings::codegen::InheritTypes::HTMLMediaElementDerived; use dom::bindings::codegen::InheritTypes::HTMLMediaElementDerived;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -28,7 +27,7 @@ impl HTMLMediaElementDerived for EventTarget {
impl HTMLMediaElement { impl HTMLMediaElement {
pub fn new_inherited(type_id: HTMLMediaElementTypeId, tag_name: DOMString, pub fn new_inherited(type_id: HTMLMediaElementTypeId, tag_name: DOMString,
prefix: Option<DOMString>, document: JSRef<Document>) prefix: Option<DOMString>, document: &Document)
-> HTMLMediaElement { -> HTMLMediaElement {
HTMLMediaElement { HTMLMediaElement {
htmlelement: htmlelement:

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::HTMLMetaElementBinding; use dom::bindings::codegen::Bindings::HTMLMetaElementBinding;
use dom::bindings::codegen::Bindings::HTMLMetaElementBinding::HTMLMetaElementMethods; use dom::bindings::codegen::Bindings::HTMLMetaElementBinding::HTMLMetaElementMethods;
use dom::bindings::codegen::InheritTypes::HTMLMetaElementDerived; use dom::bindings::codegen::InheritTypes::HTMLMetaElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -29,7 +29,7 @@ impl HTMLMetaElementDerived for EventTarget {
impl HTMLMetaElement { impl HTMLMetaElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLMetaElement { document: &Document) -> HTMLMetaElement {
HTMLMetaElement { HTMLMetaElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLMetaElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLMetaElement, localName, prefix, document)
} }
@ -38,13 +38,13 @@ impl HTMLMetaElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLMetaElement> { document: &Document) -> Root<HTMLMetaElement> {
let element = HTMLMetaElement::new_inherited(localName, prefix, document); let element = HTMLMetaElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLMetaElementBinding::Wrap) Node::reflect_node(box element, document, HTMLMetaElementBinding::Wrap)
} }
} }
impl<'a> HTMLMetaElementMethods for JSRef<'a, HTMLMetaElement> { impl<'a> HTMLMetaElementMethods for &'a HTMLMetaElement {
// https://html.spec.whatwg.org/multipage/#dom-meta-name // https://html.spec.whatwg.org/multipage/#dom-meta-name
make_getter!(Name, "name"); make_getter!(Name, "name");

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLMeterElementBinding; use dom::bindings::codegen::Bindings::HTMLMeterElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLMeterElementDerived; use dom::bindings::codegen::InheritTypes::HTMLMeterElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLMeterElementDerived for EventTarget {
impl HTMLMeterElement { impl HTMLMeterElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLMeterElement { document: &Document) -> HTMLMeterElement {
HTMLMeterElement { HTMLMeterElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLMeterElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLMeterElement, localName, prefix, document)
} }
@ -37,7 +37,7 @@ impl HTMLMeterElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLMeterElement> { document: &Document) -> Root<HTMLMeterElement> {
let element = HTMLMeterElement::new_inherited(localName, prefix, document); let element = HTMLMeterElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLMeterElementBinding::Wrap) Node::reflect_node(box element, document, HTMLMeterElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLModElementBinding; use dom::bindings::codegen::Bindings::HTMLModElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLModElementDerived; use dom::bindings::codegen::InheritTypes::HTMLModElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLModElementDerived for EventTarget {
impl HTMLModElement { impl HTMLModElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLModElement { document: &Document) -> HTMLModElement {
HTMLModElement { HTMLModElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLModElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLModElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLModElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLModElement> { document: &Document) -> Root<HTMLModElement> {
let element = HTMLModElement::new_inherited(localName, prefix, document); let element = HTMLModElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLModElementBinding::Wrap) Node::reflect_node(box element, document, HTMLModElementBinding::Wrap)
} }

View file

@ -10,9 +10,8 @@ use dom::bindings::codegen::Bindings::HTMLObjectElementBinding;
use dom::bindings::codegen::Bindings::HTMLObjectElementBinding::HTMLObjectElementMethods; use dom::bindings::codegen::Bindings::HTMLObjectElementBinding::HTMLObjectElementMethods;
use dom::bindings::codegen::InheritTypes::HTMLObjectElementDerived; use dom::bindings::codegen::InheritTypes::HTMLObjectElementDerived;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::js::{JSRef, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::Element;
use dom::element::AttributeHandlers; use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -42,7 +41,7 @@ impl HTMLObjectElementDerived for EventTarget {
impl HTMLObjectElement { impl HTMLObjectElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLObjectElement { document: &Document) -> HTMLObjectElement {
HTMLObjectElement { HTMLObjectElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLObjectElement, localName, prefix, document), HTMLElement::new_inherited(HTMLElementTypeId::HTMLObjectElement, localName, prefix, document),
@ -53,7 +52,7 @@ impl HTMLObjectElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLObjectElement> { document: &Document) -> Root<HTMLObjectElement> {
let element = HTMLObjectElement::new_inherited(localName, prefix, document); let element = HTMLObjectElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLObjectElementBinding::Wrap) Node::reflect_node(box element, document, HTMLObjectElementBinding::Wrap)
} }
@ -63,15 +62,15 @@ trait ProcessDataURL {
fn process_data_url(&self); fn process_data_url(&self);
} }
impl<'a> ProcessDataURL for JSRef<'a, HTMLObjectElement> { impl<'a> ProcessDataURL for &'a HTMLObjectElement {
// Makes the local `data` member match the status of the `data` attribute and starts // Makes the local `data` member match the status of the `data` attribute and starts
/// prefetching the image. This method must be called after `data` is changed. /// prefetching the image. This method must be called after `data` is changed.
fn process_data_url(&self) { fn process_data_url(&self) {
let elem: JSRef<Element> = ElementCast::from_ref(*self); let elem = ElementCast::from_ref(*self);
// TODO: support other values // TODO: support other values
match (elem.get_attribute(&ns!(""), &atom!("type")).map(|x| x.root().r().Value()), match (elem.get_attribute(&ns!(""), &atom!("type")).map(|x| x.r().Value()),
elem.get_attribute(&ns!(""), &atom!("data")).map(|x| x.root().r().Value())) { elem.get_attribute(&ns!(""), &atom!("data")).map(|x| x.r().Value())) {
(None, Some(_uri)) => { (None, Some(_uri)) => {
// TODO(gw): Prefetch the image here. // TODO(gw): Prefetch the image here.
} }
@ -85,9 +84,9 @@ pub fn is_image_data(uri: &str) -> bool {
TYPES.iter().any(|&type_| uri.starts_with(type_)) TYPES.iter().any(|&type_| uri.starts_with(type_))
} }
impl<'a> HTMLObjectElementMethods for JSRef<'a, HTMLObjectElement> { impl<'a> HTMLObjectElementMethods for &'a HTMLObjectElement {
fn Validity(self) -> Temporary<ValidityState> { fn Validity(self) -> Root<ValidityState> {
let window = window_from_node(self).root(); let window = window_from_node(self);
ValidityState::new(window.r()) ValidityState::new(window.r())
} }
@ -98,13 +97,13 @@ impl<'a> HTMLObjectElementMethods for JSRef<'a, HTMLObjectElement> {
make_setter!(SetType, "type"); make_setter!(SetType, "type");
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLObjectElement> { impl<'a> VirtualMethods for &'a HTMLObjectElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLOListElementBinding; use dom::bindings::codegen::Bindings::HTMLOListElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLOListElementDerived; use dom::bindings::codegen::InheritTypes::HTMLOListElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLOListElementDerived for EventTarget {
impl HTMLOListElement { impl HTMLOListElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLOListElement { document: &Document) -> HTMLOListElement {
HTMLOListElement { HTMLOListElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLOListElement, localName, prefix, document) htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLOListElement, localName, prefix, document)
} }
@ -37,7 +37,7 @@ impl HTMLOListElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLOListElement> { document: &Document) -> Root<HTMLOListElement> {
let element = HTMLOListElement::new_inherited(localName, prefix, document); let element = HTMLOListElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLOListElementBinding::Wrap) Node::reflect_node(box element, document, HTMLOListElementBinding::Wrap)
} }

View file

@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding;
use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding::HTMLOptGroupElementMethods; use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding::HTMLOptGroupElementMethods;
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLOptGroupElementDerived, HTMLOptionElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLOptGroupElementDerived, HTMLOptionElementDerived};
use dom::bindings::js::{JSRef, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::AttributeHandlers; use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -35,7 +35,7 @@ impl HTMLOptGroupElementDerived for EventTarget {
impl HTMLOptGroupElement { impl HTMLOptGroupElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLOptGroupElement { document: &Document) -> HTMLOptGroupElement {
HTMLOptGroupElement { HTMLOptGroupElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLOptGroupElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLOptGroupElement, localName, prefix, document)
@ -45,13 +45,13 @@ impl HTMLOptGroupElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLOptGroupElement> { document: &Document) -> Root<HTMLOptGroupElement> {
let element = HTMLOptGroupElement::new_inherited(localName, prefix, document); let element = HTMLOptGroupElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLOptGroupElementBinding::Wrap) Node::reflect_node(box element, document, HTMLOptGroupElementBinding::Wrap)
} }
} }
impl<'a> HTMLOptGroupElementMethods for JSRef<'a, HTMLOptGroupElement> { impl<'a> HTMLOptGroupElementMethods for &'a HTMLOptGroupElement {
// https://www.whatwg.org/html#dom-optgroup-disabled // https://www.whatwg.org/html#dom-optgroup-disabled
make_bool_getter!(Disabled); make_bool_getter!(Disabled);
@ -59,24 +59,23 @@ impl<'a> HTMLOptGroupElementMethods for JSRef<'a, HTMLOptGroupElement> {
make_bool_setter!(SetDisabled, "disabled"); make_bool_setter!(SetDisabled, "disabled");
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLOptGroupElement> { impl<'a> VirtualMethods for &'a HTMLOptGroupElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(true); node.set_disabled_state(true);
node.set_enabled_state(false); node.set_enabled_state(false);
for child in node.children() { for child in node.children() {
let child = child.root();
if child.r().is_htmloptionelement() { if child.r().is_htmloptionelement() {
child.r().set_disabled_state(true); child.r().set_disabled_state(true);
child.r().set_enabled_state(false); child.r().set_enabled_state(false);
@ -87,18 +86,17 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLOptGroupElement> {
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(false); node.set_disabled_state(false);
node.set_enabled_state(true); node.set_enabled_state(true);
for child in node.children() { for child in node.children() {
let child = child.root();
if child.r().is_htmloptionelement() { if child.r().is_htmloptionelement() {
child.r().check_disabled_attribute(); child.r().check_disabled_attribute();
} }

View file

@ -7,14 +7,13 @@ use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding; use dom::bindings::codegen::Bindings::HTMLOptionElementBinding;
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods; use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods;
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, ElementCast, HTMLElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{CharacterDataCast, ElementCast, HTMLElementCast, NodeCast, TextDerived};
use dom::bindings::codegen::InheritTypes::{HTMLOptionElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLOptionElementDerived};
use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived};
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::js::{JSRef, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::characterdata::CharacterData;
use dom::document::Document; use dom::document::Document;
use dom::element::{AttributeHandlers, Element, ElementHelpers}; use dom::element::{AttributeHandlers, ElementHelpers};
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@ -39,7 +38,7 @@ impl HTMLOptionElementDerived for EventTarget {
impl HTMLOptionElement { impl HTMLOptionElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLOptionElement { document: &Document) -> HTMLOptionElement {
HTMLOptionElement { HTMLOptionElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLOptionElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLOptionElement, localName, prefix, document)
@ -49,23 +48,22 @@ impl HTMLOptionElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLOptionElement> { document: &Document) -> Root<HTMLOptionElement> {
let element = HTMLOptionElement::new_inherited(localName, prefix, document); let element = HTMLOptionElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLOptionElementBinding::Wrap) Node::reflect_node(box element, document, HTMLOptionElementBinding::Wrap)
} }
} }
fn collect_text(node: &JSRef<Node>, value: &mut DOMString) { fn collect_text(node: &&Node, value: &mut DOMString) {
let elem: JSRef<Element> = ElementCast::to_ref(*node).unwrap(); let elem = ElementCast::to_ref(*node).unwrap();
let svg_script = *elem.namespace() == ns!(SVG) && elem.local_name() == &atom!("script"); let svg_script = *elem.namespace() == ns!(SVG) && elem.local_name() == &atom!("script");
let html_script = node.is_htmlscriptelement(); let html_script = node.is_htmlscriptelement();
if svg_script || html_script { if svg_script || html_script {
return; return;
} else { } else {
for child in node.children() { for child in node.children() {
let child = child.root();
if child.r().is_text() { if child.r().is_text() {
let characterdata: JSRef<CharacterData> = CharacterDataCast::to_ref(child.r()).unwrap(); let characterdata = CharacterDataCast::to_ref(child.r()).unwrap();
value.push_str(&characterdata.Data()); value.push_str(&characterdata.Data());
} else { } else {
collect_text(&child.r(), value); collect_text(&child.r(), value);
@ -74,19 +72,19 @@ fn collect_text(node: &JSRef<Node>, value: &mut DOMString) {
} }
} }
impl<'a> HTMLOptionElementMethods for JSRef<'a, HTMLOptionElement> { impl<'a> HTMLOptionElementMethods for &'a HTMLOptionElement {
// https://www.whatwg.org/html/#dom-option-disabled // https://www.whatwg.org/html/#dom-option-disabled
make_bool_getter!(Disabled); make_bool_getter!(Disabled);
// https://www.whatwg.org/html/#dom-option-disabled // https://www.whatwg.org/html/#dom-option-disabled
fn SetDisabled(self, disabled: bool) { fn SetDisabled(self, disabled: bool) {
let elem: JSRef<Element> = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
elem.set_bool_attribute(&atom!("disabled"), disabled) elem.set_bool_attribute(&atom!("disabled"), disabled)
} }
// https://www.whatwg.org/html/#dom-option-text // https://www.whatwg.org/html/#dom-option-text
fn Text(self) -> DOMString { fn Text(self) -> DOMString {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let mut content = String::new(); let mut content = String::new();
collect_text(&node, &mut content); collect_text(&node, &mut content);
let v: Vec<&str> = split_html_space_chars(&content).collect(); let v: Vec<&str> = split_html_space_chars(&content).collect();
@ -95,13 +93,13 @@ impl<'a> HTMLOptionElementMethods for JSRef<'a, HTMLOptionElement> {
// https://www.whatwg.org/html/#dom-option-text // https://www.whatwg.org/html/#dom-option-text
fn SetText(self, value: DOMString) { fn SetText(self, value: DOMString) {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.SetTextContent(Some(value)) node.SetTextContent(Some(value))
} }
// https://html.spec.whatwg.org/multipage/#attr-option-value // https://html.spec.whatwg.org/multipage/#attr-option-value
fn Value(self) -> DOMString { fn Value(self) -> DOMString {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
let attr = &atom!("value"); let attr = &atom!("value");
if element.has_attribute(attr) { if element.has_attribute(attr) {
element.get_string_attribute(attr) element.get_string_attribute(attr)
@ -115,7 +113,7 @@ impl<'a> HTMLOptionElementMethods for JSRef<'a, HTMLOptionElement> {
// https://html.spec.whatwg.org/multipage/#attr-option-label // https://html.spec.whatwg.org/multipage/#attr-option-label
fn Label(self) -> DOMString { fn Label(self) -> DOMString {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
let attr = &atom!("label"); let attr = &atom!("label");
if element.has_attribute(attr) { if element.has_attribute(attr) {
element.get_string_attribute(attr) element.get_string_attribute(attr)
@ -129,20 +127,20 @@ impl<'a> HTMLOptionElementMethods for JSRef<'a, HTMLOptionElement> {
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLOptionElement> { impl<'a> VirtualMethods for &'a HTMLOptionElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(true); node.set_disabled_state(true);
node.set_enabled_state(false); node.set_enabled_state(false);
}, },
@ -150,14 +148,14 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLOptionElement> {
} }
} }
fn before_remove_attr(&self, attr: JSRef<Attr>) { fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.set_disabled_state(false); node.set_disabled_state(false);
node.set_enabled_state(true); node.set_enabled_state(true);
node.check_parent_disabled_state_for_option(); node.check_parent_disabled_state_for_option();
@ -171,7 +169,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLOptionElement> {
s.bind_to_tree(tree_in_doc); s.bind_to_tree(tree_in_doc);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
node.check_parent_disabled_state_for_option(); node.check_parent_disabled_state_for_option();
} }
@ -180,7 +178,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLOptionElement> {
s.unbind_from_tree(tree_in_doc); s.unbind_from_tree(tree_in_doc);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
if node.GetParentNode().is_some() { if node.GetParentNode().is_some() {
node.check_parent_disabled_state_for_option(); node.check_parent_disabled_state_for_option();
} else { } else {

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding; use dom::bindings::codegen::Bindings::HTMLOutputElementBinding;
use dom::bindings::codegen::Bindings::HTMLOutputElementBinding::HTMLOutputElementMethods; use dom::bindings::codegen::Bindings::HTMLOutputElementBinding::HTMLOutputElementMethods;
use dom::bindings::codegen::InheritTypes::HTMLOutputElementDerived; use dom::bindings::codegen::InheritTypes::HTMLOutputElementDerived;
use dom::bindings::js::{JSRef, Rootable, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -30,7 +30,7 @@ impl HTMLOutputElementDerived for EventTarget {
impl HTMLOutputElement { impl HTMLOutputElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLOutputElement { document: &Document) -> HTMLOutputElement {
HTMLOutputElement { HTMLOutputElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLOutputElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLOutputElement, localName, prefix, document)
@ -40,15 +40,15 @@ impl HTMLOutputElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLOutputElement> { document: &Document) -> Root<HTMLOutputElement> {
let element = HTMLOutputElement::new_inherited(localName, prefix, document); let element = HTMLOutputElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLOutputElementBinding::Wrap) Node::reflect_node(box element, document, HTMLOutputElementBinding::Wrap)
} }
} }
impl<'a> HTMLOutputElementMethods for JSRef<'a, HTMLOutputElement> { impl<'a> HTMLOutputElementMethods for &'a HTMLOutputElement {
fn Validity(self) -> Temporary<ValidityState> { fn Validity(self) -> Root<ValidityState> {
let window = window_from_node(self).root(); let window = window_from_node(self);
ValidityState::new(window.r()) ValidityState::new(window.r())
} }
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLParagraphElementBinding; use dom::bindings::codegen::Bindings::HTMLParagraphElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLParagraphElementDerived; use dom::bindings::codegen::InheritTypes::HTMLParagraphElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLParagraphElementDerived for EventTarget {
impl HTMLParagraphElement { impl HTMLParagraphElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLParagraphElement { document: &Document) -> HTMLParagraphElement {
HTMLParagraphElement { HTMLParagraphElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLParagraphElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLParagraphElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLParagraphElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLParagraphElement> { document: &Document) -> Root<HTMLParagraphElement> {
let element = HTMLParagraphElement::new_inherited(localName, prefix, document); let element = HTMLParagraphElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLParagraphElementBinding::Wrap) Node::reflect_node(box element, document, HTMLParagraphElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLParamElementBinding; use dom::bindings::codegen::Bindings::HTMLParamElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLParamElementDerived; use dom::bindings::codegen::InheritTypes::HTMLParamElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLParamElementDerived for EventTarget {
impl HTMLParamElement { impl HTMLParamElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLParamElement { document: &Document) -> HTMLParamElement {
HTMLParamElement { HTMLParamElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLParamElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLParamElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLParamElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLParamElement> { document: &Document) -> Root<HTMLParamElement> {
let element = HTMLParamElement::new_inherited(localName, prefix, document); let element = HTMLParamElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLParamElementBinding::Wrap) Node::reflect_node(box element, document, HTMLParamElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLPreElementBinding; use dom::bindings::codegen::Bindings::HTMLPreElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLPreElementDerived; use dom::bindings::codegen::InheritTypes::HTMLPreElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLPreElementDerived for EventTarget {
impl HTMLPreElement { impl HTMLPreElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLPreElement { document: &Document) -> HTMLPreElement {
HTMLPreElement { HTMLPreElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLPreElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLPreElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLPreElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLPreElement> { document: &Document) -> Root<HTMLPreElement> {
let element = HTMLPreElement::new_inherited(localName, prefix, document); let element = HTMLPreElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLPreElementBinding::Wrap) Node::reflect_node(box element, document, HTMLPreElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLProgressElementBinding; use dom::bindings::codegen::Bindings::HTMLProgressElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLProgressElementDerived; use dom::bindings::codegen::InheritTypes::HTMLProgressElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLProgressElementDerived for EventTarget {
impl HTMLProgressElement { impl HTMLProgressElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLProgressElement { document: &Document) -> HTMLProgressElement {
HTMLProgressElement { HTMLProgressElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLProgressElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLProgressElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLProgressElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLProgressElement> { document: &Document) -> Root<HTMLProgressElement> {
let element = HTMLProgressElement::new_inherited(localName, prefix, document); let element = HTMLProgressElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLProgressElementBinding::Wrap) Node::reflect_node(box element, document, HTMLProgressElementBinding::Wrap)
} }

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLQuoteElementBinding; use dom::bindings::codegen::Bindings::HTMLQuoteElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLQuoteElementDerived; use dom::bindings::codegen::InheritTypes::HTMLQuoteElementDerived;
use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLQuoteElementDerived for EventTarget {
impl HTMLQuoteElement { impl HTMLQuoteElement {
fn new_inherited(localName: DOMString, fn new_inherited(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLQuoteElement { document: &Document) -> HTMLQuoteElement {
HTMLQuoteElement { HTMLQuoteElement {
htmlelement: htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLQuoteElement, localName, prefix, document) HTMLElement::new_inherited(HTMLElementTypeId::HTMLQuoteElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLQuoteElement {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, pub fn new(localName: DOMString,
prefix: Option<DOMString>, prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLQuoteElement> { document: &Document) -> Root<HTMLQuoteElement> {
let element = HTMLQuoteElement::new_inherited(localName, prefix, document); let element = HTMLQuoteElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLQuoteElementBinding::Wrap) Node::reflect_node(box element, document, HTMLQuoteElementBinding::Wrap)
} }

View file

@ -17,12 +17,12 @@ use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived, HTMLScriptE
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::EventTargetCast; use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Rootable}; use dom::bindings::js::{JS, Root};
use dom::bindings::js::RootedReference; use dom::bindings::js::RootedReference;
use dom::bindings::refcounted::Trusted; use dom::bindings::refcounted::Trusted;
use dom::bindings::trace::JSTraceable; use dom::bindings::trace::JSTraceable;
use dom::document::{Document, DocumentHelpers}; use dom::document::{Document, DocumentHelpers};
use dom::element::{Element, AttributeHandlers, ElementCreator}; use dom::element::{AttributeHandlers, ElementCreator};
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers}; use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
@ -33,6 +33,8 @@ use dom::virtualmethods::VirtualMethods;
use dom::window::{WindowHelpers, ScriptHelpers}; use dom::window::{WindowHelpers, ScriptHelpers};
use network_listener::{NetworkListener, PreInvoke}; use network_listener::{NetworkListener, PreInvoke};
use script_task::{ScriptChan, ScriptMsg, Runnable}; use script_task::{ScriptChan, ScriptMsg, Runnable};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;
use encoding::all::UTF_8; use encoding::all::UTF_8;
use encoding::label::encoding_from_whatwg_label; use encoding::label::encoding_from_whatwg_label;
@ -82,7 +84,7 @@ impl HTMLScriptElementDerived for EventTarget {
} }
impl HTMLScriptElement { impl HTMLScriptElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>, fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document,
creator: ElementCreator) -> HTMLScriptElement { creator: ElementCreator) -> HTMLScriptElement {
HTMLScriptElement { HTMLScriptElement {
htmlelement: htmlelement:
@ -91,14 +93,14 @@ impl HTMLScriptElement {
parser_inserted: Cell::new(creator == ElementCreator::ParserCreated), parser_inserted: Cell::new(creator == ElementCreator::ParserCreated),
non_blocking: Cell::new(creator != ElementCreator::ParserCreated), non_blocking: Cell::new(creator != ElementCreator::ParserCreated),
ready_to_be_parser_executed: Cell::new(false), ready_to_be_parser_executed: Cell::new(false),
parser_document: JS::from_rooted(document), parser_document: JS::from_ref(document),
block_character_encoding: DOMRefCell::new(UTF_8 as EncodingRef), block_character_encoding: DOMRefCell::new(UTF_8 as EncodingRef),
} }
} }
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>, pub fn new(localName: DOMString, prefix: Option<DOMString>, document: &Document,
creator: ElementCreator) -> Temporary<HTMLScriptElement> { creator: ElementCreator) -> Root<HTMLScriptElement> {
let element = HTMLScriptElement::new_inherited(localName, prefix, document, creator); let element = HTMLScriptElement::new_inherited(localName, prefix, document, creator);
Node::reflect_node(box element, document, HTMLScriptElementBinding::Wrap) Node::reflect_node(box element, document, HTMLScriptElementBinding::Wrap)
} }
@ -190,22 +192,22 @@ impl AsyncResponseListener for ScriptContext {
let metadata = self.metadata.borrow_mut().take().unwrap(); let metadata = self.metadata.borrow_mut().take().unwrap();
(metadata, data) (metadata, data)
}); });
let elem = self.elem.to_temporary().root(); let elem = self.elem.root();
elem.r().execute(ScriptOrigin::External(load)); elem.r().execute(ScriptOrigin::External(load));
let document = document_from_node(elem.r()).root(); let document = document_from_node(elem.r());
document.r().finish_load(LoadType::Script(self.url.clone())); document.r().finish_load(LoadType::Script(self.url.clone()));
if self.resume_on_completion { if self.resume_on_completion {
document.r().get_current_parser().unwrap().root().r().resume(); document.r().get_current_parser().unwrap().r().resume();
} }
} }
} }
impl PreInvoke for ScriptContext {} impl PreInvoke for ScriptContext {}
impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> { impl<'a> HTMLScriptElementHelpers for &'a HTMLScriptElement {
fn prepare(self) -> NextParserState { fn prepare(self) -> NextParserState {
// https://html.spec.whatwg.org/multipage/#prepare-a-script // https://html.spec.whatwg.org/multipage/#prepare-a-script
// Step 1. // Step 1.
@ -217,7 +219,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
self.parser_inserted.set(false); self.parser_inserted.set(false);
// Step 3. // Step 3.
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
if was_parser_inserted && element.has_attribute(&atom!("async")) { if was_parser_inserted && element.has_attribute(&atom!("async")) {
self.non_blocking.set(true); self.non_blocking.set(true);
} }
@ -227,7 +229,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
return NextParserState::Continue; return NextParserState::Continue;
} }
// Step 5. // Step 5.
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
if !node.is_in_doc() { if !node.is_in_doc() {
return NextParserState::Continue; return NextParserState::Continue;
} }
@ -244,7 +246,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
self.already_started.set(true); self.already_started.set(true);
// Step 10. // Step 10.
let document_from_node_ref = document_from_node(self).root(); let document_from_node_ref = document_from_node(self);
let document_from_node_ref = document_from_node_ref.r(); let document_from_node_ref = document_from_node_ref.r();
if self.parser_inserted.get() && self.parser_document.root().r() != document_from_node_ref { if self.parser_inserted.get() && self.parser_document.root().r() != document_from_node_ref {
return NextParserState::Continue; return NextParserState::Continue;
@ -256,8 +258,8 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
} }
// Step 12. // Step 12.
let for_attribute = element.get_attribute(&ns!(""), &atom!("for")).root(); let for_attribute = element.get_attribute(&ns!(""), &atom!("for"));
let event_attribute = element.get_attribute(&ns!(""), &Atom::from_slice("event")).root(); let event_attribute = element.get_attribute(&ns!(""), &Atom::from_slice("event"));
match (for_attribute.r(), event_attribute.r()) { match (for_attribute.r(), event_attribute.r()) {
(Some(for_attribute), Some(event_attribute)) => { (Some(for_attribute), Some(event_attribute)) => {
let for_value = for_attribute.Value() let for_value = for_attribute.Value()
@ -277,18 +279,18 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
} }
// Step 13. // Step 13.
if let Some(ref charset) = element.get_attribute(&ns!(""), &Atom::from_slice("charset")).root() { if let Some(ref charset) = element.get_attribute(&ns!(""), &Atom::from_slice("charset")) {
if let Some(encodingRef) = encoding_from_whatwg_label(&charset.r().Value()) { if let Some(encodingRef) = encoding_from_whatwg_label(&charset.r().Value()) {
*self.block_character_encoding.borrow_mut() = encodingRef; *self.block_character_encoding.borrow_mut() = encodingRef;
} }
} }
// Step 14. // Step 14.
let window = window_from_node(self).root(); let window = window_from_node(self);
let window = window.r(); let window = window.r();
let base_url = window.get_url(); let base_url = window.get_url();
let load = match element.get_attribute(&ns!(""), &atom!("src")).root() { let load = match element.get_attribute(&ns!(""), &atom!("src")) {
// Step 14. // Step 14.
Some(ref src) => { Some(ref src) => {
// Step 14.1 // Step 14.1
@ -314,7 +316,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
// state of the element's `crossorigin` content attribute, the origin being // state of the element's `crossorigin` content attribute, the origin being
// the origin of the script element's node document, and the default origin // the origin of the script element's node document, and the default origin
// behaviour set to taint. // behaviour set to taint.
let doc = document_from_node(self).root(); let doc = document_from_node(self);
let script_chan = window.script_chan(); let script_chan = window.script_chan();
let elem = Trusted::new(window.get_cx(), self, script_chan.clone()); let elem = Trusted::new(window.get_cx(), self, script_chan.clone());
@ -335,7 +337,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
doc.r().load_async(LoadType::Script(url), listener); doc.r().load_async(LoadType::Script(url), listener);
if self.parser_inserted.get() { if self.parser_inserted.get() {
doc.r().get_current_parser().unwrap().root().r().suspend(); doc.r().get_current_parser().unwrap().r().suspend();
} }
return NextParserState::Suspend; return NextParserState::Suspend;
} }
@ -409,18 +411,20 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
// document. Let neutralised doc be that Document. // document. Let neutralised doc be that Document.
// Step 2.b.4. // Step 2.b.4.
let document = document_from_node(self).root(); let document = document_from_node(self);
let document = document.r(); let document = document.r();
let old_script = document.GetCurrentScript().root(); let old_script = document.GetCurrentScript();
// Step 2.b.5. // Step 2.b.5.
document.set_current_script(Some(self)); document.set_current_script(Some(self));
// Step 2.b.6. // Step 2.b.6.
// TODO: Create a script... // TODO: Create a script...
let window = window_from_node(self).root(); let window = window_from_node(self);
let mut rval = RootedValue::new(window.r().get_cx(), UndefinedValue());
window.r().evaluate_script_on_global_with_result(&*source, window.r().evaluate_script_on_global_with_result(&*source,
&*url.serialize()); &*url.serialize(),
rval.handle_mut());
// Step 2.b.7. // Step 2.b.7.
document.set_current_script(old_script.r()); document.set_current_script(old_script.r());
@ -447,7 +451,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
} }
fn queue_error_event(self) { fn queue_error_event(self) {
let window = window_from_node(self).root(); let window = window_from_node(self);
let window = window.r(); let window = window.r();
let chan = window.script_chan(); let chan = window.script_chan();
let handler = Trusted::new(window.get_cx(), self, chan.clone()); let handler = Trusted::new(window.get_cx(), self, chan.clone());
@ -483,8 +487,8 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
} }
fn is_javascript(self) -> bool { fn is_javascript(self) -> bool {
let element: JSRef<Element> = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
match element.get_attribute(&ns!(""), &atom!("type")).root().map(|s| s.r().Value()) { match element.get_attribute(&ns!(""), &atom!("type")).map(|s| s.r().Value()) {
Some(ref s) if s.is_empty() => { Some(ref s) if s.is_empty() => {
// type attr exists, but empty means js // type attr exists, but empty means js
debug!("script type empty, inferring js"); debug!("script type empty, inferring js");
@ -497,7 +501,6 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
None => { None => {
debug!("no script type"); debug!("no script type");
match element.get_attribute(&ns!(""), &atom!("language")) match element.get_attribute(&ns!(""), &atom!("language"))
.root()
.map(|s| s.r().Value()) { .map(|s| s.r().Value()) {
Some(ref s) if s.is_empty() => { Some(ref s) if s.is_empty() => {
debug!("script language empty, inferring js"); debug!("script language empty, inferring js");
@ -528,44 +531,44 @@ trait PrivateHTMLScriptElementHelpers {
cancelable: EventCancelable) -> bool; cancelable: EventCancelable) -> bool;
} }
impl<'a> PrivateHTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> { impl<'a> PrivateHTMLScriptElementHelpers for &'a HTMLScriptElement {
fn dispatch_event(self, fn dispatch_event(self,
type_: DOMString, type_: DOMString,
bubbles: EventBubbles, bubbles: EventBubbles,
cancelable: EventCancelable) -> bool { cancelable: EventCancelable) -> bool {
let window = window_from_node(self).root(); let window = window_from_node(self);
let window = window.r(); let window = window.r();
let event = Event::new(GlobalRef::Window(window), let event = Event::new(GlobalRef::Window(window),
type_, type_,
bubbles, bubbles,
cancelable).root(); cancelable);
let event = event.r(); let event = event.r();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self); let target = EventTargetCast::from_ref(self);
event.fire(target) event.fire(target)
} }
} }
impl<'a> VirtualMethods for JSRef<'a, HTMLScriptElement> { impl<'a> VirtualMethods for &'a HTMLScriptElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
fn after_set_attr(&self, attr: JSRef<Attr>) { fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
if attr.local_name() == &atom!("src") && !self.parser_inserted.get() && node.is_in_doc() { if attr.local_name() == &atom!("src") && !self.parser_inserted.get() && node.is_in_doc() {
self.prepare(); self.prepare();
} }
} }
fn child_inserted(&self, child: JSRef<Node>) { fn child_inserted(&self, child: &Node) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.child_inserted(child); s.child_inserted(child);
} }
let node: JSRef<Node> = NodeCast::from_ref(*self); let node = NodeCast::from_ref(*self);
if !self.parser_inserted.get() && node.is_in_doc() { if !self.parser_inserted.get() && node.is_in_doc() {
self.prepare(); self.prepare();
} }
@ -581,7 +584,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLScriptElement> {
} }
} }
fn cloning_steps(&self, copy: JSRef<Node>, maybe_doc: Option<JSRef<Document>>, fn cloning_steps(&self, copy: &Node, maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag) { clone_children: CloneChildrenFlag) {
if let Some(ref s) = self.super_type() { if let Some(ref s) = self.super_type() {
s.cloning_steps(copy, maybe_doc, clone_children); s.cloning_steps(copy, maybe_doc, clone_children);
@ -589,13 +592,13 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLScriptElement> {
// https://whatwg.org/html/#already-started // https://whatwg.org/html/#already-started
if self.already_started.get() { if self.already_started.get() {
let copy_elem: JSRef<HTMLScriptElement> = HTMLScriptElementCast::to_ref(copy).unwrap(); let copy_elem = HTMLScriptElementCast::to_ref(copy).unwrap();
copy_elem.mark_already_started(); copy_elem.mark_already_started();
} }
} }
} }
impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> { impl<'a> HTMLScriptElementMethods for &'a HTMLScriptElement {
make_url_getter!(Src); make_url_getter!(Src);
make_setter!(SetSrc, "src"); make_setter!(SetSrc, "src");
@ -607,7 +610,7 @@ impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> {
// https://www.whatwg.org/html/#dom-script-text // https://www.whatwg.org/html/#dom-script-text
fn SetText(self, value: DOMString) { fn SetText(self, value: DOMString) {
let node: JSRef<Node> = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.SetTextContent(Some(value)) node.SetTextContent(Some(value))
} }
} }
@ -619,7 +622,7 @@ struct EventDispatcher {
impl Runnable for EventDispatcher { impl Runnable for EventDispatcher {
fn handler(self: Box<EventDispatcher>) { fn handler(self: Box<EventDispatcher>) {
let target = self.element.to_temporary().root(); let target = self.element.root();
if self.is_error { if self.is_error {
target.r().dispatch_error_event(); target.r().dispatch_error_event();
} else { } else {

Some files were not shown because too many files have changed in this diff Show more