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

View file

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

View file

@ -6,18 +6,19 @@ use devtools_traits::{CachedConsoleMessage, CachedConsoleMessageTypes, PAGE_ERRO
use devtools_traits::{EvaluateJSReply, NodeInfo, Modification, TimelineMarker, TimelineMarkerType};
use dom::bindings::conversions::FromJSValConvertible;
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::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::DOMRectBinding::{DOMRectMethods};
use dom::bindings::codegen::Bindings::ElementBinding::{ElementMethods};
use dom::node::{Node, NodeHelpers};
use dom::window::{WindowHelpers, ScriptHelpers};
use dom::element::Element;
use dom::document::DocumentHelpers;
use page::{IterablePage, Page};
use msg::constellation_msg::PipelineId;
use script_task::{get_page, ScriptTask};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;
use std::sync::mpsc::Sender;
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>){
let page = get_page(&*page, pipeline);
let window = page.window().root();
let window = page.window();
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
} else if rval.is_boolean() {
EvaluateJSReply::BooleanValue(rval.to_boolean())
} else if rval.is_double() {
EvaluateJSReply::NumberValue(FromJSValConvertible::from_jsval(cx, rval, ()).unwrap())
} else if rval.is_string() {
} else if rval.ptr.is_boolean() {
EvaluateJSReply::BooleanValue(rval.ptr.to_boolean())
} else if rval.ptr.is_double() {
EvaluateJSReply::NumberValue(FromJSValConvertible::from_jsval(cx, rval.handle(), ()).unwrap())
} else if rval.ptr.is_string() {
//FIXME: use jsstring_to_str when jsval grows to_jsstring
EvaluateJSReply::StringValue(
FromJSValConvertible::from_jsval(cx, rval, StringificationBehavior::Default).unwrap())
} else if rval.is_null() {
FromJSValConvertible::from_jsval(cx, rval.handle(), StringificationBehavior::Default).unwrap())
} else if rval.ptr.is_null() {
EvaluateJSReply::NullValue
} else {
//FIXME: jsvals don't have an is_int32/is_number yet
assert!(rval.is_object());
assert!(rval.ptr.is_object());
panic!("object values unimplemented")
}).unwrap();
}
pub fn handle_get_root_node(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
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();
}
pub fn handle_get_document_element(page: &Rc<Page>, pipeline: PipelineId, reply: Sender<NodeInfo>) {
let page = get_page(&*page, pipeline);
let document = page.document().root();
let document_element = document.r().GetDocumentElement().root().unwrap();
let document = page.document();
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();
}
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 document = page.document().root();
let node: JSRef<Node> = NodeCast::from_ref(document.r());
let document = page.document();
let node = NodeCast::from_ref(document.r());
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;
}
}
@ -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>>) {
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 child = child.root();
child.r().summarize()
}).collect();
reply.send(children).unwrap();
}
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 elem: JSRef<Element> = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
let rect = elem.GetBoundingClientRect().root();
let node = find_node_by_unique_id(&*page, pipeline, node_id);
let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
let rect = elem.GetBoundingClientRect();
let width = *rect.r().Width();
let height = *rect.r().Height();
reply.send((width, height)).unwrap();
@ -141,8 +142,8 @@ pub fn handle_modify_attribute(page: &Rc<Page>,
pipeline: PipelineId,
node_id: String,
modifications: Vec<Modification>) {
let node = find_node_by_unique_id(&*page, pipeline, node_id).root();
let elem: JSRef<Element> = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
let node = find_node_by_unique_id(&*page, pipeline, node_id);
let elem = ElementCast::to_ref(node.r()).expect("should be getting layout of element");
for modification in modifications.iter(){
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) {
let page = get_page(&*page, pipeline_id);
let window = page.window().root();
let window = page.window();
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 {
match *marker_type {
TimelineMarkerType::Reflow => {
let window = page.window().root();
let window = page.window();
window.r().set_devtools_timeline_marker(TimelineMarkerType::Reflow, reply.clone());
}
TimelineMarkerType::DOMEvent => {
@ -180,7 +181,7 @@ pub fn handle_set_timeline_markers(page: &Rc<Page>,
pub fn handle_drop_timeline_markers(page: &Rc<Page>,
script_task: &ScriptTask,
marker_types: Vec<TimelineMarkerType>) {
let window = page.window().root();
let window = page.window();
for marker_type in &marker_types {
match *marker_type {
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, )>) {
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);
}

View file

@ -4,7 +4,6 @@
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast};
use dom::bindings::js::{JSRef, Temporary, OptionalRootable, Rootable};
use dom::element::{Element, ActivationElementHelpers};
use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget;
@ -15,7 +14,7 @@ use std::borrow::ToOwned;
/// Trait for elements with defined activation behavior
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?
fn is_instance_activatable(&self) -> bool;
@ -27,32 +26,32 @@ pub trait Activatable {
fn canceled_activation(&self);
// 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
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool);
// https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps
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
if element.r().click_in_progress() {
if element.click_in_progress() {
return;
}
// Step 2
element.r().set_click_in_progress(true);
element.set_click_in_progress(true);
// Step 3
self.pre_click_activation();
// Step 4
// https://html.spec.whatwg.org/multipage/#fire-a-synthetic-mouse-event
let win = window_from_node(element.r()).root();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(element.r());
let win = window_from_node(element);
let target = EventTargetCast::from_ref(element);
let mouse = MouseEvent::new(win.r(), "click".to_owned(),
EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, Some(win.r()), 1,
0, 0, 0, 0, ctrlKey, shiftKey, altKey, metaKey,
0, None).root();
let event: JSRef<Event> = EventCast::from_ref(mouse.r());
0, None);
let event = EventCast::from_ref(mouse.r());
event.fire(target);
// Step 5
@ -64,6 +63,6 @@ pub trait Activatable {
}
// 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::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Temporary};
use dom::bindings::js::{OptionalRootable, Rootable, RootedReference};
use dom::bindings::js::{JS, MutNullableHeap};
use dom::bindings::js::{Root, RootedReference};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window;
use dom::virtualmethods::vtable_for;
@ -125,7 +124,7 @@ pub struct Attr {
impl Attr {
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 {
reflector_: Reflector::new(),
local_name: local_name,
@ -133,13 +132,13 @@ impl Attr {
name: name,
namespace: namespace,
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,
prefix: Option<Atom>, owner: Option<JSRef<Element>>) -> Temporary<Attr> {
prefix: Option<Atom>, owner: Option<&Element>) -> Root<Attr> {
reflect_dom_object(
box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
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
fn LocalName(self) -> DOMString {
(**self.local_name()).to_owned()
@ -177,8 +176,7 @@ impl<'a> AttrMethods for JSRef<'a, Attr> {
fn SetValue(self, value: DOMString) {
match self.owner() {
None => *self.value.borrow_mut() = AttrValue::String(value),
Some(o) => {
let owner = o.root();
Some(owner) => {
let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
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
fn GetOwnerElement(self) -> Option<Temporary<Element>> {
fn GetOwnerElement(self) -> Option<Root<Element>> {
self.owner()
}
@ -236,19 +234,19 @@ impl<'a> AttrMethods for JSRef<'a, Attr> {
}
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 local_name(self) -> &'a Atom;
fn set_owner(self, owner: Option<JSRef<Element>>);
fn owner(self) -> Option<Temporary<Element>>;
fn set_owner(self, owner: Option<&Element>);
fn owner(self) -> Option<Root<Element>>;
fn summarize(self) -> AttrInfo;
}
impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: JSRef<Element>) {
assert!(Some(owner) == self.owner().root().r());
impl<'a> AttrHelpers<'a> for &'a Attr {
fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
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!("");
match set_type {
@ -265,21 +263,21 @@ impl<'a> AttrHelpers<'a> for JSRef<'a, Attr> {
}
fn value(self) -> Ref<'a, AttrValue> {
self.extended_deref().value.borrow()
self.value.borrow()
}
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
/// 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;
match (self.owner().root().r(), owner) {
match (self.owner().r(), owner) {
(None, Some(new)) => {
// 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) => {
// 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)
}
self.owner.set(owner.map(JS::from_rooted))
self.owner.set(owner.map(JS::from_ref))
}
fn owner(self) -> Option<Temporary<Element>> {
self.owner.get().map(Temporary::from_rooted)
fn owner(self) -> Option<Root<Element>> {
self.owner.get().map(Root::from_rooted)
}
fn summarize(self) -> AttrInfo {
@ -311,7 +309,7 @@ pub trait AttrHelpersForLayout {
unsafe fn value_atom_forever(&self) -> Option<Atom>;
unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
unsafe fn local_name_atom_forever(&self) -> Atom;
unsafe fn value(&self) -> &AttrValue;
unsafe fn value_for_layout(&self) -> &AttrValue;
}
#[allow(unsafe_code)]
@ -354,7 +352,7 @@ impl AttrHelpersForLayout for Attr {
}
#[inline]
unsafe fn value(&self) -> &AttrValue {
unsafe fn value_for_layout(&self) -> &AttrValue {
self.value.borrow_for_layout()
}
}

View file

@ -6,15 +6,22 @@
use dom::bindings::error::{Fallible, Error};
use dom::bindings::global::global_object_for_js_object;
use dom::bindings::js::JSRef;
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::{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::rust::with_compartment;
use std::ffi::CString;
use std::ptr;
use std::rc::Rc;
use std::intrinsics::return_address;
use std::default::Default;
/// The exception handling used for a call.
#[derive(Copy, Clone, PartialEq)]
@ -26,7 +33,7 @@ pub enum ExceptionHandling {
}
/// A common base class for representing IDL callback function types.
#[derive(Copy, Clone,PartialEq)]
#[derive(PartialEq)]
#[jstraceable]
pub struct CallbackFunction {
object: CallbackObject
@ -34,17 +41,23 @@ pub struct CallbackFunction {
impl CallbackFunction {
/// Create a new `CallbackFunction` for this object.
pub fn new(callback: *mut JSObject) -> CallbackFunction {
pub fn new() -> CallbackFunction {
CallbackFunction {
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.
#[derive(Copy, Clone,PartialEq)]
#[derive(PartialEq)]
#[jstraceable]
pub struct CallbackInterface {
object: CallbackObject
@ -53,18 +66,23 @@ pub struct CallbackInterface {
/// A common base class for representing IDL callback function and
/// callback interface types.
#[allow(raw_pointer_derive)]
#[derive(Copy, Clone,PartialEq)]
#[jstraceable]
struct CallbackObject {
/// 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
/// callback interface types.
pub trait CallbackContainer {
/// 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`.
fn callback(&self) -> *mut JSObject;
}
@ -72,83 +90,103 @@ pub trait CallbackContainer {
impl CallbackInterface {
/// Returns the underlying `JSObject`.
pub fn callback(&self) -> *mut JSObject {
self.object.callback
self.object.callback.get()
}
}
impl CallbackFunction {
/// Returns the underlying `JSObject`.
pub fn callback(&self) -> *mut JSObject {
self.object.callback
self.object.callback.get()
}
}
impl CallbackInterface {
/// Create a new CallbackInterface object for the given `JSObject`.
pub fn new(callback: *mut JSObject) -> CallbackInterface {
pub fn new() -> CallbackInterface {
CallbackInterface {
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,
/// or an error otherwise.
pub fn get_callable_property(&self, cx: *mut JSContext, name: &str)
-> Fallible<JSVal> {
let mut callable = UndefinedValue();
let mut callable = RootedValue::new(cx, UndefinedValue());
let obj = RootedObject::new(cx, self.callback());
unsafe {
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);
}
if !callable.is_object() ||
JS_ObjectIsCallable(cx, callable.to_object()) == 0 {
if !callable.ptr.is_object() ||
IsCallable(callable.ptr.to_object()) == 0 {
return Err(Error::Type(
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`.
pub fn wrap_call_this_object<T: Reflectable>(cx: *mut JSContext,
p: JSRef<T>) -> *mut JSObject {
let mut obj = p.reflector().get_jsobject();
assert!(!obj.is_null());
p: &T,
mut rval: MutableHandleObject) {
rval.set(p.reflector().get_jsobject().get());
assert!(!rval.get().is_null());
unsafe {
if JS_WrapObject(cx, &mut obj) == 0 {
return ptr::null_mut();
if JS_WrapObject(cx, rval) == 0 {
rval.set(ptr::null_mut());
}
}
return obj;
}
/// 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.
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.
cx: *mut JSContext,
/// The compartment we were in before the call.
old_compartment: *mut JSCompartment,
/// The exception handling used for the call.
_handling: ExceptionHandling,
handling: ExceptionHandling,
}
impl CallSetup {
/// Performs the setup needed to make a call.
#[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.root();
let cx = global.r().get_cx();
unsafe { JS_BeginRequest(cx); }
let exception_compartment = unsafe {
GetGlobalForObjectCrossCompartment(callback.callback())
};
CallSetup {
exception_compartment:
RootedObject::new_with_addr(cx, exception_compartment,
unsafe { return_address() }),
cx: cx,
_handling: handling,
old_compartment: unsafe { JS_EnterCompartment(cx, callback.callback()) },
handling: handling,
}
}
@ -160,14 +198,23 @@ impl CallSetup {
impl Drop for CallSetup {
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 {
unsafe {
let old_global = JS_GetGlobalObject(self.cx);
with_compartment(self.cx, old_global, || {
JS_ReportPendingException(self.cx)
});
let old_global = RootedObject::new(self.cx, self.exception_compartment.ptr);
let saved = JS_SaveFrameChain(self.cx) != 0;
{
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!
#[allow(unsafe_code)]
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()
}

View file

@ -15,7 +15,7 @@
DOMInterfaces = {
'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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -24,17 +24,17 @@
//! | USVString | `USVString` |
//! | ByteString | `ByteString` |
//! | object | `*mut JSObject` |
//! | interface types | `JSRef<T>` | `Temporary<T>` |
//! | interface types | `&T` | `Root<T>` |
//! | dictionary types | `&T` | *unsupported* |
//! | enumeration types | `T` |
//! | callback function types | `T` |
//! | callback function types | `Rc<T>` |
//! | nullable types | `Option<T>` |
//! | sequences | `Vec<T>` |
//! | union types | `T` |
use dom::bindings::codegen::PrototypeList;
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::str::{ByteString, USVString};
use dom::bindings::utils::{Reflectable, Reflector, DOMClass};
@ -43,14 +43,15 @@ use util::str::DOMString;
use js;
use js::glue::{RUST_JSID_TO_STRING, RUST_JSID_IS_STRING};
use js::glue::RUST_JS_NumberValue;
use js::jsapi::{JSBool, JSContext, JSObject, JSString, jsid};
use js::jsapi::{JS_ValueToUint64, JS_ValueToInt64};
use js::jsapi::{JS_ValueToECMAUint32, JS_ValueToECMAInt32};
use js::jsapi::{JS_ValueToUint16, JS_ValueToNumber, JS_ValueToBoolean};
use js::jsapi::{JS_ValueToString, JS_GetStringCharsAndLength};
use js::rust::{ToUint64, ToInt64};
use js::rust::{ToUint32, ToInt32};
use js::rust::{ToUint16, ToNumber, ToBoolean, ToString};
use js::jsapi::{JSContext, JSObject, JSString};
use js::jsapi::{JS_StringHasLatin1Chars, JS_GetLatin1StringCharsAndLength, JS_GetTwoByteStringCharsAndLength};
use js::jsapi::{JS_NewUCStringCopyN, JS_NewStringCopyN};
use js::jsapi::{JS_WrapValue};
use js::jsapi::{JSClass, JS_GetClass};
use js::jsapi::{HandleId, HandleValue, HandleObject, MutableHandleValue};
use js::jsval::JSVal;
use js::jsval::{UndefinedValue, NullValue, BooleanValue, Int32Value, UInt32Value};
use js::jsval::{StringValue, ObjectValue, ObjectOrNullValue};
@ -60,6 +61,9 @@ use num::Float;
use std::borrow::ToOwned;
use std::default;
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`
/// implements a given interface.
@ -74,7 +78,7 @@ pub trait IDLInterface {
/// A trait to convert Rust types to `JSVal`s.
pub trait ToJSValConvertible {
/// 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.
@ -85,206 +89,201 @@ pub trait FromJSValConvertible {
/// Optional configuration of type `T` can be passed as the `option`
/// argument.
/// 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 () {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
UndefinedValue()
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(UndefinedValue());
}
}
impl ToJSValConvertible for JSVal {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
let mut value = *self;
if unsafe { JS_WrapValue(cx, &mut value) } == 0 {
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(*self);
if unsafe { JS_WrapValue(cx, rval) } == 0 {
panic!("JS_WrapValue failed.");
}
value
}
}
unsafe fn convert_from_jsval<T: default::Default>(
cx: *mut JSContext, value: JSVal,
convert_fn: unsafe extern "C" fn(*mut JSContext, JSVal, *mut T) -> JSBool) -> Result<T, ()> {
let mut ret = default::Default::default();
if convert_fn(cx, value, &mut ret) == 0 {
Err(())
} else {
Ok(ret)
impl ToJSValConvertible for HandleValue {
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(self.get());
if unsafe { JS_WrapValue(cx, rval) } == 0 {
panic!("JS_WrapValue failed.");
}
}
}
impl ToJSValConvertible for bool {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
BooleanValue(*self)
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(BooleanValue(*self));
}
}
impl FromJSValConvertible for bool {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<bool, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToBoolean) };
result.map(|b| b != 0)
fn from_jsval(_cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<bool, ()> {
Ok(ToBoolean(val))
}
}
impl ToJSValConvertible for i8 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
Int32Value(*self as i32)
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(Int32Value(*self as i32));
}
}
impl FromJSValConvertible for i8 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<i8, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToECMAInt32) };
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<i8, ()> {
let result = ToInt32(cx, val);
result.map(|v| v as i8)
}
}
impl ToJSValConvertible for u8 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
Int32Value(*self as i32)
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(Int32Value(*self as i32));
}
}
impl FromJSValConvertible for u8 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<u8, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToECMAInt32) };
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<u8, ()> {
let result = ToInt32(cx, val);
result.map(|v| v as u8)
}
}
impl ToJSValConvertible for i16 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
Int32Value(*self as i32)
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(Int32Value(*self as i32));
}
}
impl FromJSValConvertible for i16 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<i16, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToECMAInt32) };
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<i16, ()> {
let result = ToInt32(cx, val);
result.map(|v| v as i16)
}
}
impl ToJSValConvertible for u16 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
Int32Value(*self as i32)
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(Int32Value(*self as i32));
}
}
impl FromJSValConvertible for u16 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<u16, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToUint16) }
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<u16, ()> {
ToUint16(cx, val)
}
}
impl ToJSValConvertible for i32 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
Int32Value(*self)
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(Int32Value(*self));
}
}
impl FromJSValConvertible for i32 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<i32, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToECMAInt32) }
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<i32, ()> {
ToInt32(cx, val)
}
}
impl ToJSValConvertible for u32 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
UInt32Value(*self)
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(UInt32Value(*self));
}
}
impl FromJSValConvertible for u32 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<u32, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToECMAUint32) }
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<u32, ()> {
ToUint32(cx, val)
}
}
impl ToJSValConvertible for i64 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
unsafe {
RUST_JS_NumberValue(*self as f64)
rval.set(RUST_JS_NumberValue(*self as f64));
}
}
}
impl FromJSValConvertible for i64 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<i64, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToInt64) }
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<i64, ()> {
ToInt64(cx, val)
}
}
impl ToJSValConvertible for u64 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
unsafe {
RUST_JS_NumberValue(*self as f64)
rval.set(RUST_JS_NumberValue(*self as f64));
}
}
}
impl FromJSValConvertible for u64 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<u64, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToUint64) }
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<u64, ()> {
ToUint64(cx, val)
}
}
impl ToJSValConvertible for f32 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
unsafe {
RUST_JS_NumberValue(*self as f64)
rval.set(RUST_JS_NumberValue(*self as f64));
}
}
}
impl FromJSValConvertible for f32 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<f32, ()> {
let result = unsafe { convert_from_jsval(cx, val, JS_ValueToNumber) };
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<f32, ()> {
let result = ToNumber(cx, val);
result.map(|f| f as f32)
}
}
impl ToJSValConvertible for f64 {
fn to_jsval(&self, _cx: *mut JSContext) -> JSVal {
fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) {
unsafe {
RUST_JS_NumberValue(*self)
rval.set(RUST_JS_NumberValue(*self));
}
}
}
impl FromJSValConvertible for f64 {
type Config = ();
fn from_jsval(cx: *mut JSContext, val: JSVal, _option: ()) -> Result<f64, ()> {
unsafe { convert_from_jsval(cx, val, JS_ValueToNumber) }
fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<f64, ()> {
ToNumber(cx, val)
}
}
impl<T: Float + ToJSValConvertible> ToJSValConvertible for Finite<T> {
#[inline]
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
let value = **self;
value.to_jsval(cx)
value.to_jsval(cx, rval);
}
}
impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite<T> {
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));
match Finite::new(result) {
Some(v) => Ok(v),
@ -297,21 +296,22 @@ impl<T: Float + FromJSValConvertible<Config=()>> FromJSValConvertible for Finite
}
impl ToJSValConvertible for str {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
unsafe {
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() {
panic!("JS_NewUCStringCopyN failed");
}
StringValue(&*jsstr)
rval.set(StringValue(&*jsstr));
}
}
}
impl ToJSValConvertible for DOMString {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
(**self).to_jsval(cx)
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
(**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
/// contain valid UTF-16.
pub fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString {
unsafe {
let mut length = 0;
let chars = JS_GetStringCharsAndLength(cx, s, &mut length);
let mut length = 0;
let latin1 = unsafe { JS_StringHasLatin1Chars(s) != 0 };
if latin1 {
let chars = unsafe {
JS_GetLatin1StringCharsAndLength(cx, ptr::null(), s, &mut length)
};
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()
}
}
/// 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.
pub fn jsid_to_str(cx: *mut JSContext, id: jsid) -> DOMString {
pub fn jsid_to_str(cx: *mut JSContext, id: HandleId) -> DOMString {
unsafe {
assert!(RUST_JSID_IS_STRING(id) != 0);
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 {
type Config = StringificationBehavior;
fn from_jsval(cx: *mut JSContext, value: JSVal,
fn from_jsval(cx: *mut JSContext, value: HandleValue,
null_behavior: StringificationBehavior)
-> Result<DOMString, ()> {
if null_behavior == StringificationBehavior::Empty && value.is_null() {
if null_behavior == StringificationBehavior::Empty &&
value.get().is_null() {
Ok("".to_owned())
} else {
let jsstr = unsafe { JS_ValueToString(cx, value) };
let jsstr = ToString(cx, value);
if jsstr.is_null() {
debug!("JS_ValueToString failed");
debug!("ToString failed");
Err(())
} else {
Ok(jsstring_to_str(cx, jsstr))
@ -371,56 +390,75 @@ impl FromJSValConvertible for DOMString {
}
impl ToJSValConvertible for USVString {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
self.0.to_jsval(cx)
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
self.0.to_jsval(cx, rval);
}
}
impl FromJSValConvertible for USVString {
type Config = ();
fn from_jsval(cx: *mut JSContext, value: JSVal, _: ())
fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ())
-> Result<USVString, ()> {
let jsstr = unsafe { JS_ValueToString(cx, value) };
let jsstr = ToString(cx, value);
if jsstr.is_null() {
debug!("JS_ValueToString failed");
Err(())
} else {
unsafe {
let mut length = 0;
let chars = JS_GetStringCharsAndLength(cx, jsstr, &mut length);
assert!(!chars.is_null());
let char_vec = slice::from_raw_parts(chars, length as usize);
Ok(USVString(String::from_utf16_lossy(char_vec)))
}
debug!("ToString failed");
return Err(());
}
let latin1 = unsafe { JS_StringHasLatin1Chars(jsstr) != 0 };
if latin1 {
return Ok(USVString(jsstring_to_str(cx, jsstr)));
}
unsafe {
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 {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
unsafe {
let jsstr = JS_NewStringCopyN(cx, self.as_ptr() as *const libc::c_char,
self.len() as libc::size_t);
if jsstr.is_null() {
panic!("JS_NewStringCopyN failed");
}
StringValue(&*jsstr)
rval.set(StringValue(&*jsstr));
}
}
}
impl FromJSValConvertible for ByteString {
type Config = ();
fn from_jsval(cx: *mut JSContext, value: JSVal, _option: ()) -> Result<ByteString, ()> {
unsafe {
let string = JS_ValueToString(cx, value);
if string.is_null() {
debug!("JS_ValueToString failed");
return Err(());
}
fn from_jsval(cx: *mut JSContext, value: HandleValue, _option: ()) -> Result<ByteString, ()> {
let string = ToString(cx, value);
if string.is_null() {
debug!("ToString failed");
return Err(());
}
let latin1 = unsafe { JS_StringHasLatin1Chars(string) != 0 };
if latin1 {
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);
if char_vec.iter().any(|&c| c > 0xFF) {
@ -434,14 +472,13 @@ impl FromJSValConvertible for ByteString {
}
impl ToJSValConvertible for Reflector {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
let obj = self.get_jsobject();
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
let obj = self.get_jsobject().get();
assert!(!obj.is_null());
let mut value = ObjectValue(unsafe { &*obj });
if unsafe { JS_WrapValue(cx, &mut value) } == 0 {
rval.set(ObjectValue(unsafe { &*obj }));
if unsafe { JS_WrapValue(cx, rval) } == 0 {
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.
pub fn is_dom_proxy(obj: *mut JSObject) -> bool {
use js::glue::{js_IsObjectProxyClass, js_IsFunctionProxyClass, IsProxyHandlerFamily};
use js::glue::IsProxyHandlerFamily;
unsafe {
(js_IsObjectProxyClass(obj) || js_IsFunctionProxyClass(obj)) &&
IsProxyHandlerFamily(obj)
let clasp = JS_GetClass(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
// globals and non-globals.
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.
pub unsafe fn native_from_reflector<T>(obj: *mut JSObject) -> *const T {
use js::jsapi::JS_GetReservedSlot;
use js::glue::GetProxyPrivate;
let slot = dom_object_slot(obj);
let value = JS_GetReservedSlot(obj, slot);
value.to_private() as *const T
let clasp = JS_GetClass(obj);
let value = if is_dom_class(clasp) {
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.
@ -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
/// not a reflector for a DOM object of the given type (as defined by the
/// 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
{
use js::glue::{IsWrapper, UnwrapObject};
use std::ptr;
unsafe {
let dom_class = try!(get_dom_class(obj).or_else(|_| {
if IsWrapper(obj) == 1 {
debug!("found wrapper");
obj = UnwrapObject(obj, /* stopAtOuter = */ 0, ptr::null_mut());
obj = UnwrapObject(obj, /* stopAtOuter = */ 0);
if obj.is_null() {
debug!("unwrapping security wrapper failed");
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();
if dom_class.interface_chain[proto_depth] == proto_id {
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 {
debug!("bad prototype");
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> {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
self.r().reflector().to_jsval(cx)
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
self.r().reflector().to_jsval(cx, rval);
}
}
impl<'a, T: Reflectable> ToJSValConvertible for JSRef<'a, T> {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
self.reflector().to_jsval(cx)
}
}
impl<'a, T: Reflectable> ToJSValConvertible for Unrooted<T> {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
self.reflector().to_jsval(cx)
impl<'a, T: Reflectable> ToJSValConvertible for &'a T {
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
self.reflector().to_jsval(cx, rval);
}
}
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 {
&Some(ref value) => value.to_jsval(cx),
&None => NullValue(),
&Some(ref value) => value.to_jsval(cx, rval),
&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> {
type Config = ();
fn from_jsval(cx: *mut JSContext, value: JSVal, _: ()) -> Result<Option<T>, ()> {
if value.is_null_or_undefined() {
fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ()) -> Result<Option<T>, ()> {
if value.get().is_null_or_undefined() {
Ok(None)
} else {
let option: X = default::Default::default();
@ -596,11 +645,10 @@ impl<X: default::Default, T: FromJSValConvertible<Config=X>> FromJSValConvertibl
}
impl ToJSValConvertible for *mut JSObject {
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
let mut wrapped = ObjectOrNullValue(*self);
fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
rval.set(ObjectOrNullValue(*self));
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::global::GlobalRef;
use dom::bindings::js::Rootable;
use dom::domexception::{DOMException, DOMErrorName};
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_ReportErrorNumber, JSErrorFormatString, JSEXN_TYPEERR, JSEXN_RANGEERR};
use js::jsapi::{JS_ReportErrorNumber1, JSErrorFormatString, JSExnType};
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 std::ffi::CString;
use std::ptr;
use std::mem;
/// DOM exceptions that can be thrown by a native DOM method.
#[derive(Debug, Clone)]
@ -116,10 +118,11 @@ pub fn throw_dom_exception(cx: *mut JSContext, global: GlobalRef,
};
assert!(unsafe { JS_IsExceptionPending(cx) } == 0);
let exception = DOMException::new(global, code).root();
let thrown = exception.to_jsval(cx);
let exception = DOMException::new(global, code);
let mut thrown = RootedValue::new(cx, UndefinedValue());
exception.to_jsval(cx, thrown.handle_mut());
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 {
if JS_IsExceptionPending(cx) != 0 {
let saved = JS_SaveFrameChain(cx);
with_compartment(cx, obj, || {
{
let _ac = JSAutoCompartment::new(cx, obj);
JS_ReportPendingException(cx);
});
}
if saved != 0 {
JS_RestoreFrameChain(cx);
}
@ -158,25 +162,26 @@ static ERROR_FORMAT_STRING_STRING: [libc::c_char; 4] = [
static mut TYPE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
argCount: 1,
exnType: JSEXN_TYPEERR as i16,
exnType: JSExnType::JSEXN_TYPEERR as i16,
};
/// Format string struct used to throw `RangeError`s.
static mut RANGE_ERROR_FORMAT_STRING: JSErrorFormatString = JSErrorFormatString {
format: &ERROR_FORMAT_STRING_STRING as *const libc::c_char,
argCount: 1,
exnType: JSEXN_RANGEERR as i16,
exnType: JSExnType::JSEXN_RANGEERR as i16,
};
/// Callback used to throw javascript errors.
/// See throw_js_error for info about error_number.
unsafe extern fn get_error_message(_user_ref: *mut libc::c_void,
_locale: *const libc::c_char,
error_number: libc::c_uint) -> *const JSErrorFormatString
error_number: libc::c_uint)
-> *const JSErrorFormatString
{
match error_number as i32 {
JSEXN_TYPEERR => &TYPE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
JSEXN_RANGEERR => &RANGE_ERROR_FORMAT_STRING as *const JSErrorFormatString,
let num: JSExnType = mem::transmute(error_number);
match num {
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)
}
}
@ -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) {
let error = CString::new(error).unwrap();
unsafe {
JS_ReportErrorNumber(cx,
Some(get_error_message as
unsafe extern "C" fn(*mut libc::c_void, *const libc::c_char,
libc::c_uint) -> *const JSErrorFormatString),
JS_ReportErrorNumber1(cx,
Some(get_error_message),
ptr::null_mut(), error_number, error.as_ptr());
}
}
/// Throw a `TypeError` with the given message.
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.
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::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::document::DocumentHelpers;
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
@ -21,7 +21,7 @@ use msg::constellation_msg::{PipelineId, WorkerId};
use net_traits::ResourceTask;
use js::{JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS};
use js::glue::{GetGlobalForObjectCrossCompartment};
use js::jsapi::{GetGlobalForObjectCrossCompartment};
use js::jsapi::{JSContext, JSObject};
use js::jsapi::{JS_GetClass};
use url::Url;
@ -30,9 +30,9 @@ use url::Url;
#[derive(Copy, Clone)]
pub enum GlobalRef<'a> {
/// A reference to a `Window` object.
Window(JSRef<'a, window::Window>),
Window(&'a window::Window),
/// A reference to a `WorkerGlobalScope` object.
Worker(JSRef<'a, WorkerGlobalScope>),
Worker(&'a WorkerGlobalScope),
}
/// A stack-based rooted reference to a global object.
@ -55,15 +55,6 @@ pub enum GlobalField {
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> {
/// Get the `JSContext` for the `JSRuntime` associated with the thread
/// 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
/// 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 {
GlobalRef::Window(window) => window,
GlobalRef::Worker(_) => panic!("expected a Window scope"),
@ -104,7 +95,7 @@ impl<'a> GlobalRef<'a> {
pub fn resource_task(&self) -> ResourceTask {
match *self {
GlobalRef::Window(ref window) => {
let doc = window.Document().root();
let doc = window.Document();
let doc = doc.r();
let loader = doc.loader();
loader.resource_task.clone()
@ -182,8 +173,8 @@ impl GlobalField {
/// Create a new `GlobalField` from a rooted reference.
pub fn from_rooted(global: &GlobalRef) -> GlobalField {
match *global {
GlobalRef::Window(window) => GlobalField::Window(JS::from_rooted(window)),
GlobalRef::Worker(worker) => GlobalField::Worker(JS::from_rooted(worker)),
GlobalRef::Window(window) => GlobalField::Window(JS::from_ref(window)),
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.
#[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 {
let global = GetGlobalForObjectCrossCompartment(obj);
let clasp = JS_GetClass(global);
assert!(((*clasp).flags & (JSCLASS_IS_DOMJSCLASS | JSCLASS_IS_GLOBAL)) != 0);
match native_from_reflector_jsmanaged(global) {
Ok(window) => return GlobalUnrooted::Window(window),
Ok(window) => return GlobalRoot::Window(window),
Err(_) => (),
}
match native_from_reflector_jsmanaged(global) {
Ok(worker) => return GlobalUnrooted::Worker(worker),
Ok(worker) => return GlobalRoot::Worker(worker),
Err(_) => (),
}

View file

@ -11,178 +11,32 @@
//!
//! 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.
//! - `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.
//! - `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::RootedVec;
use dom::bindings::trace::trace_reflector;
use dom::bindings::utils::{Reflector, Reflectable};
use dom::node::Node;
use js::jsapi::JSObject;
use js::jsval::JSVal;
use js::jsapi::{JSObject, Heap, JSTracer};
use js::jsval::{JSVal, UndefinedValue};
use layout_interface::TrustedNodeAddress;
use script_task::STACK_ROOTS;
use core::nonzero::NonZero;
use libc;
use std::cell::{Cell, UnsafeCell};
use std::default::Default;
use std::intrinsics::return_address;
use std::marker::PhantomData;
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
/// DOM objects.
#[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`
/// traits must be implemented on this.
@ -208,7 +88,7 @@ pub struct LayoutJS<T> {
impl<T: Reflectable> LayoutJS<T> {
/// Get the reflector.
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> PartialEq for JS<T> {
#[allow(unrooted_must_root)]
fn eq(&self, other: &JS<T>) -> bool {
self.ptr == other.ptr
}
}
impl<T> PartialEq for LayoutJS<T> {
#[allow(unrooted_must_root)]
fn eq(&self, other: &LayoutJS<T>) -> bool {
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> {
fn reflector<'a>(&'a self) -> &'a Reflector {
unsafe {
@ -298,19 +153,50 @@ impl<T: Reflectable> Reflectable for JS<T> {
pub trait HeapGCValue: JSTraceable {
}
impl HeapGCValue for JSVal {
impl HeapGCValue for Heap<JSVal> {
}
impl<T: Reflectable> HeapGCValue for JS<T> {
}
/// A holder that provides interior mutability for GC-managed values such as
/// `JSVal` and `JS<T>`.
/// A holder that provides interior mutability for GC-managed JSVals.
///
/// Must be used in place of traditional interior mutability to ensure proper
/// GC barriers are enforced.
#[must_root]
#[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> {
val: Cell<T>,
}
@ -323,13 +209,12 @@ impl<T: HeapGCValue+Copy> MutHeap<T> {
}
}
/// Set this `MutHeap` to the given value, calling write barriers as
/// appropriate.
/// Set this `MutHeap` to the given value.
pub fn set(&self, val: T) {
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 {
self.val.get()
}
@ -353,8 +238,7 @@ impl<T: HeapGCValue+Copy> MutNullableHeap<T> {
}
}
/// Set this `MutNullableHeap` to the given value, calling write barriers
/// as appropriate.
/// Set this `MutNullableHeap` to the given value.
pub fn set(&self, val: Option<T>) {
self.ptr.set(val);
}
@ -368,14 +252,14 @@ impl<T: HeapGCValue+Copy> MutNullableHeap<T> {
impl<T: Reflectable> MutNullableHeap<JS<T>> {
/// Retrieve a copy of the current inner value. If it is `None`, it is
/// initialized with the result of `cb` first.
pub fn or_init<F>(&self, cb: F) -> Temporary<T>
where F: FnOnce() -> Temporary<T>
pub fn or_init<F>(&self, cb: F) -> Root<T>
where F: FnOnce() -> Root<T>
{
match self.get() {
Some(inner) => Temporary::from_rooted(inner),
Some(inner) => Root::from_rooted(inner),
None => {
let inner = cb();
self.set(Some(JS::from_rooted(inner.clone())));
self.set(Some(JS::from_rooted(&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> {
/// 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
@ -419,129 +293,36 @@ impl<T: Reflectable> LayoutJS<T> {
pub trait RootedReference<T> {
/// Obtain a safe optional reference to the wrapped JS owned-value that
/// 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>> {
fn r<'a>(&'a self) -> Option<JSRef<'a, T>> {
fn r<'a>(&'a self) -> Option<&'a T> {
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> {
/// Obtain a safe optional optional reference to the wrapped JS owned-value
/// 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>>> {
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())
}
}
/// Trait that allows extracting a `JS<T>` value from a variety of
/// rooting-related containers, which in general is an unsafe operation since
/// 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.
/// A rooting mechanism for reflectors on the stack.
/// LIFO is not required.
///
/// 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).
#[no_move]
pub struct RootCollection {
roots: UnsafeCell<RootedVec<*mut JSObject>>,
roots: UnsafeCell<Vec<*const Reflector>>,
}
/// A pointer to a RootCollection, for use in global variables.
@ -555,142 +336,114 @@ impl Clone for RootCollectionPtr {
impl RootCollection {
/// Create an empty collection of roots
pub fn new() -> RootCollection {
let addr = unsafe {
return_address() as *const libc::c_void
};
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.
fn root<'b>(&self, untracked_js_ptr: *mut JSObject) {
/// Start tracking a stack-based root
fn root<'b>(&self, untracked_reflector: *const Reflector) {
unsafe {
let roots = self.roots.get();
(*roots).push(untracked_js_ptr);
debug!(" rooting {:?}", untracked_js_ptr);
let mut roots = &mut *self.roots.get();
roots.push(untracked_reflector);
assert!(!(*untracked_reflector).get_jsobject().is_null())
}
}
/// Stop tracking a stack-based root, asserting if LIFO root ordering has
/// been violated
/// Stop tracking a stack-based root, asserting if the reflector isn't found
fn unroot<'b, T: Reflectable>(&self, rooted: &Root<T>) {
unsafe {
let roots = self.roots.get();
let unrooted = (*roots).pop().unwrap();
debug!("unrooted {:?} (expecting {:?}", unrooted, rooted.js_ptr);
assert!(unrooted == rooted.js_ptr);
let mut roots = &mut *self.roots.get();
let old_reflector = &*rooted.r().reflector();
match roots.iter().rposition(|r| *r == old_reflector) {
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.
///
/// 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
/// for the same JS value. `Root`s cannot outlive the associated
/// `RootCollection` object. Attempts to transfer ownership of a `Root` via
/// moving will trigger dynamic unrooting failures due to incorrect ordering.
#[no_move]
/// `RootCollection` object.
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
ptr: NonZero<*const T>,
/// On-stack JS pointer to assuage conservative stack scanner
js_ptr: *mut JSObject,
/// List that ensures correct dynamic root ordering
root_list: *const RootCollection,
}
impl<T: Reflectable> Root<T> {
/// Create a new stack-bounded root for the provided JS-owned value.
/// It cannot not outlive its associated `RootCollection`, and it contains
/// a `JSRef` which cannot outlive this new `Root`.
#[inline]
fn new(roots: &'static RootCollection, unrooted: NonZero<*const T>)
-> Root<T> {
let js_ptr = unsafe {
(**unrooted).reflector().get_jsobject()
};
roots.root(js_ptr);
Root {
root_list: roots,
ptr: unrooted,
js_ptr: js_ptr,
}
/// It cannot not outlive its associated `RootCollection`, and it gives
/// out references which cannot outlive this new `Root`.
pub fn new(unrooted: NonZero<*const T>)
-> Root<T> {
STACK_ROOTS.with(|ref collection| {
let RootCollectionPtr(collection) = collection.get().unwrap();
unsafe { (*collection).root(&*(**unrooted).reflector()) }
Root {
ptr: unrooted,
root_list: collection,
}
})
}
/// 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
/// outlive the lifetime of this root.
pub fn r<'b>(&'b self) -> JSRef<'b, T> {
JSRef {
ptr: self.ptr,
chain: PhantomData,
}
pub fn r<'a>(&'a self) -> &'a T {
&**self
}
/// Obtain an unsafe reference to the wrapped JS owned-value that can
/// outlive the lifetime of this root.
///
/// DO NOT CALL.
pub fn get_unsound_ref_forever<'b>(&self) -> JSRef<'b, T> {
JSRef {
ptr: self.ptr,
chain: PhantomData,
}
/// Don't use this. Don't make me find you.
pub fn get_unsound_ref_forever<'a, 'b>(&'a self) -> &'b T {
unsafe { &**self.ptr }
}
/// Generate a new root from a JS<T> reference
#[allow(unrooted_must_root)]
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> {
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::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_DefinePropertyById, JS_NewObjectWithGivenProto};
use js::jsapi::{JS_ReportErrorFlagsAndNumber, JS_StrictPropertyStub};
use js::jsapi::{JSREPORT_WARNING, JSREPORT_STRICT, JSREPORT_STRICT_MODE_ERROR};
use js::jsapi::{JS_DefinePropertyById6, JS_NewObjectWithGivenProto};
use js::jsapi::{JS_StrictPropertyStub, JSErrNum};
use js::jsapi::{Handle, HandleObject, HandleId, MutableHandle, RootedObject, ObjectOpResult};
use js::jsapi::AutoIdVector;
use js::jsapi::GetObjectProto;
use js::jsval::ObjectValue;
use js::glue::GetProxyExtra;
use js::glue::{GetObjectProto, GetObjectParent, SetProxyExtra, GetProxyHandler};
use js::glue::{SetProxyExtra, GetProxyHandler};
use js::glue::InvokeGetOwnPropertyDescriptor;
use js::glue::RUST_js_GetErrorMessage;
use js::glue::AutoIdVector;
use js::{JSPROP_GETTER, JSPROP_ENUMERATE, JSPROP_READONLY, JSRESOLVE_QUALIFIED};
use js::{JSPROP_GETTER, JSPROP_ENUMERATE, JSPROP_READONLY};
use js::{JSTrue, JSFalse};
use libc;
use std::mem;
@ -32,60 +33,78 @@ static JSPROXYSLOT_EXPANDO: u32 = 0;
/// Otherwise, walk along the prototype chain to find a property with that
/// name.
pub unsafe extern fn get_property_descriptor(cx: *mut JSContext,
proxy: *mut JSObject,
id: jsid, set: bool,
desc: *mut JSPropertyDescriptor)
-> bool {
let handler = GetProxyHandler(proxy);
if !InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, set, desc) {
return false;
proxy: HandleObject,
id: HandleId,
desc: MutableHandle<JSPropertyDescriptor>)
-> u8 {
let handler = GetProxyHandler(proxy.get());
if InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) == 0 {
return JSFalse;
}
if !(*desc).obj.is_null() {
return true;
if !desc.get().obj.is_null() {
return JSTrue;
}
//let proto = JS_GetPrototype(proxy);
let proto = GetObjectProto(proxy);
if proto.is_null() {
(*desc).obj = ptr::null_mut();
return true;
let mut proto = RootedObject::new(cx, ptr::null_mut());
if GetObjectProto(cx, proxy, proto.handle_mut()) == 0 {
desc.get().obj = ptr::null_mut();
return JSTrue;
}
JS_GetPropertyDescriptorById(cx, proto, id, JSRESOLVE_QUALIFIED, desc) != 0
JS_GetPropertyDescriptorById(cx, proto.handle(), id, desc)
}
/// Defines an expando on the given `proxy`.
pub unsafe extern fn define_property(cx: *mut JSContext, proxy: *mut JSObject,
id: jsid, desc: *mut JSPropertyDescriptor)
-> bool {
static JSMSG_GETTER_ONLY: libc::c_uint = 160;
pub unsafe extern fn define_property(cx: *mut JSContext, proxy: HandleObject,
id: HandleId, desc: Handle<JSPropertyDescriptor>,
result: *mut ObjectOpResult)
-> u8 {
//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);
if ((*desc).attrs & JSPROP_GETTER) != 0 && setter == setter_stub {
return JS_ReportErrorFlagsAndNumber(cx,
JSREPORT_WARNING | JSREPORT_STRICT |
JSREPORT_STRICT_MODE_ERROR,
Some(RUST_js_GetErrorMessage), ptr::null_mut(),
JSMSG_GETTER_ONLY) != 0;
if (desc.get().attrs & JSPROP_GETTER) != 0 && setter == setter_stub {
(*result).code_ = JSErrNum::JSMSG_GETTER_ONLY as u32;
return JSTrue;
}
let expando = ensure_expando_object(cx, proxy);
return JS_DefinePropertyById(cx, expando, id, (*desc).value, (*desc).getter,
(*desc).setter, (*desc).attrs) != 0;
let expando = RootedObject::new(cx, ensure_expando_object(cx, proxy));
JS_DefinePropertyById6(cx, expando.handle(), id, desc, result)
}
/// Deletes an expando off the given `proxy`.
pub unsafe extern fn delete(cx: *mut JSContext, proxy: *mut JSObject, id: jsid,
bp: *mut bool) -> bool {
let expando = get_expando_object(proxy);
if expando.is_null() {
*bp = true;
return true;
pub unsafe extern fn delete(cx: *mut JSContext, proxy: HandleObject, id: HandleId,
bp: *mut ObjectOpResult) -> u8 {
let expando = RootedObject::new(cx, get_expando_object(proxy));
if expando.ptr.is_null() {
(*bp).code_ = 0 /* OkCode */;
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`.
@ -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.
pub fn get_expando_object(obj: *mut JSObject) -> *mut JSObject {
pub fn get_expando_object(obj: HandleObject) -> *mut JSObject {
unsafe {
assert!(is_dom_proxy(obj));
let val = GetProxyExtra(obj, JSPROXYSLOT_EXPANDO);
assert!(is_dom_proxy(obj.get()));
let val = GetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO);
if val.is_undefined() {
ptr::null_mut()
} 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.
/// 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 {
unsafe {
assert!(is_dom_proxy(obj));
assert!(is_dom_proxy(obj.get()));
let mut expando = get_expando_object(obj);
if expando.is_null() {
expando = JS_NewObjectWithGivenProto(cx, ptr::null_mut(),
ptr::null_mut(),
GetObjectParent(obj));
expando = JS_NewObjectWithGivenProto(cx, ptr::null_mut(), HandleObject::null());
assert!(!expando.is_null());
SetProxyExtra(obj, JSPROXYSLOT_EXPANDO, ObjectValue(&*expando));
SetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO, ObjectValue(&*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.getter = 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 removed.
use dom::bindings::js::{Temporary, JSRef, Unrooted};
use dom::bindings::js::Root;
use dom::bindings::utils::{Reflector, Reflectable};
use dom::bindings::trace::trace_reflector;
use script_task::{ScriptMsg, ScriptChan};
use js::jsapi::{JS_AddObjectRoot, JS_RemoveObjectRoot, JSContext};
use js::jsapi::{JSContext, JSTracer};
use libc;
use std::cell::RefCell;
@ -35,6 +36,7 @@ use std::collections::hash_map::Entry::{Vacant, Occupied};
use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use core::nonzero::NonZero;
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
/// be prevented from being GCed for the duration of the resulting `Trusted<T>` object's
/// 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| {
let r = r.borrow();
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
/// a different thread than the original value from which this `Trusted<T>` was
/// obtained.
pub fn to_temporary(&self) -> Temporary<T> {
pub fn root(&self) -> Root<T> {
assert!(LIVE_REFERENCES.with(|ref r| {
let r = r.borrow();
let live_references = r.as_ref().unwrap();
self.owner_thread == (&*live_references) as *const _ as *const libc::c_void
}));
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()
}
Vacant(entry) => {
unsafe {
let rootable = (*ptr).reflector().rootable();
JS_AddObjectRoot(cx, rootable);
}
let refcount = Arc::new(Mutex::new(1));
entry.insert(refcount.clone());
refcount
@ -168,7 +166,6 @@ impl LiveDOMReferences {
LIVE_REFERENCES.with(|ref r| {
let r = r.borrow();
let live_references = r.as_ref().unwrap();
let reflectable = raw_reflectable as *const Reflector;
let mut table = live_references.table.borrow_mut();
match table.entry(raw_reflectable) {
Occupied(entry) => {
@ -178,9 +175,6 @@ impl LiveDOMReferences {
return;
}
unsafe {
JS_RemoveObjectRoot(cx, (*reflectable).rootable());
}
let _ = entry.remove();
}
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::{JS_WriteStructuredClone, JS_ClearPendingException};
use js::jsapi::JS_ReadStructuredClone;
use js::jsval::{JSVal, UndefinedValue};
use js::jsapi::{HandleValue, MutableHandleValue};
use libc::size_t;
use std::ptr;
@ -26,13 +26,14 @@ pub struct StructuredCloneData {
impl StructuredCloneData {
/// 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> {
let mut data = ptr::null_mut();
let mut nbytes = 0;
let result = unsafe {
JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes,
ptr::null(), ptr::null_mut())
ptr::null(), ptr::null_mut(),
HandleValue::undefined())
};
if result == 0 {
unsafe { JS_ClearPendingException(cx); }
@ -47,15 +48,13 @@ impl StructuredCloneData {
/// Reads a structured clone.
///
/// Panics if `JS_ReadStructuredClone` fails.
pub fn read(self, global: GlobalRef) -> JSVal {
let mut message = UndefinedValue();
pub fn read(self, global: GlobalRef, rval: MutableHandleValue) {
unsafe {
assert!(JS_ReadStructuredClone(
global.get_cx(), self.data as *const u64, self.nbytes,
JS_STRUCTURED_CLONE_VERSION, &mut message,
global.get_cx(), self.data, self.nbytes,
JS_STRUCTURED_CLONE_VERSION, rval,
ptr::null(), ptr::null_mut()) != 0);
}
message
}
}

View file

@ -44,7 +44,8 @@ use euclid::size::Size2D;
use html5ever::tree_builder::QuirksMode;
use hyper::header::Headers;
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::rust::Runtime;
use layout_interface::{LayoutRPC, LayoutChan};
@ -59,7 +60,7 @@ use msg::compositor_msg::ScriptListener;
use msg::constellation_msg::ConstellationChan;
use net_traits::image::base::Image;
use util::str::{LengthOrPercentageOrAuto};
use std::cell::{Cell, RefCell};
use std::cell::{Cell, UnsafeCell, RefCell};
use std::collections::{HashMap, HashSet};
use std::collections::hash_state::HashState;
use std::ffi::CString;
@ -91,36 +92,46 @@ no_jsmanaged_fields!(EncodingRef);
no_jsmanaged_fields!(Reflector);
/// Trace a `JSVal`.
pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: JSVal) {
if !val.is_markable() {
return;
}
pub fn trace_jsval(tracer: *mut JSTracer, description: &str, val: &Heap<JSVal>) {
unsafe {
if !val.get().is_markable() {
return;
}
let name = CString::new(description).unwrap();
(*tracer).debugPrinter = None;
(*tracer).debugPrintIndex = !0;
(*tracer).debugPrintArg = name.as_ptr() as *const libc::c_void;
(*tracer).debugPrinter_ = None;
(*tracer).debugPrintIndex_ = !0;
(*tracer).debugPrintArg_ = name.as_ptr() as *const libc::c_void;
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`.
#[allow(unrooted_must_root)]
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`.
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 {
let name = CString::new(description).unwrap();
(*tracer).debugPrinter = None;
(*tracer).debugPrintIndex = !0;
(*tracer).debugPrintArg = name.as_ptr() as *const libc::c_void;
(*tracer).debugPrinter_ = None;
(*tracer).debugPrintIndex_ = !0;
(*tracer).debugPrintArg_ = name.as_ptr() as *const libc::c_void;
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) {
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) {
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
pub struct RootedCollectionSet {
set: Vec<HashSet<*const RootedVec<Void>>>
/// Homemade trait object for JSTraceable things
struct TraceableInfo {
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
thread_local!(pub static ROOTED_COLLECTIONS: Rc<RefCell<RootedCollectionSet>> =
Rc::new(RefCell::new(RootedCollectionSet::new())));
/// Type of `RootedVec`
pub enum CollectionType {
/// DOM objects
DOMObjects,
/// `JSVal`s
JSVals,
/// `*mut JSObject`s
JSObjects,
/// Holds a set of JSTraceables that need to be rooted
pub struct RootedTraceableSet {
set: Vec<TraceableInfo>
}
/// 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 {
fn new() -> RootedCollectionSet {
RootedCollectionSet {
set: vec!(HashSet::new(), HashSet::new(), HashSet::new())
impl RootedTraceableSet {
fn new() -> RootedTraceableSet {
RootedTraceableSet {
set: vec!()
}
}
fn remove<T: VecRootableType>(collection: &RootedVec<T>) {
ROOTED_COLLECTIONS.with(|ref collections| {
let type_ = VecRootableType::tag(None::<T>);
let mut collections = collections.borrow_mut();
assert!(collections.set[type_ as usize].remove(&(collection as *const _ as *const _)));
fn remove<T: JSTraceable>(traceable: &T) {
ROOTED_TRACEABLES.with(|ref traceables| {
let mut traceables = traceables.borrow_mut();
let idx =
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>) {
ROOTED_COLLECTIONS.with(|ref collections| {
let type_ = VecRootableType::tag(None::<T>);
let mut collections = collections.borrow_mut();
collections.set[type_ as usize].insert(collection as *const _ as *const _);
fn add<T: JSTraceable>(traceable: &T) {
ROOTED_TRACEABLES.with(|ref traceables| {
fn trace<T: JSTraceable>(obj: *const libc::c_void, tracer: *mut JSTracer) {
let obj: &T = unsafe { &*(obj as *const T) };
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) {
fn trace_collection_type<T>(tracer: *mut JSTracer,
collections: &HashSet<*const RootedVec<Void>>)
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);
}
}
for info in self.set.iter() {
(info.trace)(info.ptr, 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]);
}
}
/// Trait implemented by all types that can be used with RootedVec
pub trait VecRootableType {
/// Return the type tag used to determine how to trace RootedVec
fn tag(_a: Option<Self>) -> CollectionType;
/// Roots any JSTraceable thing
///
/// If you have a valid Reflectable, use Root.
/// If you have GC things like *mut JSObject or JSVal, use jsapi::Rooted.
/// 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> {
fn tag(_a: Option<JS<T>>) -> CollectionType { CollectionType::DOMObjects }
impl<'a, T: JSTraceable> RootedTraceable<'a, T> {
/// 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 {
fn tag(_a: Option<JSVal>) -> CollectionType { CollectionType::JSVals }
}
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!() }
impl<'a, T: JSTraceable> Drop for RootedTraceable<'a, T> {
fn drop(&mut self) {
RootedTraceableSet::remove(self.ptr);
}
}
/// A vector of items that are rooted for the lifetime
/// of this struct
/// of this struct.
/// Must be a reflectable
#[allow(unrooted_must_root)]
#[no_move]
pub struct RootedVec<T: VecRootableType> {
#[jstraceable]
pub struct RootedVec<T: JSTraceable + Reflectable> {
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
/// the lifetime of this struct
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
/// for RootCollection.
/// for RootTraceableSet.
pub fn new_with_destination_address(addr: *const libc::c_void) -> RootedVec<T> {
unsafe {
RootedCollectionSet::add::<T>(&*(addr as *const _));
RootedTraceableSet::add::<RootedVec<T>>(&*(addr as *const _));
}
RootedVec::<T> { v: vec!() }
}
}
impl<T: VecRootableType> Drop for RootedVec<T> {
impl<T: JSTraceable + Reflectable> Drop for RootedVec<T> {
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>;
fn deref(&self) -> &Vec<T> {
&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> {
&mut self.v
}
}
/// SM Callback that traces the rooted collections
pub unsafe fn trace_collections(tracer: *mut JSTracer) {
ROOTED_COLLECTIONS.with(|ref collections| {
let collections = collections.borrow();
collections.trace(tracer);
/// SM Callback that traces the rooted traceables
pub unsafe fn trace_traceables(tracer: *mut JSTracer) {
ROOTED_TRACEABLES.with(|ref traceables| {
let traceables = traceables.borrow();
traceables.trace(tracer);
});
}

View file

@ -6,10 +6,10 @@
use dom::bindings::codegen::PrototypeList;
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::global::GlobalRef;
use dom::bindings::js::{Temporary, Root, Rootable};
use dom::bindings::js::Root;
use dom::bindings::trace::trace_object;
use dom::browsercontext;
use dom::window;
@ -19,30 +19,39 @@ use util::str::DOMString;
use libc;
use libc::c_uint;
use std::boxed;
use std::cell::Cell;
use std::ffi::CString;
use std::ptr;
use std::cmp::PartialEq;
use std::default::Default;
use std::cell::UnsafeCell;
use js::glue::UnwrapObject;
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_GetClass, JS_LinkConstructorAndPrototype, JS_GetStringCharsAndLength};
use js::jsapi::{JSHandleObject, JSTracer};
use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype};
use js::jsapi::{HandleObject, HandleId, HandleValue, MutableHandleValue};
use js::jsapi::JS_GetFunctionObject;
use js::jsapi::{JS_HasPropertyById, JS_GetPrototype};
use js::jsapi::{JS_GetProperty, JS_HasProperty, JS_SetProperty};
use js::jsapi::{JS_DefineFunctions, JS_DefineProperty};
use js::jsapi::{JS_ValueToString, JS_GetReservedSlot, JS_SetReservedSlot};
use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass};
use js::jsapi::{JS_DefineFunctions, JS_DefineProperty, JS_DefineProperty1};
use js::jsapi::{JS_GetReservedSlot, JS_SetReservedSlot};
use js::jsapi::{JSContext, JSObject, JSClass, JSTracer};
use js::jsapi::{JSFunctionSpec, JSPropertySpec};
use js::jsapi::{JS_NewGlobalObject, JS_InitStandardClasses};
use js::jsapi::JS_DeletePropertyById2;
use js::jsfriendapi::JS_ObjectToOuterObject;
use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType;
use js::jsapi::{OnNewGlobalHookOption, CompartmentOptions};
use js::jsapi::{JS_FireOnNewGlobalObject, JSVersion};
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::{PrivateValue, ObjectValue, NullValue};
use js::jsval::{Int32Value, UInt32Value, DoubleValue, BooleanValue, UndefinedValue};
use js::rust::with_compartment;
use js::jsval::{PrivateValue, NullValue};
use js::jsval::{Int32Value, UInt32Value, DoubleValue, BooleanValue};
use js::rust::{GCMethods, ToString};
use js::glue::{WrapperNew, GetCrossCompartmentWrapper};
use js::{JSPROP_ENUMERATE, JSPROP_READONLY, JSPROP_PERMANENT};
use js::JSFUN_CONSTRUCTOR;
use js;
@ -145,7 +154,7 @@ unsafe impl Sync for DOMClass {}
#[derive(Copy)]
pub struct DOMJSClass {
/// The actual JSClass.
pub base: js::Class,
pub base: js::jsapi::Class,
/// Associated data for DOM object reflectors.
pub dom_class: DOMClass
}
@ -181,95 +190,93 @@ unsafe impl Sync for NativeProperties {}
/// A JSNative that cannot be null.
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)
/// and the *interface object* (if a `constructor` is given).
/// Fails on JSAPI failure.
pub fn do_create_interface_objects(cx: *mut JSContext, global: *mut JSObject,
receiver: *mut JSObject,
proto_proto: *mut JSObject,
pub fn do_create_interface_objects(cx: *mut JSContext,
receiver: HandleObject,
proto_proto: HandleObject,
proto_class: Option<&'static JSClass>,
constructor: Option<(NonNullJSNative, &'static str, u32)>,
dom_class: *const DOMClass,
members: &'static NativeProperties)
-> *mut JSObject {
members: &'static NativeProperties,
rval: MutableHandleObject) {
if let Some(proto_class) = proto_class {
create_interface_prototype_object(cx, proto_proto,
proto_class, members, rval);
}
unsafe {
let proto = match proto_class {
Some(proto_class) => {
let proto = create_interface_prototype_object(cx, global, proto_proto,
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())
if !rval.get().is_null() {
JS_SetReservedSlot(rval.get(), DOM_PROTO_INSTANCE_CLASS_SLOT,
PrivateValue(dom_class as *const libc::c_void));
}
}
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*.
/// Fails on JSAPI failure.
fn create_interface_object(cx: *mut JSContext, global: *mut JSObject,
receiver: *mut JSObject,
fn create_interface_object(cx: *mut JSContext,
receiver: HandleObject,
constructor_native: NonNullJSNative,
ctor_nargs: u32, proto: *mut JSObject,
ctor_nargs: u32, proto: HandleObject,
members: &'static NativeProperties,
name: *const libc::c_char) {
unsafe {
let fun = JS_NewFunction(cx, Some(constructor_native), ctor_nargs,
JSFUN_CONSTRUCTOR, global, name);
JSFUN_CONSTRUCTOR, name);
assert!(!fun.is_null());
let constructor = JS_GetFunctionObject(fun);
assert!(!constructor.is_null());
let constructor = RootedObject::new(cx, JS_GetFunctionObject(fun));
assert!(!constructor.ptr.is_null());
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 {
define_properties(cx, constructor, static_properties);
define_properties(cx, constructor.handle(), static_properties);
}
if let Some(constants) = members.consts {
define_constants(cx, constructor, constants);
define_constants(cx, constructor.handle(), constants);
}
if !proto.is_null() {
assert!(JS_LinkConstructorAndPrototype(cx, constructor, proto) != 0);
if !proto.get().is_null() {
assert!(JS_LinkConstructorAndPrototype(cx, constructor.handle(), proto) != 0);
}
let mut already_defined = 0;
assert!(JS_AlreadyHasOwnProperty(cx, receiver, name, &mut already_defined) != 0);
if already_defined == 0 {
assert!(JS_DefineProperty(cx, receiver, name,
ObjectValue(&*constructor),
None, None, 0) != 0);
assert!(JS_DefineProperty1(cx, receiver, name,
constructor.handle(),
0, None, None) != 0);
}
}
}
/// Defines constants on `obj`.
/// Fails on JSAPI failure.
fn define_constants(cx: *mut JSContext, obj: *mut JSObject,
fn define_constants(cx: *mut JSContext, obj: HandleObject,
constants: &'static [ConstantSpec]) {
for spec in constants.iter() {
let value = RootedValue::new(cx, spec.get_value());
unsafe {
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_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
/// memory.
/// Fails on JSAPI failure.
fn define_methods(cx: *mut JSContext, obj: *mut JSObject,
fn define_methods(cx: *mut JSContext, obj: HandleObject,
methods: &'static [JSFunctionSpec]) {
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
/// zeroed memory.
/// Fails on JSAPI failure.
fn define_properties(cx: *mut JSContext, obj: *mut JSObject,
fn define_properties(cx: *mut JSContext, obj: HandleObject,
properties: &'static [JSPropertySpec]) {
unsafe {
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*.
/// Fails on JSAPI failure.
fn create_interface_prototype_object(cx: *mut JSContext, global: *mut JSObject,
parent_proto: *mut JSObject,
fn create_interface_prototype_object(cx: *mut JSContext, global: HandleObject,
proto_class: &'static JSClass,
members: &'static NativeProperties)
-> *mut JSObject {
members: &'static NativeProperties,
rval: MutableHandleObject) {
unsafe {
let our_proto = JS_NewObjectWithUniqueType(cx, proto_class,
&*parent_proto, &*global);
assert!(!our_proto.is_null());
rval.set(JS_NewObjectWithUniqueType(cx, proto_class, global));
assert!(!rval.get().is_null());
if let Some(methods) = members.methods {
define_methods(cx, our_proto, methods);
define_methods(cx, rval.handle(), methods);
}
if let Some(properties) = members.attrs {
define_properties(cx, our_proto, properties);
define_properties(cx, rval.handle(), properties);
}
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
/// `NoInterfaceObject` nor `Constructor`.
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.");
return 0;
}
@ -351,6 +354,10 @@ pub fn initialize_global(global: *mut JSObject) {
pub trait Reflectable {
/// Returns the receiver's 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
@ -358,47 +365,56 @@ pub trait Reflectable {
pub fn reflect_dom_object<T: Reflectable>
(obj: Box<T>,
global: GlobalRef,
wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<T>) -> Temporary<T>)
-> Temporary<T> {
wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<T>) -> Root<T>)
-> Root<T> {
wrap_fn(global.get_cx(), global, obj)
}
/// 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
#[allow(raw_pointer_derive, unrooted_must_root, unused_attributes)]
#[derive(PartialEq)]
#[must_root]
#[servo_lang = "reflector"]
// If you're renaming or moving this field, update the path in plugins::reflector as well
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 {
/// Get the reflector.
#[inline]
pub fn get_jsobject(&self) -> *mut JSObject {
self.object.get()
pub fn get_jsobject(&self) -> HandleObject {
HandleObject { ptr: self.object.get() }
}
/// Initialize the reflector. (May be called only once.)
pub fn set_jsobject(&self, object: *mut JSObject) {
assert!(self.object.get().is_null());
assert!(!object.is_null());
self.object.set(object);
pub fn set_jsobject(&mut self, object: *mut JSObject) {
unsafe {
let obj = self.object.get();
assert!((*obj).is_null());
assert!(!object.is_null());
*obj = object;
}
}
/// 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.
pub unsafe fn rootable(&self) -> *mut *mut JSObject {
self.object.as_unsafe_cell().get()
pub fn rootable(&self) -> *mut *mut JSObject {
self.object.get()
}
/// Create an uninitialized `Reflector`.
pub fn new() -> 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.
///
/// Returns false on JSAPI failure.
pub fn get_property_on_prototype(cx: *mut JSContext, proxy: *mut JSObject,
id: jsid, found: *mut bool, vp: *mut JSVal)
pub fn get_property_on_prototype(cx: *mut JSContext, proxy: HandleObject,
id: HandleId, found: *mut bool, vp: MutableHandleValue)
-> bool {
unsafe {
//let proto = GetObjectProto(proxy);
let proto = JS_GetPrototype(proxy);
if proto.is_null() {
let mut proto = RootedObject::new(cx, ptr::null_mut());
if JS_GetPrototype(cx, proxy, proto.handle_mut()) == 0 ||
proto.ptr.is_null() {
*found = false;
return true;
}
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;
}
*found = has_property != 0;
let no_output = vp.is_null();
let no_output = vp.ptr.is_null();
if has_property == 0 || no_output {
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
/// `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 {
if RUST_JSID_IS_INT(id) != 0 {
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
/// `Ok(None)` if there was no matching string.
pub fn find_enum_string_index(cx: *mut JSContext,
v: JSVal,
v: HandleValue,
values: &[&'static str])
-> Result<Option<usize>, ()> {
unsafe {
let jsstr = JS_ValueToString(cx, v);
if jsstr.is_null() {
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 jsstr = ToString(cx, v);
if jsstr.is_null() {
return Err(());
}
let search = jsstring_to_str(cx, jsstr);
Ok(values.iter().position(|value| value == &search))
}
/// 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
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() {
return false;
}
@ -508,53 +513,54 @@ pub fn is_platform_object(obj: *mut JSObject) -> bool {
/// Get the property with name `property` from `object`.
/// 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,
object: *mut JSObject,
property: &str) -> Result<Option<JSVal>, ()> {
fn has_property(cx: *mut JSContext, object: *mut JSObject, property: &CString,
found: &mut JSBool) -> bool {
object: HandleObject,
property: &str,
rval: MutableHandleValue)
-> Result<bool, ()> {
fn has_property(cx: *mut JSContext, object: HandleObject, property: &CString,
found: &mut u8) -> bool {
unsafe {
JS_HasProperty(cx, object, property.as_ptr(), found) != 0
}
}
fn get_property(cx: *mut JSContext, object: *mut JSObject, property: &CString,
value: &mut JSVal) -> bool {
fn get_property(cx: *mut JSContext, object: HandleObject, property: &CString,
value: MutableHandleValue) -> bool {
unsafe {
JS_GetProperty(cx, object, property.as_ptr(), value) != 0
}
}
let property = CString::new(property).unwrap();
if object.is_null() {
return Ok(None);
if object.get().is_null() {
return Ok(false);
}
let mut found: JSBool = 0;
let mut found: u8 = 0;
if !has_property(cx, object, &property, &mut found) {
return Err(());
}
if found == 0 {
return Ok(None);
return Ok(false);
}
let mut value = NullValue();
if !get_property(cx, object, &property, &mut value) {
if !get_property(cx, object, &property, rval) {
return Err(());
}
Ok(Some(value))
Ok(true)
}
/// Set the property with name `property` from `object`.
/// Returns `Err(())` on JSAPI failure, or null object,
/// and Ok(()) otherwise
pub fn set_dictionary_property(cx: *mut JSContext,
object: *mut JSObject,
object: HandleObject,
property: &str,
value: &mut JSVal) -> Result<(), ()> {
if object.is_null() {
value: HandleValue) -> Result<(), ()> {
if object.get().is_null() {
return Err(());
}
@ -569,79 +575,99 @@ pub fn set_dictionary_property(cx: *mut JSContext,
}
/// Returns whether `proxy` has a property `id` on its prototype.
pub fn has_property_on_prototype(cx: *mut JSContext, proxy: *mut JSObject,
id: jsid) -> bool {
pub fn has_property_on_prototype(cx: *mut JSContext, proxy: HandleObject,
id: HandleId) -> bool {
// MOZ_ASSERT(js::IsProxy(proxy) && js::GetProxyHandler(proxy) == handler);
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.
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 {
unsafe {
let obj = JS_NewGlobalObject(cx, class, ptr::null_mut());
if obj.is_null() {
let mut options = CompartmentOptions::default();
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();
}
with_compartment(cx, obj, || {
JS_InitStandardClasses(cx, obj);
});
initialize_global(obj);
obj
let _ac = JSAutoCompartment::new(cx, obj.ptr);
JS_InitStandardClasses(cx, obj.handle());
initialize_global(obj.ptr);
JS_FireOnNewGlobalObject(cx, obj.handle());
obj.ptr
}
}
/// Drop the resources held by reserved slots of a global object
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> =
Box::from_raw(get_proto_or_iface_array(obj));
Box::from_raw(protolist);
}
/// Trace the resources held by reserved slots of a global object
pub unsafe fn trace_global(tracer: *mut JSTracer, obj: *mut JSObject) {
let array = get_proto_or_iface_array(obj);
for &proto in (*array).iter() {
for proto in (&*array).iter() {
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.
pub unsafe extern fn wrap_for_same_compartment(cx: *mut JSContext, obj: *mut JSObject) -> *mut JSObject {
unsafe extern fn wrap(cx: *mut JSContext,
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)
}
/// Callback to outerize windows before wrapping.
pub unsafe extern fn pre_wrap(cx: *mut JSContext, _scope: *mut JSObject,
obj: *mut JSObject, _flags: c_uint) -> *mut JSObject {
JS_ObjectToOuterObject(cx, obj)
}
/// Callback table for use with JS_SetWrapObjectCallbacks
pub static WRAP_CALLBACKS: JSWrapObjectCallbacks = JSWrapObjectCallbacks {
wrap: Some(wrap),
preWrap: Some(pre_wrap),
};
/// Callback to outerize windows.
pub extern fn outerize_global(_cx: *mut JSContext, obj: JSHandleObject) -> *mut JSObject {
unsafe {
debug!("outerizing");
let obj = *obj.unnamed_field1;
let win: Root<window::Window> = native_from_reflector_jsmanaged(obj).unwrap().root();
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let win = win.r();
let context = win.browser_context();
context.as_ref().unwrap().window_proxy()
}
pub unsafe extern fn outerize_global(_cx: *mut JSContext, obj: HandleObject) -> *mut JSObject {
debug!("outerizing");
let win: Root<window::Window> = native_from_handleobject(obj).unwrap();
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let win = win.r();
let context = win.browser_context();
context.as_ref().unwrap().window_proxy()
}
/// Deletes the property `id` from `object`.
pub unsafe fn delete_property_by_id(cx: *mut JSContext, object: *mut JSObject,
id: jsid, bp: &mut bool) -> bool {
let mut value = UndefinedValue();
if JS_DeletePropertyById2(cx, object, id, &mut value) == 0 {
return false;
}
*bp = value.to_boolean();
return true;
pub unsafe fn delete_property_by_id(cx: *mut JSContext, object: HandleObject,
id: HandleId, bp: *mut ObjectOpResult) -> u8 {
JS_DeletePropertyById1(cx, object, id, bp)
}
/// 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.
/// See https://dom.spec.whatwg.org/#validate-and-extract for details.
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::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::error::Fallible;
use dom::bindings::codegen::Bindings::BlobBinding;
@ -54,20 +54,20 @@ impl Blob {
}
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),
global,
BlobBinding::Wrap)
}
// 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, ""))
}
// http://dev.w3.org/2006/webapi/FileAPI/#constructorBlob
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
let bytes: Option<Vec<u8>> = Some(blobParts.into_bytes());
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
fn Size(self) -> u64{
match self.bytes {
@ -95,7 +95,7 @@ impl<'a> BlobMethods for JSRef<'a, Blob> {
// http://dev.w3.org/2006/webapi/FileAPI/#slice-method-algo
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 relativeStart: i64 = match start {
None => 0,

View file

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

View file

@ -5,7 +5,7 @@
use canvas_traits::{FillOrStrokeStyle, SurfaceStyle, RepetitionStyle};
use dom::bindings::codegen::Bindings::CanvasPatternBinding;
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::canvasgradient::ToFillOrStrokeStyle;
use euclid::size::Size2D;
@ -41,14 +41,14 @@ impl CanvasPattern {
surface_data: Vec<u8>,
surface_size: Size2D<i32>,
repeat: RepetitionStyle)
-> Temporary<CanvasPattern> {
-> Root<CanvasPattern> {
reflect_dom_object(box CanvasPattern::new_inherited(surface_data, surface_size, repeat),
global, CanvasPatternBinding::Wrap)
}
}
impl<'a> ToFillOrStrokeStyle for JSRef<'a, CanvasPattern> {
fn to_fill_or_stroke_style(&self) -> FillOrStrokeStyle {
impl<'a> ToFillOrStrokeStyle for &'a CanvasPattern {
fn to_fill_or_stroke_style(self) -> FillOrStrokeStyle {
FillOrStrokeStyle::Surface(
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::Fallible;
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::utils::{Reflector, reflect_dom_object};
use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle};
@ -115,20 +115,20 @@ impl CanvasContextState {
}
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 {
reflector_: Reflector::new(),
global: GlobalField::from_rooted(&global),
renderer: CanvasPaintTask::start(size),
canvas: JS::from_rooted(canvas),
canvas: JS::from_ref(canvas),
state: RefCell::new(CanvasContextState::new()),
saved_states: RefCell::new(Vec::new()),
}
}
pub fn new(global: GlobalRef, canvas: JSRef<HTMLCanvasElement>, size: Size2D<i32>)
-> Temporary<CanvasRenderingContext2D> {
pub fn new(global: GlobalRef, canvas: &HTMLCanvasElement, size: Size2D<i32>)
-> Root<CanvasRenderingContext2D> {
reflect_dom_object(box CanvasRenderingContext2D::new_inherited(global, canvas, size),
global, CanvasRenderingContext2DBinding::Wrap)
}
@ -211,7 +211,7 @@ impl CanvasRenderingContext2D {
//
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn draw_html_canvas_element(&self,
canvas: JSRef<HTMLCanvasElement>,
canvas: &HTMLCanvasElement,
sx: f64, sy: f64, sw: f64, sh: f64,
dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> {
// 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))
} else { // Source and target canvases are different
let context = match canvas.get_or_init_2d_context() {
Some(context) => context.root(),
Some(context) => context,
None => return Err(InvalidState),
};
@ -275,7 +275,7 @@ impl CanvasRenderingContext2D {
}
fn fetch_image_data(&self,
image_element: &JSRef<HTMLImageElement>)
image_element: &&HTMLImageElement)
-> Option<(Vec<u8>, Size2D<f64>)> {
let url = match image_element.get_url() {
Some(url) => url,
@ -302,7 +302,7 @@ impl CanvasRenderingContext2D {
fn request_image_from_cache(&self, url: Url) -> ImageResponse {
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 image_cache = window.image_cache_task();
let (response_chan, response_port) = channel();
@ -325,11 +325,11 @@ impl CanvasRenderingContext2D {
}
pub trait CanvasRenderingContext2DHelpers {
fn get_renderer(&self) -> Sender<CanvasMsg>;
fn get_renderer(self) -> Sender<CanvasMsg>;
}
impl CanvasRenderingContext2DHelpers for CanvasRenderingContext2D {
fn get_renderer(&self) -> Sender<CanvasMsg> {
impl<'a> CanvasRenderingContext2DHelpers for &'a CanvasRenderingContext2D {
fn get_renderer(self) -> Sender<CanvasMsg> {
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.
//
// 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
fn Canvas(self) -> Temporary<HTMLCanvasElement> {
Temporary::from_rooted(self.canvas)
fn Canvas(self) -> Root<HTMLCanvasElement> {
self.canvas.root()
}
// 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;
match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => {
let canvas = image.root();
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(canvas) => {
let canvas_size = canvas.r().get_size();
let dw: f64 = canvas_size.width 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)
}
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => {
let image = image.root();
let context = image.r();
let canvas = context.Canvas().root();
let canvas = context.Canvas();
let canvas_size = canvas.r().get_size();
let dw: f64 = canvas_size.width 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)
}
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image = image.root();
let image_element = image.r();
// https://html.spec.whatwg.org/multipage/#img-error
// 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;
match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => {
let canvas = image.root();
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(canvas) => {
let canvas_size = canvas.r().get_size();
let sw: f64 = canvas_size.width 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)
}
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => {
let image = image.root();
let context = image.r();
let canvas = context.Canvas().root();
let canvas = context.Canvas();
let canvas_size = canvas.r().get_size();
let sw: f64 = canvas_size.width 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)
}
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image = image.root();
let image_element = image.r();
// https://html.spec.whatwg.org/multipage/#img-error
// 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 {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLCanvasElement(image) => {
let canvas = image.root();
return self.draw_html_canvas_element(canvas.r(),
return self.draw_html_canvas_element(image.r(),
sx, sy, sw, sh,
dx, dy, dw, dh)
}
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eCanvasRenderingContext2D(image) => {
let image = image.root();
let context = image.r();
let canvas = context.Canvas().root();
let canvas = context.Canvas();
return self.draw_html_canvas_element(canvas.r(),
sx, sy, sw, sh,
dx, dy, dw, dh)
}
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image = image.root();
let image_element = image.r();
// https://html.spec.whatwg.org/multipage/#img-error
// 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)
},
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) => {
let gradient_root = gradient.root();
self.state.borrow_mut().stroke_style = CanvasFillOrStrokeStyle::Gradient(
JS::from_rooted(gradient_root.r()));
JS::from_ref(gradient.r()));
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();
},
_ => {}
@ -860,7 +850,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
StringOrCanvasGradientOrCanvasPattern::eString(result)
},
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) => {
let gradient_root = gradient.root();
self.state.borrow_mut().fill_style = CanvasFillOrStrokeStyle::Gradient(
JS::from_rooted(gradient_root.r()));
JS::from_rooted(&gradient));
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();
}
StringOrCanvasGradientOrCanvasPattern::eCanvasPattern(pattern) => {
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
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()) {
return Err(NotSupported);
}
@ -908,7 +897,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
}
// 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))
}
@ -917,7 +906,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
sx: Finite<f64>,
sy: Finite<f64>,
sw: Finite<f64>,
sh: Finite<f64>) -> Fallible<Temporary<ImageData>> {
sh: Finite<f64>) -> Fallible<Root<ImageData>> {
let sx = *sx;
let sy = *sy;
let sw = *sw;
@ -938,7 +927,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
}
// 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 dy = *dy;
@ -960,7 +949,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
}
// 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>) {
let dx = *dx;
let dy = *dy;
@ -989,7 +978,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient
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 y0 = *y0;
let x1 = *x1;
@ -1006,7 +995,7 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient
fn CreateRadialGradient(self, x0: Finite<f64>, y0: Finite<f64>, r0: Finite<f64>,
x1: Finite<f64>, y1: Finite<f64>, r1: Finite<f64>)
-> Fallible<Temporary<CanvasGradient>> {
-> Fallible<Root<CanvasGradient>> {
let x0 = *x0;
let y0 = *y0;
let r0 = *r0;
@ -1025,10 +1014,9 @@ impl<'a> CanvasRenderingContext2DMethods for JSRef<'a, CanvasRenderingContext2D>
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
fn CreatePattern(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
repetition: DOMString) -> Fallible<Temporary<CanvasPattern>> {
repetition: DOMString) -> Fallible<Root<CanvasPattern>> {
match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
let image = image.root();
let image_element = image.r();
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::error::{Fallible, ErrorResult};
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::element::Element;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -39,7 +39,7 @@ impl CharacterDataDerived for EventTarget {
}
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 {
node: Node::new_inherited(NodeTypeId::CharacterData(id), document),
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
fn Data(self) -> DOMString {
// 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
fn Remove(self) {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
node.remove_self();
}
// 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()
.filter_map(ElementCast::to_temporary).next()
.filter_map(ElementCast::to_root).next()
}
// 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()
.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>;
}
impl<'a> CharacterDataHelpers<'a> for JSRef<'a, CharacterData> {
impl<'a> CharacterDataHelpers<'a> for &'a CharacterData {
#[inline]
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::error::Fallible;
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::event::{Event, EventTypeId, EventBubbles, EventCancelable};
use script_task::ScriptChan;
@ -40,21 +40,23 @@ impl CloseEvent {
cancelable: EventCancelable,
wasClean: bool,
code: u16,
reason: DOMString) -> Temporary<CloseEvent> {
reason: DOMString) -> Root<CloseEvent> {
let event = box CloseEvent::new_inherited(EventTypeId::CloseEvent,
wasClean, code, reason);
let ev = reflect_dom_object(event, global, CloseEventBinding::Wrap).root();
let event: JSRef<Event> = EventCast::from_ref(ev.r());
event.InitEvent(type_,
bubbles == EventBubbles::Bubbles,
cancelable == EventCancelable::Cancelable);
Temporary::from_rooted(ev.r())
let ev = reflect_dom_object(event, global, CloseEventBinding::Wrap);
{
let event = EventCast::from_ref(ev.r());
event.InitEvent(type_,
bubbles == EventBubbles::Bubbles,
cancelable == EventCancelable::Cancelable);
}
ev
}
pub fn Constructor(global: GlobalRef,
type_: DOMString,
init: &CloseEventBinding::CloseEventInit)
-> Fallible<Temporary<CloseEvent>> {
-> Fallible<Root<CloseEvent>> {
let bubbles = if init.parent.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble };
let cancelable = if init.parent.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 {
self.wasClean
}

View file

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

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::ConsoleBinding;
use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
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::window::WindowHelpers;
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)
}
}
impl<'a> ConsoleMethods for JSRef<'a, Console> {
impl<'a> ConsoleMethods for &'a Console {
// https://developer.mozilla.org/en-US/docs/Web/API/Console/log
fn Log(self, messages: Vec<DOMString>) {
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();
match global.r() {
GlobalRef::Window(window_ref) => {

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::bindings::codegen::InheritTypes::ElementCast;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::Element;
use dom::element::ElementCreator;
@ -81,8 +81,8 @@ use string_cache::{Atom, QualName};
use std::borrow::ToOwned;
pub fn create_element(name: QualName, prefix: Option<Atom>,
document: JSRef<Document>, creator: ElementCreator)
-> Temporary<Element> {
document: &Document, creator: ElementCreator)
-> Root<Element> {
let prefix = prefix.map(|p| (*p).to_owned());
if name.ns != ns!(HTML) {
@ -92,11 +92,11 @@ pub fn create_element(name: QualName, prefix: Option<Atom>,
macro_rules! make(
($ctor:ident) => ({
let obj = $ctor::new((*name.local).to_owned(), prefix, document);
ElementCast::from_temporary(obj)
ElementCast::from_root(obj)
});
($ctor:ident, $($arg:expr),+) => ({
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::error::{Error, ErrorResult, Fallible};
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::document::DocumentHelpers;
use dom::element::{Element, ElementHelpers, StylePriority};
use dom::element::{ElementHelpers, StylePriority};
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 util::str::DOMString;
use string_cache::Atom;
@ -55,17 +55,17 @@ fn serialize_list(list: &Vec<PropertyDeclaration>) -> DOMString {
}
impl CSSStyleDeclaration {
pub fn new_inherited(owner: JSRef<HTMLElement>,
pub fn new_inherited(owner: &HTMLElement,
modification_access: CSSModificationAccess) -> CSSStyleDeclaration {
CSSStyleDeclaration {
reflector_: Reflector::new(),
owner: JS::from_rooted(owner),
owner: JS::from_ref(owner),
readonly: modification_access == CSSModificationAccess::Readonly,
}
}
pub fn new(global: JSRef<Window>, owner: JSRef<HTMLElement>,
modification_access: CSSModificationAccess) -> Temporary<CSSStyleDeclaration> {
pub fn new(global: &Window, owner: &HTMLElement,
modification_access: CSSModificationAccess) -> Root<CSSStyleDeclaration> {
reflect_dom_object(box CSSStyleDeclaration::new_inherited(owner, modification_access),
GlobalRef::Window(global),
CSSStyleDeclarationBinding::Wrap)
@ -77,25 +77,25 @@ trait PrivateCSSStyleDeclarationHelpers {
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> {
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())
}
fn get_important_declaration(self, property: &Atom) -> Option<PropertyDeclaration> {
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())
}
}
impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
// http://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length
fn Length(self) -> u32 {
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() {
Some(ref declarations) => declarations.normal.len() + declarations.important.len(),
None => 0
@ -107,7 +107,7 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
fn Item(self, index: u32) -> DOMString {
let index = index as usize;
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 result = style_attribute.as_ref().and_then(|declarations| {
if index > declarations.normal.len() {
@ -216,7 +216,7 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
synthesized_declaration.push_str(&value);
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());
// Step 7
@ -225,7 +225,7 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
}
let owner = self.owner.root();
let element: JSRef<Element> = ElementCast::from_ref(owner.r());
let element = ElementCast::from_ref(owner.r());
// Step 8
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);
}
let document = document_from_node(element).root();
let node: JSRef<Node> = NodeCast::from_ref(element);
let document = document_from_node(element);
let node = NodeCast::from_ref(element);
document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
Ok(())
}
@ -266,9 +266,9 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
}
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 element: JSRef<Element> = ElementCast::from_ref(owner.r());
let element = ElementCast::from_ref(owner.r());
// Step 5
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);
}
let document = document_from_node(element).root();
let node: JSRef<Node> = NodeCast::from_ref(element);
let document = document_from_node(element);
let node = NodeCast::from_ref(element);
document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
Ok(())
}
@ -317,7 +317,7 @@ impl<'a> CSSStyleDeclarationMethods for JSRef<'a, CSSStyleDeclaration> {
None => {
// Step 5
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)
}
}

View file

@ -8,18 +8,18 @@ use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventCast, CustomEventDerived};
use dom::bindings::error::Fallible;
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::event::{Event, EventTypeId};
use js::jsapi::JSContext;
use js::jsval::{JSVal, NullValue};
use js::jsapi::{JSContext, HandleValue};
use js::jsval::JSVal;
use util::str::DOMString;
// https://dom.spec.whatwg.org/#interface-customevent
#[dom_struct]
pub struct CustomEvent {
event: Event,
detail: MutHeap<JSVal>,
detail: MutHeapJSVal,
}
impl CustomEventDerived for Event {
@ -32,11 +32,11 @@ impl CustomEvent {
fn new_inherited(type_id: EventTypeId) -> CustomEvent {
CustomEvent {
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),
global,
CustomEventBinding::Wrap)
@ -45,19 +45,23 @@ impl CustomEvent {
type_: DOMString,
bubbles: bool,
cancelable: bool,
detail: JSVal) -> Temporary<CustomEvent> {
let ev = CustomEvent::new_uninitialized(global).root();
detail: HandleValue) -> Root<CustomEvent> {
let ev = CustomEvent::new_uninitialized(global);
ev.r().InitCustomEvent(global.get_cx(), type_, bubbles, cancelable, detail);
Temporary::from_rooted(ev.r())
ev
}
pub fn Constructor(global: GlobalRef,
type_: DOMString,
init: &CustomEventBinding::CustomEventInit) -> Fallible<Temporary<CustomEvent>>{
Ok(CustomEvent::new(global, type_, init.parent.bubbles, init.parent.cancelable, init.detail))
init: &CustomEventBinding::CustomEventInit) -> Fallible<Root<CustomEvent>>{
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
fn Detail(self, _cx: *mut JSContext) -> JSVal {
self.detail.get()
@ -69,13 +73,13 @@ impl<'a> CustomEventMethods for JSRef<'a, CustomEvent> {
type_: DOMString,
can_bubble: bool,
cancelable: bool,
detail: JSVal) {
let event: JSRef<Event> = EventCast::from_ref(self);
detail: HandleValue) {
let event = EventCast::from_ref(self);
if event.dispatching() {
return;
}
self.detail.set(detail);
self.detail.set(detail.get());
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::InheritTypes::DedicatedWorkerGlobalScopeDerived;
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::js::{JSRef, RootCollection, Rootable, Temporary};
use dom::bindings::js::{RootCollection, Root};
use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::utils::Reflectable;
@ -33,8 +33,9 @@ use util::task::spawn_named;
use util::task_state;
use util::task_state::{SCRIPT, IN_WORKER};
use js::jsapi::JSContext;
use js::jsval::JSVal;
use js::jsapi::{JSContext, RootedValue, HandleValue};
use js::jsapi::{JSAutoRequest, JSAutoCompartment};
use js::jsval::UndefinedValue;
use js::rust::Runtime;
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
/// providing a reference that can be cloned freely.
struct AutoWorkerReset<'a> {
workerscope: JSRef<'a, DedicatedWorkerGlobalScope>,
workerscope: &'a DedicatedWorkerGlobalScope,
old_worker: Option<TrustedWorkerAddress>,
}
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 {
workerscope: workerscope,
old_worker: workerscope.worker.borrow().clone()
@ -132,7 +133,7 @@ impl DedicatedWorkerGlobalScope {
parent_sender: Box<ScriptChan+Send>,
own_sender: Sender<(TrustedWorkerAddress, ScriptMsg)>,
receiver: Receiver<(TrustedWorkerAddress, ScriptMsg)>)
-> Temporary<DedicatedWorkerGlobalScope> {
-> Root<DedicatedWorkerGlobalScope> {
let scope = box DedicatedWorkerGlobalScope::new_inherited(
worker_url, id, devtools_chan, runtime.clone(), resource_task,
parent_sender, own_sender, receiver);
@ -170,7 +171,7 @@ impl DedicatedWorkerGlobalScope {
let runtime = Rc::new(ScriptTask::new_rt_and_cx());
let global = DedicatedWorkerGlobalScope::new(
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);
@ -178,7 +179,13 @@ impl DedicatedWorkerGlobalScope {
match runtime.evaluate_script(
global.r().reflector().get_jsobject(), source, url.serialize(), 1) {
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);
}
impl<'a> DedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalScope> {
impl<'a> DedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope {
fn script_chan(self) -> Box<ScriptChan+Send> {
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let worker = self.worker.borrow();
@ -232,34 +239,37 @@ impl<'a> DedicatedWorkerGlobalScopeHelpers for JSRef<'a, DedicatedWorkerGlobalSc
trait PrivateDedicatedWorkerGlobalScopeHelpers {
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) {
match msg {
ScriptMsg::DOMMessage(data) => {
let scope: JSRef<WorkerGlobalScope> = WorkerGlobalScopeCast::from_ref(self);
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
let message = data.read(GlobalRef::Worker(scope));
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message);
let scope = WorkerGlobalScopeCast::from_ref(self);
let target = EventTargetCast::from_ref(self);
let _ar = JSAutoRequest::new(scope.get_cx());
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) => {
runnable.handler()
},
ScriptMsg::RefcountCleanup(addr) => {
let scope: JSRef<WorkerGlobalScope> = WorkerGlobalScopeCast::from_ref(self);
let scope = WorkerGlobalScopeCast::from_ref(self);
LiveDOMReferences::cleanup(scope.get_cx(), addr);
}
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);
}
_ => 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 file_name = errorevent.Filename();
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
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 worker = self.worker.borrow().as_ref().unwrap().clone();
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::{ElementCast, NodeCast};
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::global::GlobalRef;
use dom::document::Document;
@ -33,40 +33,39 @@ impl DocumentFragmentDerived for EventTarget {
impl DocumentFragment {
/// Creates a new DocumentFragment.
fn new_inherited(document: JSRef<Document>) -> DocumentFragment {
fn new_inherited(document: &Document) -> DocumentFragment {
DocumentFragment {
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),
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 = document.root();
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
fn Children(self) -> Temporary<HTMLCollection> {
let window = window_from_node(self).root();
fn Children(self) -> Root<HTMLCollection> {
let window = window_from_node(self);
HTMLCollection::children(window.r(), NodeCast::from_ref(self))
}
// 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()
}
// https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
fn GetLastElementChild(self) -> Option<Temporary<Element>> {
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_temporary).next()
fn GetLastElementChild(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next()
}
// 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
fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> {
let root: JSRef<Node> = NodeCast::from_ref(self);
fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
let root = NodeCast::from_ref(self);
root.query_selector(selectors)
}
// https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Temporary<NodeList>> {
let root: JSRef<Node> = NodeCast::from_ref(self);
fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Root<NodeList>> {
let root = NodeCast::from_ref(self);
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::UnionTypes::NodeOrString;
use dom::bindings::error::ErrorResult;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::node::{Node, NodeHelpers, NodeTypeId};
@ -35,7 +35,7 @@ impl DocumentType {
fn new_inherited(name: DOMString,
public_id: Option<DOMString>,
system_id: Option<DOMString>,
document: JSRef<Document>)
document: &Document)
-> DocumentType {
DocumentType {
node: Node::new_inherited(NodeTypeId::DocumentType, document),
@ -48,8 +48,8 @@ impl DocumentType {
pub fn new(name: DOMString,
public_id: Option<DOMString>,
system_id: Option<DOMString>,
document: JSRef<Document>)
-> Temporary<DocumentType> {
document: &Document)
-> Root<DocumentType> {
let documenttype = DocumentType::new_inherited(name,
public_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
fn Name(self) -> DOMString {
self.name.clone()
@ -106,7 +106,7 @@ impl<'a> DocumentTypeMethods for JSRef<'a, DocumentType> {
// https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(self) {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(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::DOMExceptionMethods;
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 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)
}
}
impl<'a> DOMExceptionMethods for JSRef<'a, DOMException> {
impl<'a> DOMExceptionMethods for &'a DOMException {
// https://heycam.github.io/webidl/#dfn-DOMException
fn Code(self) -> u16 {
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::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, OptionalRootable, Root, Rootable};
use dom::bindings::js::Temporary;
use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::bindings::utils::validate_qualified_name;
use dom::document::{Document, DocumentHelpers, IsHTMLDocument};
@ -21,7 +20,6 @@ use dom::htmlbodyelement::HTMLBodyElement;
use dom::htmlheadelement::HTMLHeadElement;
use dom::htmlhtmlelement::HTMLHtmlElement;
use dom::htmltitleelement::HTMLTitleElement;
use dom::node::Node;
use dom::text::Text;
use util::str::DOMString;
@ -35,15 +33,15 @@ pub struct DOMImplementation {
}
impl DOMImplementation {
fn new_inherited(document: JSRef<Document>) -> DOMImplementation {
fn new_inherited(document: &Document) -> DOMImplementation {
DOMImplementation {
reflector_: Reflector::new(),
document: JS::from_rooted(document),
document: JS::from_ref(document),
}
}
pub fn new(document: JSRef<Document>) -> Temporary<DOMImplementation> {
let window = document.window().root();
pub fn new(document: &Document) -> Root<DOMImplementation> {
let window = document.window();
reflect_dom_object(box DOMImplementation::new_inherited(document),
GlobalRef::Window(window.r()),
DOMImplementationBinding::Wrap)
@ -51,10 +49,10 @@ impl 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
fn CreateDocumentType(self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString)
-> Fallible<Temporary<DocumentType>> {
-> Fallible<Root<DocumentType>> {
try!(validate_qualified_name(&qualified_name));
let document = self.document.root();
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
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 = doc.r();
let win = doc.window().root();
let win = doc.window();
let loader = DocumentLoader::new(&*doc.loader());
// Step 1.
let doc = Document::new(win.r(), None, IsHTMLDocument::NonHTMLDocument,
None, None, DocumentSource::NotFromParser, loader).root();
None, None, DocumentSource::NotFromParser, loader);
// Step 2-3.
let maybe_elem = if qname.is_empty() {
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.
match maybe_doctype {
None => (),
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())
}
}
// Step 5.
match maybe_elem.root() {
match maybe_elem {
None => (),
Some(ref elem) => {
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
// Step 7.
Ok(Temporary::from_rooted(doc.r()))
Ok(doc)
}
// 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 = document.r();
let win = document.window().root();
let win = document.window();
let loader = DocumentLoader::new(&*document.loader());
// Step 1-2.
let doc = Document::new(win.r(), None, IsHTMLDocument::HTMLDocument, None, None,
DocumentSource::NotFromParser, loader).root();
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r());
DocumentSource::NotFromParser, loader);
{
// 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());
}
{
// Step 4.
let doc_html: Root<Node> = NodeCast::from_temporary(
HTMLHtmlElement::new("html".to_owned(), None, doc.r())).root();
let doc_node = NodeCast::from_ref(doc.r());
let doc_html = NodeCast::from_root(
HTMLHtmlElement::new("html".to_owned(), None, doc.r()));
assert!(doc_node.AppendChild(doc_html.r()).is_ok());
{
// Step 5.
let doc_head: Root<Node> = NodeCast::from_temporary(
HTMLHeadElement::new("head".to_owned(), None, doc.r())).root();
let doc_head = NodeCast::from_root(
HTMLHeadElement::new("head".to_owned(), None, doc.r()));
assert!(doc_html.r().AppendChild(doc_head.r()).is_ok());
// Step 6.
@ -144,19 +143,19 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
None => (),
Some(title_str) => {
// Step 6.1.
let doc_title: Root<Node> = NodeCast::from_temporary(
HTMLTitleElement::new("title".to_owned(), None, doc.r())).root();
let doc_title = NodeCast::from_root(
HTMLTitleElement::new("title".to_owned(), None, doc.r()));
assert!(doc_head.r().AppendChild(doc_title.r()).is_ok());
// 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());
}
}
}
// 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());
}
@ -164,7 +163,7 @@ impl<'a> DOMImplementationMethods for JSRef<'a, DOMImplementation> {
// FIXME: https://github.com/mozilla/servo/issues/1522
// Step 9.
Temporary::from_rooted(doc.r())
doc
}
// 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::error::Fallible;
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::document::{Document, DocumentHelpers, IsHTMLDocument};
use dom::document::DocumentSource;
@ -27,33 +27,33 @@ pub struct DOMParser {
}
impl DOMParser {
fn new_inherited(window: JSRef<Window>) -> DOMParser {
fn new_inherited(window: &Window) -> DOMParser {
DOMParser {
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),
DOMParserBinding::Wrap)
}
pub fn Constructor(global: GlobalRef) -> Fallible<Temporary<DOMParser>> {
pub fn Constructor(global: GlobalRef) -> Fallible<Root<DOMParser>> {
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
fn ParseFromString(self,
s: DOMString,
ty: DOMParserBinding::SupportedType)
-> Fallible<Temporary<Document>> {
-> Fallible<Root<Document>> {
let window = self.window.root();
let url = window.r().get_url();
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 loader = DocumentLoader::new(&*doc.loader());
match ty {
@ -63,10 +63,10 @@ impl<'a> DOMParserMethods for JSRef<'a, DOMParser> {
Some(content_type),
None,
DocumentSource::FromParser,
loader).root();
loader);
parse_html(document.r(), s, &url, ParseContext::Owner(None));
document.r().set_ready_state(DocumentReadyState::Complete);
Ok(Temporary::from_rooted(document.r()))
Ok(document)
}
Text_xml => {
//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::DOMRectMethods;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::bindings::num::Finite;
use dom::bindings::utils::{Reflector, reflect_dom_object};
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,
left: Au, right: Au) -> Temporary<DOMRect> {
left: Au, right: Au) -> Root<DOMRect> {
reflect_dom_object(box DOMRect::new_inherited(top, bottom, left, right),
GlobalRef::Window(window), DOMRectBinding::Wrap)
}
}
impl<'a> DOMRectMethods for JSRef<'a, DOMRect> {
impl<'a> DOMRectMethods for &'a DOMRect {
fn Top(self) -> Finite<f32> {
Finite::wrap(self.top)
}

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::DOMRectListBinding;
use dom::bindings::codegen::Bindings::DOMRectListBinding::DOMRectListMethods;
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::domrect::DOMRect;
use dom::window::Window;
@ -18,37 +18,37 @@ pub struct DOMRectList {
}
impl DOMRectList {
fn new_inherited<T>(window: JSRef<Window>, rects: T) -> DOMRectList
where T: Iterator<Item=Temporary<DOMRect>> {
fn new_inherited<T>(window: &Window, rects: T) -> DOMRectList
where T: Iterator<Item=Root<DOMRect>> {
DOMRectList {
reflector_: Reflector::new(),
rects: rects.map(JS::from_rooted).collect(),
window: JS::from_rooted(window),
rects: rects.map(|r| JS::from_rooted(&r)).collect(),
window: JS::from_ref(window),
}
}
pub fn new<T>(window: JSRef<Window>, rects: T) -> Temporary<DOMRectList>
where T: Iterator<Item=Temporary<DOMRect>> {
pub fn new<T>(window: &Window, rects: T) -> Root<DOMRectList>
where T: Iterator<Item=Root<DOMRect>> {
reflect_dom_object(box DOMRectList::new_inherited(window, rects),
GlobalRef::Window(window), DOMRectListBinding::Wrap)
}
}
impl<'a> DOMRectListMethods for JSRef<'a, DOMRectList> {
impl<'a> DOMRectListMethods for &'a DOMRectList {
fn Length(self) -> 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;
if index < rects.len() as u32 {
Some(Temporary::from_rooted(rects[index as usize].clone()))
Some(rects[index as usize].root())
} else {
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;
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::error::ErrorResult;
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::node::window_from_node;
use dom::htmlelement::{HTMLElement, HTMLElementCustomAttributeHelpers};
@ -19,22 +19,22 @@ pub struct DOMStringMap {
}
impl DOMStringMap {
fn new_inherited(element: JSRef<HTMLElement>) -> DOMStringMap {
fn new_inherited(element: &HTMLElement) -> DOMStringMap {
DOMStringMap {
reflector_: Reflector::new(),
element: JS::from_rooted(element),
element: JS::from_ref(element),
}
}
pub fn new(element: JSRef<HTMLElement>) -> Temporary<DOMStringMap> {
let window = window_from_node(element).root();
pub fn new(element: &HTMLElement) -> Root<DOMStringMap> {
let window = window_from_node(element);
reflect_dom_object(box DOMStringMap::new_inherited(element),
GlobalRef::Window(window.r()), DOMStringMapBinding::Wrap)
}
}
// 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 {
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::Error::{InvalidCharacter, Syntax};
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::element::{Element, AttributeHandlers};
use dom::node::window_from_node;
@ -26,16 +26,16 @@ pub struct 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 {
reflector_: Reflector::new(),
element: JS::from_rooted(element),
element: JS::from_ref(element),
local_name: local_name,
}
}
pub fn new(element: JSRef<Element>, local_name: &Atom) -> Temporary<DOMTokenList> {
let window = window_from_node(element).root();
pub fn new(element: &Element, local_name: &Atom) -> Root<DOMTokenList> {
let window = window_from_node(element);
reflect_dom_object(box DOMTokenList::new_inherited(element, local_name.clone()),
GlobalRef::Window(window.r()),
DOMTokenListBinding::Wrap)
@ -43,12 +43,12 @@ impl DOMTokenList {
}
trait PrivateDOMTokenListHelpers {
fn attribute(self) -> Option<Temporary<Attr>>;
fn attribute(self) -> Option<Root<Attr>>;
fn check_token_exceptions(self, token: &str) -> Fallible<Atom>;
}
impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> {
fn attribute(self) -> Option<Temporary<Attr>> {
impl<'a> PrivateDOMTokenListHelpers for &'a DOMTokenList {
fn attribute(self) -> Option<Root<Attr>> {
let element = self.element.root();
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
impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
impl<'a> DOMTokenListMethods for &'a DOMTokenList {
// https://dom.spec.whatwg.org/#dom-domtokenlist-length
fn Length(self) -> u32 {
self.attribute().root().map(|attr| {
self.attribute().map(|attr| {
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r();
let value = attr.value();
@ -76,7 +76,7 @@ impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
// https://dom.spec.whatwg.org/#dom-domtokenlist-item
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)
let attr = attr.r();
let value = attr.value();
@ -95,7 +95,7 @@ impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
// https://dom.spec.whatwg.org/#dom-domtokenlist-contains
fn Contains(self, token: DOMString) -> Fallible<bool> {
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)
let attr = attr.r();
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::Error::{InvalidCharacter, Syntax};
use dom::bindings::error::Error::NoModificationAllowed;
use dom::bindings::js::{JS, JSRef, LayoutJS, MutNullableHeap};
use dom::bindings::js::{OptionalRootable, Rootable, RootedReference};
use dom::bindings::js::{Temporary, TemporaryPushable};
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
use dom::bindings::js::{Root, RootedReference};
use dom::bindings::trace::RootedVec;
use dom::bindings::utils::{xml_name_type, validate_and_extract};
use dom::bindings::utils::XMLName::InvalidXMLName;
@ -42,7 +41,6 @@ use dom::document::{Document, DocumentHelpers, LayoutDocumentHelpers};
use dom::domtokenlist::DOMTokenList;
use dom::event::{Event, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlanchorelement::HTMLAnchorElement;
use dom::htmlbodyelement::{HTMLBodyElement, HTMLBodyElementHelpers};
use dom::htmlcollection::HTMLCollection;
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)]
#[jstraceable]
pub enum ElementTypeId {
@ -131,14 +135,14 @@ pub enum ElementCreator {
//
impl Element {
pub fn create(name: QualName, prefix: Option<Atom>,
document: JSRef<Document>, creator: ElementCreator)
-> Temporary<Element> {
document: &Document, creator: ElementCreator)
-> Root<Element> {
create_element(name, prefix, document, creator)
}
pub fn new_inherited(type_id: ElementTypeId, local_name: DOMString,
namespace: Namespace, prefix: Option<DOMString>,
document: JSRef<Document>) -> Element {
document: &Document) -> Element {
Element {
node: Node::new_inherited(NodeTypeId::Element(type_id), document),
local_name: Atom::from_slice(&local_name),
@ -154,7 +158,7 @@ impl Element {
pub fn new(local_name: DOMString,
namespace: Namespace,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<Element> {
document: &Document) -> Root<Element> {
Node::reflect_node(
box Element::new_inherited(ElementTypeId::Element, local_name, namespace, prefix, document),
document,
@ -181,8 +185,6 @@ pub trait RawLayoutElementHelpers {
-> Option<u32>;
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]
@ -504,14 +506,6 @@ impl RawLayoutElementHelpers for Element {
fn local_name<'a>(&'a self) -> &'a Atom {
&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 {
@ -560,18 +554,18 @@ pub trait ElementHelpers<'a> {
fn get_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 get_root_element(self) -> Temporary<Element>;
fn get_root_element(self) -> Root<Element>;
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 {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
self.namespace == ns!(HTML) && node.is_in_html_doc()
}
fn local_name(self) -> &'a Atom {
&self.extended_deref().local_name
&self.local_name
}
fn parsed_name(self, name: DOMString) -> DOMString {
@ -583,30 +577,30 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
}
fn namespace(self) -> &'a Namespace {
&self.extended_deref().namespace
&self.namespace
}
fn prefix(self) -> &'a Option<DOMString> {
&self.extended_deref().prefix
&self.prefix
}
fn attrs(&self) -> Ref<Vec<JS<Attr>>> {
self.extended_deref().attrs.borrow()
self.attrs.borrow()
}
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>> {
&self.extended_deref().style_attribute
&self.style_attribute
}
fn summarize(self) -> Vec<AttrInfo> {
let attrs = self.Attributes().root();
let attrs = self.Attributes();
let mut summarized = vec!();
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
@ -702,7 +696,7 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
}
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![];
match serialize(&mut writer, &node,
SerializeOpts {
@ -715,10 +709,10 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
}
// https://html.spec.whatwg.org/multipage/#root-element
fn get_root_element(self) -> Temporary<Element> {
let node: JSRef<Node> = NodeCast::from_ref(self);
fn get_root_element(self) -> Root<Element> {
let node = NodeCast::from_ref(self);
node.inclusive_ancestors()
.filter_map(ElementCast::to_temporary)
.filter_map(ElementCast::to_root)
.last()
.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
fn lookup_prefix(self, namespace: Namespace) -> Option<DOMString> {
for node in NodeCast::from_ref(self).inclusive_ancestors() {
match ElementCast::to_ref(node.root().r()) {
match ElementCast::to_ref(node.r()) {
Some(element) => {
// Step 1.
if *element.namespace() == namespace {
@ -736,9 +730,9 @@ impl<'a> ElementHelpers<'a> for JSRef<'a, Element> {
}
// Step 2.
let attrs = element.Attributes().root();
let attrs = element.Attributes();
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")) &&
**attr.r().value() == *namespace.0 {
return Some(attr.r().LocalName());
@ -760,13 +754,13 @@ pub trait FocusElementHelpers {
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 {
if self.is_actually_disabled() {
return false;
}
// 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) {
return true;
}
@ -783,7 +777,7 @@ impl<'a> FocusElementHelpers for JSRef<'a, Element> {
}
fn is_actually_disabled(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
match node.type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) |
@ -805,10 +799,10 @@ pub trait AttributeHandlers {
/// Returns the attribute with given namespace and case-sensitive local
/// name, if any.
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
/// 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 set_attribute_from_parser(self,
name: QualName,
@ -819,19 +813,19 @@ pub trait AttributeHandlers {
fn do_set_attribute<F>(self, local_name: Atom, value: AttrValue,
name: Atom, namespace: Namespace,
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,
value: DOMString) -> AttrValue;
/// Removes the first attribute with any given namespace and case-sensitive local
/// name, if any.
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.
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`.
fn do_remove_attribute<F>(self, find: F) -> Option<Temporary<Attr>>
where F: Fn(JSRef<Attr>) -> bool;
fn do_remove_attribute<F>(self, find: F) -> Option<Root<Attr>>
where F: Fn(&Attr) -> 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);
}
impl<'a> AttributeHandlers for JSRef<'a, Element> {
fn get_attribute(self, namespace: &Namespace, local_name: &Atom) -> Option<Temporary<Attr>> {
impl<'a> AttributeHandlers for &'a Element {
fn get_attribute(self, namespace: &Namespace, local_name: &Atom) -> Option<Root<Attr>> {
let mut attributes = RootedVec::new();
self.get_attributes(local_name, &mut attributes);
attributes.iter()
.map(|attr| attr.root())
.find(|attr| attr.r().namespace() == namespace)
.map(|x| Temporary::from_rooted(x.r()))
}
// 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));
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let attrs = self.attrs.borrow();
attrs.iter().map(|attr| attr.root())
.find(|a| a.r().name() == name)
.map(|x| Temporary::from_rooted(x.r()))
}
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
fn get_attributes(self, local_name: &Atom, attributes: &mut RootedVec<JS<Attr>>) {
// FIXME(https://github.com/rust-lang/rust/issues/23338)
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)
let attr = attr.r();
let attr_local_name = attr.local_name();
let attr = attr.root();
let attr_local_name = attr.r().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,
prefix: Option<Atom>,
cb: F)
where F: Fn(JSRef<Attr>) -> bool
where F: Fn(&Attr) -> bool
{
let idx = self.attrs.borrow().iter()
.map(|attr| attr.root())
@ -946,10 +938,10 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
let (idx, set_type) = match idx {
Some(idx) => (idx, AttrSettingType::ReplacedAttr),
None => {
let window = window_from_node(self).root();
let window = window_from_node(self);
let attr = Attr::new(window.r(), local_name, value.clone(),
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)
}
};
@ -968,18 +960,18 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
}
fn remove_attribute(self, namespace: &Namespace, local_name: &Atom)
-> Option<Temporary<Attr>> {
-> Option<Root<Attr>> {
self.do_remove_attribute(|attr| {
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)
}
fn do_remove_attribute<F>(self, find: F) -> Option<Temporary<Attr>>
where F: Fn(JSRef<Attr>) -> bool
fn do_remove_attribute<F>(self, find: F) -> Option<Root<Attr>>
where F: Fn(&Attr) -> bool
{
let idx = self.attrs.borrow().iter()
.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());
}
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
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") {
NodeDamage::NodeStyleDamaged
} else {
@ -1007,21 +999,21 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
};
document.r().content_changed(node, damage);
}
Temporary::from_rooted(attr.r())
attr
})
}
fn has_class(self, name: &Atom) -> bool {
let quirks_mode = {
let node: JSRef<Node> = NodeCast::from_ref(self);
let owner_doc = node.owner_doc().root();
let node = NodeCast::from_ref(self);
let owner_doc = node.owner_doc();
owner_doc.r().quirks_mode()
};
let is_equal = |lhs: &Atom, rhs: &Atom| match quirks_mode {
NoQuirks | LimitedQuirks => lhs == 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)
let attr = attr.r();
let value = attr.value();
@ -1063,7 +1055,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
return "".to_owned();
}
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();
// https://html.spec.whatwg.org/multipage/#reflect
// 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 {
match self.get_attribute(&ns!(""), local_name) {
Some(x) => x.root().r().Value(),
Some(x) => x.r().Value(),
None => "".to_owned()
}
}
@ -1088,7 +1080,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
}
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)
let attr = attr.r();
let value = attr.value();
@ -1112,7 +1104,7 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> {
assert!(local_name.chars().all(|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 {
Some(ref attribute) => {
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
fn GetNamespaceURI(self) -> Option<DOMString> {
match self.namespace {
@ -1185,25 +1177,25 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
}
// 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")))
}
// https://dom.spec.whatwg.org/#dom-element-attributes
fn Attributes(self) -> Temporary<NamedNodeMap> {
fn Attributes(self) -> Root<NamedNodeMap> {
self.attr_list.or_init(|| {
let doc = {
let node: JSRef<Node> = NodeCast::from_ref(self);
node.owner_doc().root()
let node = NodeCast::from_ref(self);
node.owner_doc()
};
let window = doc.r().window().root();
let window = doc.r().window();
NamedNodeMap::new(window.r(), self)
})
}
// https://dom.spec.whatwg.org/#dom-element-getattribute
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())
}
@ -1212,7 +1204,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
namespace: Option<DOMString>,
local_name: DOMString) -> Option<DOMString> {
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())
}
@ -1282,28 +1274,28 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
}
// https://dom.spec.whatwg.org/#dom-element-getelementsbytagname
fn GetElementsByTagName(self, localname: DOMString) -> Temporary<HTMLCollection> {
let window = window_from_node(self).root();
fn GetElementsByTagName(self, localname: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self);
HTMLCollection::by_tag_name(window.r(), NodeCast::from_ref(self), localname)
}
// https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens
fn GetElementsByTagNameNS(self, maybe_ns: Option<DOMString>,
localname: DOMString) -> Temporary<HTMLCollection> {
let window = window_from_node(self).root();
localname: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self);
HTMLCollection::by_tag_name_ns(window.r(), NodeCast::from_ref(self), localname, maybe_ns)
}
// https://dom.spec.whatwg.org/#dom-element-getelementsbyclassname
fn GetElementsByClassName(self, classes: DOMString) -> Temporary<HTMLCollection> {
let window = window_from_node(self).root();
fn GetElementsByClassName(self, classes: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self);
HTMLCollection::by_class_name(window.r(), NodeCast::from_ref(self), classes)
}
// http://dev.w3.org/csswg/cssom-view/#dom-element-getclientrects
fn GetClientRects(self) -> Temporary<DOMRectList> {
let win = window_from_node(self).root();
let node: JSRef<Node> = NodeCast::from_ref(self);
fn GetClientRects(self) -> Root<DOMRectList> {
let win = window_from_node(self);
let node = NodeCast::from_ref(self);
let raw_rects = node.get_content_boxes();
let rects = raw_rects.iter().map(|rect| {
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
fn GetBoundingClientRect(self) -> Temporary<DOMRect> {
let win = window_from_node(self).root();
let node: JSRef<Node> = NodeCast::from_ref(self);
fn GetBoundingClientRect(self) -> Root<DOMRect> {
let win = window_from_node(self);
let node = NodeCast::from_ref(self);
let rect = node.get_bounding_content_box();
DOMRect::new(
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
fn SetInnerHTML(self, value: DOMString) -> Fallible<()> {
let context_node: JSRef<Node> = NodeCast::from_ref(self);
let context_node = NodeCast::from_ref(self);
// Step 1.
let frag = try!(context_node.parse_fragment(value));
// 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(())
}
@ -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
fn SetOuterHTML(self, value: DOMString) -> Fallible<()> {
let context_document = document_from_node(self).root();
let context_node: JSRef<Node> = NodeCast::from_ref(self);
let context_document = document_from_node(self);
let context_node = NodeCast::from_ref(self);
// Step 1.
let context_parent = match context_node.GetParentNode() {
None => {
@ -1358,7 +1350,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
return Ok(());
},
Some(parent) => parent,
}.root();
};
let parent = match context_parent.r().type_id() {
// Step 3.
@ -1369,45 +1361,45 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
let body_elem = Element::create(QualName::new(ns!(HTML), atom!(body)),
None, context_document.r(),
ElementCreator::ScriptCreated);
NodeCast::from_temporary(body_elem)
NodeCast::from_root(body_elem)
},
_ => context_node.GetParentNode().unwrap()
}.root();
};
// Step 5.
let frag = try!(parent.r().parse_fragment(value));
// 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));
Ok(())
}
// 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()
.filter_map(ElementCast::to_temporary).next()
.filter_map(ElementCast::to_root).next()
}
// 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()
.filter_map(ElementCast::to_temporary).next()
.filter_map(ElementCast::to_root).next()
}
// https://dom.spec.whatwg.org/#dom-parentnode-children
fn Children(self) -> Temporary<HTMLCollection> {
let window = window_from_node(self).root();
fn Children(self) -> Root<HTMLCollection> {
let window = window_from_node(self);
HTMLCollection::children(window.r(), NodeCast::from_ref(self))
}
// 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()
}
// https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
fn GetLastElementChild(self) -> Option<Temporary<Element>> {
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_temporary).next()
fn GetLastElementChild(self) -> Option<Root<Element>> {
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next()
}
// 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
fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Temporary<Element>>> {
let root: JSRef<Node> = NodeCast::from_ref(self);
fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
let root = NodeCast::from_ref(self);
root.query_selector(selectors)
}
// https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Temporary<NodeList>> {
let root: JSRef<Node> = NodeCast::from_ref(self);
fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Root<NodeList>> {
let root = NodeCast::from_ref(self);
root.query_selector_all(selectors)
}
@ -1454,7 +1446,7 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
// https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(self) {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
node.remove_self();
}
@ -1463,23 +1455,22 @@ impl<'a> ElementMethods for JSRef<'a, Element> {
match parse_author_origin_selector_list_from_str(&selectors) {
Err(()) => Err(Syntax),
Ok(ref selectors) => {
let root: JSRef<Node> = NodeCast::from_ref(self);
let root = NodeCast::from_ref(self);
Ok(matches(selectors, &root, &mut None))
}
}
}
// 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) {
Err(()) => Err(Syntax),
Ok(ref selectors) => {
let root: JSRef<Node> = NodeCast::from_ref(self);
let root = NodeCast::from_ref(self);
for element in root.inclusive_ancestors() {
let element = element.root();
if let Some(element) = ElementCast::to_ref(element.r()) {
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> {
let node: &JSRef<Node> = NodeCast::from_borrowed_ref(self);
let node: &&Node = NodeCast::from_borrowed_ref(self);
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() {
s.after_set_attr(attr);
}
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
match attr.local_name() {
&atom!("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 value = attr.value();
let style = Some(parse_style_attribute(&value, &base_url));
@ -1517,7 +1508,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
&atom!("class") => {
// Modifying a class can change style.
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);
}
}
@ -1525,7 +1516,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
// Modifying an ID might change style.
let value = attr.value();
if node.is_in_doc() {
let doc = document_from_node(*self).root();
let doc = document_from_node(*self);
if !value.is_empty() {
let value = value.atom().unwrap().clone();
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.
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);
}
}
}
}
fn before_remove_attr(&self, attr: JSRef<Attr>) {
fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() {
s.before_remove_attr(attr);
}
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
match attr.local_name() {
&atom!("style") => {
// Modifying the `style` attribute might change style.
*self.style_attribute.borrow_mut() = None;
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);
}
}
@ -1563,7 +1554,7 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
// Modifying an ID can change style.
let value = attr.value();
if node.is_in_doc() {
let doc = document_from_node(*self).root();
let doc = document_from_node(*self);
if !value.is_empty() {
let value = value.atom().unwrap().clone();
doc.r().unregister_named_element(*self, value);
@ -1574,14 +1565,14 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
&atom!("class") => {
// Modifying a class can change style.
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);
}
}
_ => {
// Modifying any other attribute might change arbitrary things.
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);
}
}
@ -1603,8 +1594,8 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
if !tree_in_doc { return; }
if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")).root() {
let doc = document_from_node(*self).root();
if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) {
let doc = document_from_node(*self);
let value = attr.r().Value();
if !value.is_empty() {
let value = Atom::from_slice(&value);
@ -1620,8 +1611,8 @@ impl<'a> VirtualMethods for JSRef<'a, Element> {
if !tree_in_doc { return; }
if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")).root() {
let doc = document_from_node(*self).root();
if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) {
let doc = document_from_node(*self);
let value = attr.r().Value();
if !value.is_empty() {
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 {
// FIXME: This is HTML only.
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
match node.type_id() {
// https://html.spec.whatwg.org/multipage/#selector-link
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement)) |
@ -1675,19 +1666,18 @@ impl<'a> style::node::TElement<'a> for JSRef<'a, Element> {
get_namespace(self)
}
fn get_hover_state(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
node.get_hover_state()
}
fn get_focus_state(self) -> bool {
// TODO: Also check whether the top-level browsing context has the system focus,
// and whether this element is a browsing context container.
// 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()
}
fn get_id(self) -> Option<Atom> {
self.get_attribute(&ns!(""), &atom!("id")).map(|attr| {
let attr = attr.root();
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r();
let value = attr.value();
@ -1698,22 +1688,22 @@ impl<'a> style::node::TElement<'a> for JSRef<'a, Element> {
})
}
fn get_disabled_state(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
node.get_disabled_state()
}
fn get_enabled_state(self) -> bool {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
node.get_enabled_state()
}
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 {
Some(input) => input.Checked(),
None => false,
}
}
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 {
Some(input) => input.get_indeterminate_state(),
None => false,
@ -1731,7 +1721,7 @@ impl<'a> style::node::TElement<'a> for JSRef<'a, Element> {
fn each_class<F>(self, mut callback: F)
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() {
for token in tokens {
callback(token)
@ -1740,7 +1730,7 @@ impl<'a> style::node::TElement<'a> for JSRef<'a, Element> {
}
}
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 {
None => false,
Some(this) => {
@ -1757,20 +1747,20 @@ pub trait ActivationElementHelpers<'a> {
fn as_maybe_activatable(&'a self) -> Option<&'a (Activatable + 'a)>;
fn click_in_progress(self) -> bool;
fn set_click_in_progress(self, click: bool);
fn nearest_activable_element(self) -> Option<Temporary<Element>>;
fn authentic_click_activation<'b>(self, event: JSRef<'b, Event>);
fn nearest_activable_element(self) -> Option<Root<Element>>;
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)> {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
let element = match node.type_id() {
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))
},
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))
},
_ => {
@ -1787,26 +1777,25 @@ impl<'a> ActivationElementHelpers<'a> for JSRef<'a, Element> {
}
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)
}
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)
}
// 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() {
Some(el) => Some(Temporary::from_rooted(el.as_element().root().r())),
Some(el) => Some(Root::from_ref(el.as_element())),
None => {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
for node in node.ancestors() {
let node = node.root();
if let Some(node) = ElementCast::to_ref(node.r()) {
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.
/// 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
// required to save state between pre-activation and post-activation
// since we cannot nest authentic clicks (unlike synthetic click activation, where
// the script can generate more click events from the handler)
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 3
self.set_click_in_progress(true);
// Step 4
let e = self.nearest_activable_element().root();
let e = self.nearest_activable_element();
match e {
Some(ref el) => match el.r().as_maybe_activatable() {
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::error::Fallible;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, MutHeap, Rootable, Temporary};
use js::jsapi::JSContext;
use dom::bindings::js::{Root, MutHeapJSVal};
use js::jsapi::{JSContext, HandleValue};
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::reflect_dom_object;
@ -18,8 +18,8 @@ use util::str::DOMString;
use dom::bindings::cell::DOMRefCell;
use std::borrow::ToOwned;
use std::cell::{Cell};
use js::jsval::{JSVal, NullValue};
use std::cell::Cell;
use js::jsval::JSVal;
#[dom_struct]
pub struct ErrorEvent {
@ -28,7 +28,7 @@ pub struct ErrorEvent {
filename: DOMRefCell<DOMString>,
lineno: Cell<u32>,
colno: Cell<u32>,
error: MutHeap<JSVal>,
error: MutHeapJSVal,
}
impl ErrorEventDerived for Event {
@ -45,11 +45,11 @@ impl ErrorEvent {
filename: DOMRefCell::new("".to_owned()),
lineno: 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),
global,
ErrorEventBinding::Wrap)
@ -63,24 +63,26 @@ impl ErrorEvent {
filename: DOMString,
lineno: u32,
colno: u32,
error: JSVal) -> Temporary<ErrorEvent> {
let ev = ErrorEvent::new_uninitialized(global).root();
let event: JSRef<Event> = EventCast::from_ref(ev.r());
event.InitEvent(type_, bubbles == EventBubbles::Bubbles,
cancelable == EventCancelable::Cancelable);
error: HandleValue) -> Root<ErrorEvent> {
let ev = ErrorEvent::new_uninitialized(global);
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let ev = ev.r();
*ev.message.borrow_mut() = message;
*ev.filename.borrow_mut() = filename;
ev.lineno.set(lineno);
ev.colno.set(colno);
ev.error.set(error);
Temporary::from_rooted(ev)
{
let ev = ev.r();
let event = EventCast::from_ref(ev);
event.InitEvent(type_, bubbles == EventBubbles::Bubbles,
cancelable == EventCancelable::Cancelable);
*ev.message.borrow_mut() = message;
*ev.filename.borrow_mut() = filename;
ev.lineno.set(lineno);
ev.colno.set(colno);
}
ev.error.set(error.get());
ev
}
pub fn Constructor(global: GlobalRef,
type_: DOMString,
init: &ErrorEventBinding::ErrorEventInit) -> Fallible<Temporary<ErrorEvent>>{
init: &ErrorEventBinding::ErrorEventInit) -> Fallible<Root<ErrorEvent>>{
let msg = match init.message.as_ref() {
Some(message) => message.clone(),
None => "".to_owned(),
@ -106,13 +108,14 @@ impl ErrorEvent {
let event = ErrorEvent::new(global, type_,
bubbles, cancelable,
msg, file_name,
line_num, col_num, init.error);
line_num, col_num,
HandleValue { ptr: &init.error });
Ok(event)
}
}
impl<'a> ErrorEventMethods for JSRef<'a, ErrorEvent> {
impl<'a> ErrorEventMethods for &'a ErrorEvent {
fn Lineno(self) -> u32 {
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::error::Fallible;
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::eventtarget::{EventTarget, EventTargetHelpers};
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),
global,
EventBinding::Wrap)
@ -104,15 +104,15 @@ impl Event {
pub fn new(global: GlobalRef,
type_: DOMString,
bubbles: EventBubbles,
cancelable: EventCancelable) -> Temporary<Event> {
let event = Event::new_uninitialized(global).root();
cancelable: EventCancelable) -> Root<Event> {
let event = Event::new_uninitialized(global);
event.r().InitEvent(type_, bubbles == EventBubbles::Bubbles, cancelable == EventCancelable::Cancelable);
Temporary::from_rooted(event.r())
event
}
pub fn Constructor(global: GlobalRef,
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 cancelable = if init.cancelable { EventCancelable::Cancelable } else { EventCancelable::NotCancelable };
Ok(Event::new(global, type_, bubbles, cancelable))
@ -129,13 +129,13 @@ impl Event {
}
#[inline]
pub fn set_current_target(&self, val: JSRef<EventTarget>) {
self.current_target.set(Some(JS::from_rooted(val)));
pub fn set_current_target(&self, val: &EventTarget) {
self.current_target.set(Some(JS::from_ref(val)));
}
#[inline]
pub fn set_target(&self, val: JSRef<EventTarget>) {
self.target.set(Some(JS::from_rooted(val)));
pub fn set_target(&self, val: &EventTarget) {
self.target.set(Some(JS::from_ref(val)));
}
#[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
fn EventPhase(self) -> 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
fn GetTarget(self) -> Option<Temporary<EventTarget>> {
self.target.get().map(Temporary::from_rooted)
fn GetTarget(self) -> Option<Root<EventTarget>> {
self.target.get().map(Root::from_rooted)
}
// https://dom.spec.whatwg.org/#dom-event-currenttarget
fn GetCurrentTarget(self) -> Option<Temporary<EventTarget>> {
self.current_target.get().map(Temporary::from_rooted)
fn GetCurrentTarget(self) -> Option<Root<EventTarget>> {
self.current_target.get().map(Root::from_rooted)
}
// https://dom.spec.whatwg.org/#dom-event-defaultprevented
@ -263,16 +263,16 @@ impl<'a> EventMethods for JSRef<'a, Event> {
pub trait EventHelpers {
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) {
self.trusted.set(trusted);
}
// 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);
target.dispatch_event(self)
}

View file

@ -5,7 +5,7 @@
use dom::bindings::callback::ExceptionHandling::Report;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
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::eventtarget::{EventTarget, ListenerPhase};
use dom::event::{Event, EventPhase};
@ -13,9 +13,9 @@ use dom::node::{Node, NodeHelpers};
use dom::virtualmethods::vtable_for;
// See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event<'a, 'b>(target: JSRef<'a, EventTarget>,
pseudo_target: Option<JSRef<'b, EventTarget>>,
event: JSRef<Event>) -> bool {
pub fn dispatch_event<'a, 'b>(target: &'a EventTarget,
pseudo_target: Option<&'b EventTarget>,
event: &Event) -> bool {
assert!(!event.dispatching());
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();
if let Some(target_node) = NodeCast::to_ref(target) {
for ancestor in target_node.ancestors() {
let ancestor = ancestor.root();
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 */
let target = event.GetTarget().root();
let target = event.GetTarget();
match 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 {
Some(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::error::{Fallible, report_pending_exception};
use dom::bindings::error::Error::InvalidState;
use dom::bindings::js::JSRef;
use dom::bindings::utils::{Reflectable, Reflector};
use dom::event::{Event, EventHelpers};
use dom::eventdispatcher::dispatch_event;
@ -17,8 +16,10 @@ use dom::node::NodeTypeId;
use dom::workerglobalscope::WorkerGlobalScopeTypeId;
use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTargetTypeId;
use dom::virtualmethods::VirtualMethods;
use js::jsapi::{JS_CompileUCFunction, JS_GetFunctionObject, JS_CloneFunctionObject};
use js::jsapi::{JSContext, JSObject};
use js::jsapi::{CompileFunction, JS_GetFunctionObject};
use js::jsapi::{JSContext, RootedFunction, HandleObject};
use js::jsapi::{JSAutoCompartment, JSAutoRequest};
use js::rust::{AutoObjectVectorWrapper, CompileOptionsWrapper};
use util::str::DOMString;
use fnv::FnvHasher;
@ -30,6 +31,7 @@ use std::default::Default;
use std::ffi::CString;
use std::intrinsics;
use std::ptr;
use std::rc::Rc;
use url::Url;
use std::collections::HashMap;
@ -88,23 +90,23 @@ impl EventTargetTypeId {
}
}
#[derive(Copy, Clone, PartialEq)]
#[derive(Clone, PartialEq)]
#[jstraceable]
pub enum EventListenerType {
Additive(EventListener),
Inline(EventListener),
Additive(Rc<EventListener>),
Inline(Rc<EventListener>),
}
impl EventListenerType {
fn get_listener(&self) -> EventListener {
fn get_listener(&self) -> Rc<EventListener> {
match *self {
EventListenerType::Additive(listener) |
EventListenerType::Inline(listener) => listener
EventListenerType::Additive(ref listener) |
EventListenerType::Inline(ref listener) => listener.clone(),
}
}
}
#[derive(Copy, Clone, PartialEq)]
#[derive(Clone, PartialEq)]
#[jstraceable]
#[privatize]
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| {
listeners.iter().map(|entry| entry.listener.get_listener()).collect()
})
}
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| {
let filtered = listeners.iter().filter(|entry| entry.phase == desired_phase);
filtered.map(|entry| entry.listener.get_listener()).collect()
@ -150,47 +152,47 @@ impl EventTarget {
pub trait EventTargetHelpers {
fn dispatch_event_with_target(self,
target: JSRef<EventTarget>,
event: JSRef<Event>) -> bool;
fn dispatch_event(self, event: JSRef<Event>) -> bool;
target: &EventTarget,
event: &Event) -> bool;
fn dispatch_event(self, event: &Event) -> bool;
fn set_inline_event_listener(self,
ty: DOMString,
listener: Option<EventListener>);
fn get_inline_event_listener(self, ty: DOMString) -> Option<EventListener>;
listener: Option<Rc<EventListener>>);
fn get_inline_event_listener(self, ty: DOMString) -> Option<Rc<EventListener>>;
fn set_event_handler_uncompiled(self,
cx: *mut JSContext,
url: Url,
scope: *mut JSObject,
scope: HandleObject,
ty: &str,
source: DOMString);
fn set_event_handler_common<T: CallbackContainer>(self, ty: &str,
listener: Option<T>);
fn get_event_handler_common<T: CallbackContainer>(self, ty: &str) -> Option<T>;
listener: Option<Rc<T>>);
fn get_event_handler_common<T: CallbackContainer>(self, ty: &str) -> Option<Rc<T>>;
fn has_handlers(self) -> bool;
}
impl<'a> EventTargetHelpers for JSRef<'a, EventTarget> {
impl<'a> EventTargetHelpers for &'a EventTarget {
fn dispatch_event_with_target(self,
target: JSRef<EventTarget>,
event: JSRef<Event>) -> bool {
target: &EventTarget,
event: &Event) -> bool {
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)
}
fn set_inline_event_listener(self,
ty: DOMString,
listener: Option<EventListener>) {
listener: Option<Rc<EventListener>>) {
let mut handlers = self.handlers.borrow_mut();
let entries = match handlers.entry(ty) {
Occupied(entry) => entry.into_mut(),
Vacant(entry) => entry.insert(vec!()),
};
let idx = entries.iter().position(|&entry| {
let idx = entries.iter().position(|ref entry| {
match entry.listener {
EventListenerType::Inline(_) => true,
_ => 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 entries = handlers.get(&ty);
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,
cx: *mut JSContext,
url: Url,
scope: *mut JSObject,
scope: HandleObject,
ty: &str,
source: DOMString) {
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];
let source: Vec<u16> = source.utf16_units().collect();
let handler = unsafe {
JS_CompileUCFunction(cx,
ptr::null_mut(),
name.as_ptr(),
nargs,
ARG_NAMES.as_mut_ptr(),
source.as_ptr(),
source.len() as size_t,
url.as_ptr(),
lineno)
let options = CompileOptionsWrapper::new(cx, url.as_ptr(), lineno);
let scopechain = AutoObjectVectorWrapper::new(cx);
let _ar = JSAutoRequest::new(cx);
let _ac = JSAutoCompartment::new(cx, scope.get());
let mut handler = RootedFunction::new(cx, ptr::null_mut());
let rv = unsafe {
CompileFunction(cx,
scopechain.ptr,
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() {
report_pending_exception(cx, self.reflector().get_jsobject());
if rv == 0 || handler.ptr.is_null() {
report_pending_exception(cx, self.reflector().get_jsobject().get());
return;
}
let funobj = unsafe {
JS_CloneFunctionObject(cx, JS_GetFunctionObject(handler), scope)
};
let funobj = unsafe { JS_GetFunctionObject(handler.ptr) };
assert!(!funobj.is_null());
self.set_event_handler_common(ty, Some(EventHandlerNonNull::new(funobj)));
}
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|
EventListener::new(listener.callback()));
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());
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,
ty: DOMString,
listener: Option<EventListener>,
listener: Option<Rc<EventListener>>,
capture: bool) {
match listener {
Some(listener) => {
@ -314,17 +320,17 @@ impl<'a> EventTargetMethods for JSRef<'a, EventTarget> {
fn RemoveEventListener(self,
ty: DOMString,
listener: Option<EventListener>,
listener: Option<Rc<EventListener>>,
capture: bool) {
match listener {
Some(listener) => {
Some(ref listener) => {
let mut handlers = self.handlers.borrow_mut();
let mut entry = handlers.get_mut(&ty);
for entry in entry.iter_mut() {
let phase = if capture { ListenerPhase::Capturing } else { ListenerPhase::Bubbling };
let old_entry = EventListenerEntry {
phase: phase,
listener: EventListenerType::Additive(listener)
listener: EventListenerType::Additive(listener.clone())
};
let position = entry.position_elem(&old_entry);
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() {
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> {
None
}

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::FileBinding;
use dom::bindings::codegen::Bindings::FileBinding::FileMethods;
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::blob::{Blob, BlobTypeId};
use util::str::DOMString;
@ -18,7 +18,7 @@ pub struct File {
impl File {
fn new_inherited(global: GlobalRef, type_: BlobTypeId,
_file_bits: JSRef<Blob>, name: DOMString) -> File {
_file_bits: &Blob, name: DOMString) -> File {
File {
//TODO: get type from the underlying filesystem instead of "".to_string()
blob: Blob::new_inherited(global, type_, None, ""),
@ -28,7 +28,7 @@ impl File {
// 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),
global,
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 {
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::error::{Fallible};
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::blob::Blob;
use dom::file::File;
@ -38,29 +38,29 @@ pub struct FormData {
}
impl FormData {
fn new_inherited(form: Option<JSRef<HTMLFormElement>>, global: GlobalRef) -> FormData {
fn new_inherited(form: Option<&HTMLFormElement>, global: GlobalRef) -> FormData {
FormData {
reflector_: Reflector::new(),
data: DOMRefCell::new(HashMap::new()),
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),
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))
}
}
impl<'a> FormDataMethods for JSRef<'a, FormData> {
impl<'a> FormDataMethods for &'a FormData {
#[allow(unrooted_must_root)]
fn Append(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) {
let file = FormDatum::FileData(JS::from_rooted(self.get_file_from_blob(value, filename)));
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 mut data = self.data.borrow_mut();
match data.entry(name) {
Occupied(entry) => entry.into_mut().push(file),
@ -90,7 +90,7 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
match data[&name][0].clone() {
FormDatum::StringData(ref s) => Some(eString(s.clone())),
FormDatum::FileData(ref f) => {
Some(eFile(Unrooted::from_js(*f)))
Some(eFile(f.root()))
}
}
} else {
@ -104,8 +104,8 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
data.contains_key(&name)
}
#[allow(unrooted_must_root)]
fn Set(self, name: DOMString, value: JSRef<Blob>, filename: Option<DOMString>) {
let file = FormDatum::FileData(JS::from_rooted(self.get_file_from_blob(value, filename)));
fn Set(self, name: DOMString, value: &Blob, filename: Option<DOMString>) {
let file = FormDatum::FileData(JS::from_rooted(&self.get_file_from_blob(value, filename)));
self.data.borrow_mut().insert(name, vec!(file));
}
@ -115,13 +115,13 @@ impl<'a> FormDataMethods for JSRef<'a, FormData> {
}
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 {
fn get_file_from_blob(&self, value: JSRef<Blob>, filename: Option<DOMString>) -> Temporary<File> {
impl<'a> PrivateFormDataHelpers for &'a FormData {
fn get_file_from_blob(self, value: &Blob, filename: Option<DOMString>) -> Root<File> {
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()));
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::{ElementCast, HTMLElementCast};
use dom::bindings::codegen::InheritTypes::{MouseEventCast, NodeCast};
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary};
use dom::bindings::js::OptionalRootable;
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::document::{Document, DocumentHelpers};
use dom::domtokenlist::DOMTokenList;
use dom::element::{Element, AttributeHandlers, ElementTypeId};
@ -47,7 +46,7 @@ impl HTMLAnchorElementDerived for EventTarget {
impl HTMLAnchorElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLAnchorElement {
document: &Document) -> HTMLAnchorElement {
HTMLAnchorElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLAnchorElement, localName, prefix, document),
@ -58,19 +57,19 @@ impl HTMLAnchorElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLAnchorElement> {
document: &Document) -> Root<HTMLAnchorElement> {
let element = HTMLAnchorElement::new_inherited(localName, prefix, document);
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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods)
}
fn handle_event(&self, event: JSRef<Event>) {
fn handle_event(&self, event: &Event) {
match self.super_type() {
Some(s) => {
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 {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
node.GetTextContent().unwrap()
}
fn SetText(self, value: DOMString) {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
node.SetTextContent(Some(value))
}
fn RelList(self) -> Temporary<DOMTokenList> {
fn RelList(self) -> Root<DOMTokenList> {
self.rel_list.or_init(|| {
DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel"))
})
}
}
impl<'a> Activatable for JSRef<'a, HTMLAnchorElement> {
fn as_element(&self) -> Temporary<Element> {
Temporary::from_rooted(ElementCast::from_ref(*self))
impl<'a> Activatable for &'a HTMLAnchorElement {
fn as_element<'b>(&'b self) -> &'b Element {
ElementCast::from_ref(*self)
}
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
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.
let doc = document_from_node(*self).root();
let doc = document_from_node(*self);
if !doc.r().is_fully_active() {
return;
}
//TODO: Step 2. Check if browsing context is specified and act accordingly.
//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 mut ismap_suffix = None;
if let Some(element) = ElementCast::to_ref(target) {
if target.is_htmlimageelement() && element.has_attribute(&atom!("ismap")) {
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());
ismap_suffix = Some(
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.
let attr = element.get_attribute(&ns!(""), &atom!("href")).root();
let attr = element.get_attribute(&ns!(""), &atom!("href"));
match attr {
Some(ref href) => {
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::bindings::codegen::InheritTypes::HTMLAppletElementDerived;
use dom::bindings::codegen::InheritTypes::HTMLElementCast;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::{AttributeHandlers, ElementTypeId};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -35,7 +35,7 @@ impl HTMLAppletElementDerived for EventTarget {
impl HTMLAppletElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLAppletElement {
document: &Document) -> HTMLAppletElement {
HTMLAppletElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLAppletElement, localName, prefix, document)
@ -45,19 +45,19 @@ impl HTMLAppletElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLAppletElement> {
document: &Document) -> Root<HTMLAppletElement> {
let element = HTMLAppletElement::new_inherited(localName, prefix, document);
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
make_getter!(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> {
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::InheritTypes::{HTMLAreaElementDerived, HTMLElementCast};
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::document::Document;
use dom::domtokenlist::DOMTokenList;
@ -36,7 +36,7 @@ impl HTMLAreaElementDerived for EventTarget {
}
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 {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLAreaElement, localName, prefix, document),
rel_list: Default::default(),
@ -46,15 +46,15 @@ impl HTMLAreaElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLAreaElement> {
document: &Document) -> Root<HTMLAreaElement> {
let element = HTMLAreaElement::new_inherited(localName, prefix, document);
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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods)
}
@ -66,8 +66,8 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLAreaElement> {
}
}
impl<'a> HTMLAreaElementMethods for JSRef<'a, HTMLAreaElement> {
fn RelList(self) -> Temporary<DOMTokenList> {
impl<'a> HTMLAreaElementMethods for &'a HTMLAreaElement {
fn RelList(self) -> Root<DOMTokenList> {
self.rel_list.or_init(|| {
DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel"))
})

View file

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

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLBaseElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLBaseElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLBaseElementDerived for EventTarget {
}
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 {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLBaseElement, localName, prefix, document)
}
@ -35,7 +35,7 @@ impl HTMLBaseElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLBaseElement> {
document: &Document) -> Root<HTMLBaseElement> {
let element = HTMLBaseElement::new_inherited(localName, prefix, document);
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::InheritTypes::{EventTargetCast};
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::document::{Document, DocumentHelpers};
use dom::element::ElementTypeId;
@ -25,6 +25,7 @@ use util::str::{self, DOMString};
use std::borrow::ToOwned;
use std::cell::Cell;
use std::rc::Rc;
use time;
/// 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 {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>)
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document)
-> HTMLBodyElement {
HTMLBodyElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLBodyElement,
@ -57,43 +58,43 @@ impl HTMLBodyElement {
}
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>)
-> Temporary<HTMLBodyElement> {
pub fn new(localName: DOMString, prefix: Option<DOMString>, document: &Document)
-> Root<HTMLBodyElement> {
let element = HTMLBodyElement::new_inherited(localName, prefix, document);
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
make_getter!(BgColor, "bgcolor");
make_setter!(SetBgColor, "bgcolor");
fn GetOnunload(self) -> Option<EventHandlerNonNull> {
let win = window_from_node(self).root();
fn GetOnunload(self) -> Option<Rc<EventHandlerNonNull>> {
let win = window_from_node(self);
win.r().GetOnunload()
}
fn SetOnunload(self, listener: Option<EventHandlerNonNull>) {
let win = window_from_node(self).root();
fn SetOnunload(self, listener: Option<Rc<EventHandlerNonNull>>) {
let win = window_from_node(self);
win.r().SetOnunload(listener)
}
}
pub trait HTMLBodyElementHelpers {
fn get_background_color(&self) -> Option<RGBA>;
fn get_background_color(self) -> Option<RGBA>;
}
impl HTMLBodyElementHelpers for HTMLBodyElement {
fn get_background_color(&self) -> Option<RGBA> {
impl<'a> HTMLBodyElementHelpers for &'a HTMLBodyElement {
fn get_background_color(self) -> Option<RGBA> {
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> {
let element: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let element: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(element as &VirtualMethods)
}
@ -106,15 +107,15 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
return
}
let window = window_from_node(*self).root();
let document = window.r().Document().root();
let window = window_from_node(*self);
let document = window.r().Document();
document.r().set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY);
let ConstellationChan(ref chan) = window.r().constellation_chan();
let event = ConstellationMsg::HeadParsed;
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() {
s.after_set_attr(attr);
}
@ -126,11 +127,11 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
"onbeforeunload", "onhashchange", "onlanguagechange", "onmessage",
"onoffline", "ononline", "onpagehide", "onpageshow", "onpopstate",
"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(),
window.r().get_url(),
window.r().reflector().get_jsobject());
let evtarget: JSRef<EventTarget> =
let evtarget =
if FORWARDED_EVENTS.iter().any(|&event| &**name == event) {
EventTargetCast::from_ref(window.r())
} 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() {
Some(ref s) => s.before_remove_attr(attr),
_ => {}

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLBRElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLBRElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLBRElementDerived for EventTarget {
}
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 {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLBRElement, localName, prefix, document)
}
@ -35,7 +35,7 @@ impl HTMLBRElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLBRElement> {
document: &Document) -> Root<HTMLBRElement> {
let element = HTMLBRElement::new_inherited(localName, prefix, document);
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::InheritTypes::{ElementCast, HTMLElementCast, HTMLButtonElementCast, NodeCast};
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::element::{AttributeHandlers, Element, ElementTypeId};
use dom::element::ActivationElementHelpers;
@ -54,7 +54,7 @@ impl HTMLButtonElementDerived for EventTarget {
impl HTMLButtonElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLButtonElement {
document: &Document) -> HTMLButtonElement {
HTMLButtonElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLButtonElement, localName, prefix, document),
@ -66,15 +66,15 @@ impl HTMLButtonElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLButtonElement> {
document: &Document) -> Root<HTMLButtonElement> {
let element = HTMLButtonElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLButtonElementBinding::Wrap)
}
}
impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
fn Validity(self) -> Temporary<ValidityState> {
let window = window_from_node(self).root();
impl<'a> HTMLButtonElementMethods for &'a HTMLButtonElement {
fn Validity(self) -> Root<ValidityState> {
let window = window_from_node(self);
ValidityState::new(window.r())
}
@ -86,7 +86,7 @@ impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
// https://html.spec.whatwg.org/multipage/#dom-button-type
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();
// https://html.spec.whatwg.org/multipage/#attr-button-type
match &*ty {
@ -129,20 +129,20 @@ impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
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() {
s.after_set_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(true);
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() {
s.before_remove_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(false);
node.set_enabled_state(true);
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);
}
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
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);
}
let node: JSRef<Node> = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.root().r().is_htmlfieldsetelement()) {
let node = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) {
node.check_ancestors_disabled_state_for_form_control();
} else {
node.check_disabled_attribute();
@ -189,20 +189,20 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLButtonElement> {
}
}
impl<'a> FormControl<'a> for JSRef<'a, HTMLButtonElement> {
fn to_element(self) -> JSRef<'a, Element> {
impl<'a> FormControl<'a> for &'a HTMLButtonElement {
fn to_element(self) -> &'a Element {
ElementCast::from_ref(self)
}
}
impl<'a> Activatable for JSRef<'a, HTMLButtonElement> {
fn as_element(&self) -> Temporary<Element> {
Temporary::from_rooted(ElementCast::from_ref(*self))
impl<'a> Activatable for &'a HTMLButtonElement {
fn as_element<'b>(&'b self) -> &'b Element {
ElementCast::from_ref(*self)
}
fn is_instance_activatable(&self) -> bool {
//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())
}
@ -216,14 +216,14 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> {
}
// 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();
match ty {
//https://html.spec.whatwg.org/multipage/#attr-button-type-submit-state
ButtonType::ButtonSubmit => {
self.form_owner().map(|o| {
o.root().r().submit(SubmittedFrom::NotFromFormSubmitMethod,
FormSubmitter::ButtonElement(self.clone()))
o.r().submit(SubmittedFrom::NotFromFormSubmitMethod,
FormSubmitter::ButtonElement(self.clone()))
});
},
_ => ()
@ -233,10 +233,10 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> {
// https://html.spec.whatwg.org/multipage/#implicit-submission
#[allow(unsafe_code)]
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) {
let doc = document_from_node(*self).root();
let node: JSRef<Node> = NodeCast::from_ref(doc.r());
let doc = document_from_node(*self);
let node = NodeCast::from_ref(doc.r());
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() {
return;
}
@ -244,8 +244,7 @@ impl<'a> Activatable for JSRef<'a, HTMLButtonElement> {
// and only then performing actions which may modify the DOM tree
unsafe {
node.query_selector_iter("button[type=submit]".to_owned()).unwrap()
.filter_map(HTMLButtonElementCast::to_temporary)
.map(|t| t.root())
.filter_map(HTMLButtonElementCast::to_root)
.find(|r| r.r().form_owner() == owner)
.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::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, LayoutJS, MutNullableHeap, HeapGCValue, Rootable};
use dom::bindings::js::Temporary;
use dom::bindings::js::Unrooted;
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, HeapGCValue, Root};
use dom::bindings::utils::{Reflectable};
use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
use dom::document::Document;
use dom::element::{Element, AttributeHandlers};
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@ -27,7 +25,7 @@ use dom::virtualmethods::VirtualMethods;
use dom::webglrenderingcontext::{WebGLRenderingContext, LayoutCanvasWebGLRenderingContextHelpers};
use util::str::{DOMString, parse_unsigned_integer};
use js::jsapi::{JSContext};
use js::jsapi::{JSContext, HandleValue};
use js::jsval::JSVal;
use offscreen_gl_context::GLContextAttributes;
@ -58,6 +56,12 @@ pub struct HTMLCanvasElement {
height: Cell<u32>,
}
impl PartialEq for HTMLCanvasElement {
fn eq(&self, other: &HTMLCanvasElement) -> bool {
self as *const HTMLCanvasElement == &*other
}
}
impl HTMLCanvasElementDerived for EventTarget {
fn is_htmlcanvaselement(&self) -> bool {
*self.type_id() ==
@ -69,7 +73,7 @@ impl HTMLCanvasElementDerived for EventTarget {
impl HTMLCanvasElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLCanvasElement {
document: &Document) -> HTMLCanvasElement {
HTMLCanvasElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLCanvasElement, localName, prefix, document),
@ -82,7 +86,7 @@ impl HTMLCanvasElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLCanvasElement> {
document: &Document) -> Root<HTMLCanvasElement> {
let element = HTMLCanvasElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap)
}
@ -139,37 +143,37 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> {
}
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,
cx: *mut JSContext,
attrs: Option<&JSVal>) -> Option<Temporary<WebGLRenderingContext>>;
attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>>;
fn is_valid(self) -> bool;
}
impl<'a> HTMLCanvasElementHelpers for JSRef<'a, HTMLCanvasElement> {
fn get_or_init_2d_context(self) -> Option<Temporary<CanvasRenderingContext2D>> {
impl<'a> HTMLCanvasElementHelpers for &'a HTMLCanvasElement {
fn get_or_init_2d_context(self) -> Option<Root<CanvasRenderingContext2D>> {
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 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() {
CanvasContext::Context2d(context) => Some(Temporary::from_rooted(context)),
CanvasContext::Context2d(context) => Some(context.root()),
_ => None,
}
}
fn get_or_init_webgl_context(self,
cx: *mut JSContext,
attrs: Option<&JSVal>) -> Option<Temporary<WebGLRenderingContext>> {
attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> {
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 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)
} else {
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);
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() {
match context {
CanvasContext::WebGL(context) => Some(Temporary::from_rooted(context)),
CanvasContext::WebGL(context) => Some(context.root()),
_ => None,
}
} 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 {
self.width.get()
}
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)
}
@ -214,38 +218,38 @@ impl<'a> HTMLCanvasElementMethods for JSRef<'a, HTMLCanvasElement> {
}
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)
}
fn GetContext(self,
cx: *mut JSContext,
id: DOMString,
attributes: Vec<JSVal>)
attributes: Vec<HandleValue>)
-> Option<CanvasRenderingContext2DOrWebGLRenderingContext> {
match &*id {
"2d" => {
self.get_or_init_2d_context()
.map(|ctx| CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D(
Unrooted::from_temporary(ctx)))
ctx))
}
"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(
Unrooted::from_temporary(ctx)))
ctx))
}
_ => None
}
}
}
impl<'a> VirtualMethods for JSRef<'a, HTMLCanvasElement> {
impl<'a> VirtualMethods for &'a HTMLCanvasElement {
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)
}
fn before_remove_attr(&self, attr: JSRef<Attr>) {
fn before_remove_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() {
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() {
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::InheritTypes::{ElementCast, NodeCast};
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::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers, ElementHelpers};
@ -20,7 +20,7 @@ use std::iter::{FilterMap, Skip};
use string_cache::{Atom, Namespace};
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]
@ -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),
GlobalRef::Window(window), HTMLCollectionBinding::Wrap)
}
}
impl HTMLCollection {
pub fn create(window: JSRef<Window>, root: JSRef<Node>,
filter: Box<CollectionFilter+'static>) -> Temporary<HTMLCollection> {
HTMLCollection::new(window, CollectionTypeId::Live(JS::from_rooted(root), filter))
pub fn create(window: &Window, root: &Node,
filter: Box<CollectionFilter+'static>) -> Root<HTMLCollection> {
HTMLCollection::new(window, CollectionTypeId::Live(JS::from_ref(root), filter))
}
fn all_elements(window: JSRef<Window>, root: JSRef<Node>,
namespace_filter: Option<Namespace>) -> Temporary<HTMLCollection> {
fn all_elements(window: &Window, root: &Node,
namespace_filter: Option<Namespace>) -> Root<HTMLCollection> {
#[jstraceable]
struct AllElementFilter {
namespace_filter: Option<Namespace>
}
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 {
None => true,
Some(ref namespace) => *elem.namespace() == *namespace
@ -74,8 +74,8 @@ impl HTMLCollection {
HTMLCollection::create(window, root, box filter)
}
pub fn by_tag_name(window: JSRef<Window>, root: JSRef<Node>, tag: DOMString)
-> Temporary<HTMLCollection> {
pub fn by_tag_name(window: &Window, root: &Node, tag: DOMString)
-> Root<HTMLCollection> {
if tag == "*" {
return HTMLCollection::all_elements(window, root, None);
}
@ -86,7 +86,7 @@ impl HTMLCollection {
ascii_lower_tag: Atom,
}
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() {
*elem.local_name() == self.ascii_lower_tag
} else {
@ -101,8 +101,8 @@ impl HTMLCollection {
HTMLCollection::create(window, root, box filter)
}
pub fn by_tag_name_ns(window: JSRef<Window>, root: JSRef<Node>, tag: DOMString,
maybe_ns: Option<DOMString>) -> Temporary<HTMLCollection> {
pub fn by_tag_name_ns(window: &Window, root: &Node, tag: DOMString,
maybe_ns: Option<DOMString>) -> Root<HTMLCollection> {
let namespace_filter = match maybe_ns {
Some(ref namespace) if namespace == &"*" => None,
ns => Some(namespace::from_domstring(ns)),
@ -117,7 +117,7 @@ impl HTMLCollection {
namespace_filter: Option<Namespace>
}
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 {
Some(ref namespace) => {
*elem.namespace() == *namespace
@ -134,14 +134,14 @@ impl HTMLCollection {
HTMLCollection::create(window, root, box filter)
}
pub fn by_class_name(window: JSRef<Window>, root: JSRef<Node>, classes: DOMString)
-> Temporary<HTMLCollection> {
pub fn by_class_name(window: &Window, root: &Node, classes: DOMString)
-> Root<HTMLCollection> {
#[jstraceable]
struct ClassNameFilter {
classes: Vec<Atom>
}
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))
}
}
@ -153,30 +153,30 @@ impl HTMLCollection {
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]
struct 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))
}
}
HTMLCollection::create(window, root, box ElementChildFilter)
}
fn traverse(root: JSRef<Node>)
fn traverse(root: &Node)
-> FilterMap<Skip<TreeIterator>,
fn(Temporary<Node>) -> Option<Temporary<Element>>> {
fn to_temporary(node: Temporary<Node>) -> Option<Temporary<Element>> {
ElementCast::to_temporary(node)
fn(Root<Node>) -> Option<Root<Element>>> {
fn to_temporary(node: Root<Node>) -> Option<Root<Element>> {
ElementCast::to_root(node)
}
root.traverse_preorder()
.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
fn Length(self) -> u32 {
match self.collection {
@ -184,30 +184,29 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
CollectionTypeId::Live(ref root, ref filter) => {
let root = root.root();
HTMLCollection::traverse(root.r())
.filter(|element| filter.filter(element.root().r(), root.r()))
.filter(|element| filter.filter(element.r(), root.r()))
.count() as u32
}
}
}
// 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;
match self.collection {
CollectionTypeId::Static(ref elems) => elems
.get(index)
.map(|elem| Temporary::from_rooted(elem.clone())),
.get(index).map(|t| t.root()),
CollectionTypeId::Live(ref root, ref filter) => {
let root = root.root();
HTMLCollection::traverse(root.r())
.filter(|element| filter.filter(element.root().r(), root.r()))
.filter(|element| filter.filter(element.r(), root.r()))
.nth(index)
}
}
}
// 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.
if key.is_empty() {
return None;
@ -219,28 +218,25 @@ impl<'a> HTMLCollectionMethods for JSRef<'a, HTMLCollection> {
.map(|elem| elem.root())
.find(|elem| {
elem.r().get_string_attribute(&atom!("name")) == key ||
elem.r().get_string_attribute(&atom!("id")) == key })
.map(|maybe_elem| Temporary::from_rooted(maybe_elem.r())),
elem.r().get_string_attribute(&atom!("id")) == key }),
CollectionTypeId::Live(ref root, ref filter) => {
let root = root.root();
HTMLCollection::traverse(root.r())
.map(|element| element.root())
.filter(|element| filter.filter(element.r(), root.r()))
.find(|elem| {
elem.r().get_string_attribute(&atom!("name")) == 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);
*found = maybe_elem.is_some();
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);
*found = maybe_elem.is_some();
maybe_elem

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLDataElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLDataElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLDataElementDerived for EventTarget {
impl HTMLDataElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLDataElement {
document: &Document) -> HTMLDataElement {
HTMLDataElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLDataElement, localName, prefix, document)
}
@ -37,7 +37,7 @@ impl HTMLDataElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDataElement> {
document: &Document) -> Root<HTMLDataElement> {
let element = HTMLDataElement::new_inherited(localName, prefix, document);
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::InheritTypes::{HTMLDataListElementDerived, HTMLOptionElementDerived};
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::js::{JSRef, Rootable, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::Element;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -32,7 +32,7 @@ impl HTMLDataListElementDerived for EventTarget {
impl HTMLDataListElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLDataListElement {
document: &Document) -> HTMLDataListElement {
HTMLDataListElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLDataListElement, localName, prefix, document)
@ -42,24 +42,24 @@ impl HTMLDataListElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDataListElement> {
document: &Document) -> Root<HTMLDataListElement> {
let element = HTMLDataListElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLDataListElementBinding::Wrap)
}
}
impl<'a> HTMLDataListElementMethods for JSRef<'a, HTMLDataListElement> {
fn Options(self) -> Temporary<HTMLCollection> {
impl<'a> HTMLDataListElementMethods for &'a HTMLDataListElement {
fn Options(self) -> Root<HTMLCollection> {
#[jstraceable]
struct 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()
}
}
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
let filter = box HTMLDataListOptionsFilter;
let window = window_from_node(node).root();
let window = window_from_node(node);
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::InheritTypes::HTMLDialogElementDerived;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -34,7 +34,7 @@ impl HTMLDialogElementDerived for EventTarget {
impl HTMLDialogElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLDialogElement {
document: &Document) -> HTMLDialogElement {
HTMLDialogElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLDialogElement, localName, prefix, document),
@ -45,13 +45,13 @@ impl HTMLDialogElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDialogElement> {
document: &Document) -> Root<HTMLDialogElement> {
let element = HTMLDialogElement::new_inherited(localName, prefix, document);
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
make_bool_getter!(Open);

View file

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

View file

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

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLDListElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLDListElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -26,7 +26,7 @@ impl HTMLDListElementDerived for EventTarget {
}
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 {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLDListElement, localName, prefix, document)
@ -36,7 +36,7 @@ impl HTMLDListElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLDListElement> {
document: &Document) -> Root<HTMLDListElement> {
let element = HTMLDListElement::new_inherited(localName, prefix, document);
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::{EventTargetCast, HTMLInputElementCast, NodeCast};
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::Error::Syntax;
use dom::bindings::utils::Reflectable;
@ -37,6 +37,7 @@ use string_cache::Atom;
use std::borrow::ToOwned;
use std::default::Default;
use std::intrinsics;
use std::rc::Rc;
#[dom_struct]
pub struct HTMLElement {
@ -45,6 +46,12 @@ pub struct HTMLElement {
dataset: MutNullableHeap<JS<DOMStringMap>>,
}
impl PartialEq for HTMLElement {
fn eq(&self, other: &HTMLElement) -> bool {
self as *const HTMLElement == &*other
}
}
impl HTMLElementDerived for EventTarget {
fn is_htmlelement(&self) -> bool {
match *self.type_id() {
@ -58,7 +65,7 @@ impl HTMLElement {
pub fn new_inherited(type_id: HTMLElementTypeId,
tag_name: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLElement {
document: &Document) -> HTMLElement {
HTMLElement {
element:
Element::new_inherited(ElementTypeId::HTMLElement(type_id), tag_name, ns!(HTML), prefix, document),
@ -68,7 +75,7 @@ impl HTMLElement {
}
#[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);
Node::reflect_node(box element, document, HTMLElementBinding::Wrap)
}
@ -79,9 +86,9 @@ trait PrivateHTMLElementHelpers {
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 {
let eventtarget: JSRef<EventTarget> = EventTargetCast::from_ref(self);
let eventtarget = EventTargetCast::from_ref(self);
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")) {
let attr = attr.root();
let attr = attr.r();
let value = attr.value();
let is_true = match *value {
@ -124,10 +130,10 @@ impl<'a> PrivateHTMLElementHelpers for JSRef<'a, HTMLElement> {
}
}
impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> {
fn Style(self) -> Temporary<CSSStyleDeclaration> {
impl<'a> HTMLElementMethods for &'a HTMLElement {
fn Style(self) -> Root<CSSStyleDeclaration> {
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)
})
}
@ -145,39 +151,39 @@ impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> {
global_event_handlers!(NoOnload);
// 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))
}
fn GetOnload(self) -> Option<EventHandlerNonNull> {
fn GetOnload(self) -> Option<Rc<EventHandlerNonNull>> {
if self.is_body_or_frameset() {
let win = window_from_node(self).root();
let win = window_from_node(self);
win.r().GetOnload()
} else {
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
let target = EventTargetCast::from_ref(self);
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() {
let win = window_from_node(self).root();
let win = window_from_node(self);
win.r().SetOnload(listener)
} else {
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
let target = EventTargetCast::from_ref(self);
target.set_event_handler_common("load", listener)
}
}
// https://html.spec.whatwg.org/multipage/#dom-click
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 i.Disabled() {
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 ?
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) {
// TODO: Mark the element as locked for focus and run the focusing steps.
// https://html.spec.whatwg.org/multipage/#focusing-steps
let element: JSRef<Element> = ElementCast::from_ref(self);
let document = document_from_node(self).root();
let element = ElementCast::from_ref(self);
let document = document_from_node(self);
let document = document.r();
document.begin_focus_transaction();
document.request_focus(element);
@ -197,12 +203,12 @@ impl<'a> HTMLElementMethods for JSRef<'a, HTMLElement> {
// https://html.spec.whatwg.org/multipage/#dom-blur
fn Blur(self) {
// TODO: Run the unfocusing steps.
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
if !node.get_focus_state() {
return;
}
// 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();
// If `request_focus` is not called, focus will be set to None.
document.r().commit_focus_transaction(FocusType::Element);
@ -229,22 +235,21 @@ fn to_snake_case(name: DOMString) -> DOMString {
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 {
if name.chars()
.skip_while(|&ch| ch != '\u{2d}')
.nth(1).map_or(false, |ch| ch >= 'a' && ch <= 'z') {
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)
}
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));
element.get_attribute(&ns!(""), &local_name).map(|attr| {
let attr = attr.root();
// FIXME(https://github.com/rust-lang/rust/issues/23338)
let attr = attr.r();
let value = attr.value();
@ -253,19 +258,19 @@ impl<'a> HTMLElementCustomAttributeHelpers for JSRef<'a, HTMLElement> {
}
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));
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> {
let element: &JSRef<Element> = ElementCast::from_borrowed_ref(self);
let element: &&Element = ElementCast::from_borrowed_ref(self);
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() {
s.before_remove_attr(attr);
}
@ -278,18 +283,18 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLElement> {
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() {
s.after_set_attr(attr);
}
let name = attr.local_name();
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(),
window.r().get_url(),
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,
&name[2..],
(**attr.value()).to_owned());

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLEmbedElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLEmbedElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -26,7 +26,7 @@ impl HTMLEmbedElementDerived for EventTarget {
}
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 {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLEmbedElement, localName, prefix, document)
}
@ -35,7 +35,7 @@ impl HTMLEmbedElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLEmbedElement> {
document: &Document) -> Root<HTMLEmbedElement> {
let element = HTMLEmbedElement::new_inherited(localName, prefix, document);
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::InheritTypes::{HTMLFieldSetElementDerived, NodeCast};
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::element::{AttributeHandlers, Element, ElementHelpers};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -37,7 +37,7 @@ impl HTMLFieldSetElementDerived for EventTarget {
impl HTMLFieldSetElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLFieldSetElement {
document: &Document) -> HTMLFieldSetElement {
HTMLFieldSetElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLFieldSetElement, localName, prefix, document)
@ -47,32 +47,32 @@ impl HTMLFieldSetElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLFieldSetElement> {
document: &Document) -> Root<HTMLFieldSetElement> {
let element = HTMLFieldSetElement::new_inherited(localName, prefix, document);
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
fn Elements(self) -> Temporary<HTMLCollection> {
fn Elements(self) -> Root<HTMLCollection> {
#[jstraceable]
struct 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",
"keygen", "object", "output", "select", "textarea"];
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 window = window_from_node(node).root();
let window = window_from_node(node);
HTMLCollection::create(window.r(), node, filter)
}
fn Validity(self) -> Temporary<ValidityState> {
let window = window_from_node(self).root();
fn Validity(self) -> Root<ValidityState> {
let window = window_from_node(self);
ValidityState::new(window.r())
}
@ -83,34 +83,31 @@ impl<'a> HTMLFieldSetElementMethods for JSRef<'a, HTMLFieldSetElement> {
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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
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() {
s.after_set_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(true);
node.set_enabled_state(false);
let maybe_legend = node.children()
.map(|node| node.root())
.find(|node| node.r().is_htmllegendelement());
for child in node.children() {
let child = child.root();
if Some(child.r()) == maybe_legend.r() {
continue;
}
for descendant in child.r().traverse_preorder() {
let descendant = descendant.root();
match descendant.r().type_id() {
NodeTypeId::Element(
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() {
s.before_remove_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(false);
node.set_enabled_state(true);
let maybe_legend = node.children()
.map(|node| node.root())
.find(|node| node.r().is_htmllegendelement());
for child in node.children() {
let child = child.root();
if Some(child.r()) == maybe_legend.r() {
continue;
}
for descendant in child.r().traverse_preorder() {
let descendant = descendant.root();
match descendant.r().type_id() {
NodeTypeId::Element(
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::HTMLFontElementMethods;
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLFontElementDerived};
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -33,7 +33,7 @@ impl HTMLFontElementDerived for EventTarget {
}
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 {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLFontElement, localName, prefix, document),
color: Cell::new(None),
@ -43,24 +43,24 @@ impl HTMLFontElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLFontElement> {
document: &Document) -> Root<HTMLFontElement> {
let element = HTMLFontElement::new_inherited(localName, prefix, document);
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_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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement = HTMLElementCast::from_borrowed_ref(self);
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() {
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() {
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::{HTMLTextAreaElementCast, NodeCast};
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::element::{Element, AttributeHandlers};
use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable};
@ -49,6 +49,12 @@ pub struct HTMLFormElement {
marked_for_reset: Cell<bool>,
}
impl PartialEq for HTMLFormElement {
fn eq(&self, other: &HTMLFormElement) -> bool {
self as *const HTMLFormElement == &*other
}
}
impl HTMLFormElementDerived for EventTarget {
fn is_htmlformelement(&self) -> bool {
*self.type_id() ==
@ -60,7 +66,7 @@ impl HTMLFormElementDerived for EventTarget {
impl HTMLFormElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLFormElement {
document: &Document) -> HTMLFormElement {
HTMLFormElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLFormElement, localName, prefix, document),
marked_for_reset: Cell::new(false),
@ -70,13 +76,13 @@ impl HTMLFormElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLFormElement> {
document: &Document) -> Root<HTMLFormElement> {
let element = HTMLFormElement::new_inherited(localName, prefix, document);
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
make_getter!(AcceptCharset, "accept-charset");
@ -165,19 +171,19 @@ pub trait HTMLFormElementHelpers {
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) {
// Step 1
let doc = document_from_node(self).root();
let win = window_from_node(self).root();
let doc = document_from_node(self);
let win = window_from_node(self);
let base = doc.r().url();
// TODO: Handle browsing contexts
// TODO: Handle validation
let event = Event::new(GlobalRef::Window(win.r()),
"submit".to_owned(),
EventBubbles::Bubbles,
EventCancelable::Cancelable).root();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
EventCancelable::Cancelable);
let target = EventTargetCast::from_ref(self);
event.r().fire(target);
if event.r().DefaultPrevented() {
return;
@ -262,16 +268,15 @@ impl<'a> HTMLFormElementHelpers for JSRef<'a, HTMLFormElement> {
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
// by the form, but good enough until html5ever lands
let data_set = node.traverse_preorder().filter_map(|child| {
let child = child.root();
if child.r().get_disabled_state() {
return None;
}
if child.r().ancestors()
.any(|a| HTMLDataListElementCast::to_temporary(a).is_some()) {
.any(|a| HTMLDataListElementCast::to_root(a).is_some()) {
return None;
}
// 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);
}
let win = window_from_node(self).root();
let win = window_from_node(self);
let event = Event::new(GlobalRef::Window(win.r()),
"reset".to_owned(),
EventBubbles::Bubbles,
EventCancelable::Cancelable).root();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
EventCancelable::Cancelable);
let target = EventTargetCast::from_ref(self);
event.r().fire(target);
if event.r().DefaultPrevented() {
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
// by the form, but good enough until html5ever lands
for child in node.traverse_preorder() {
let child = child.root();
match child.r().type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
let input = HTMLInputElementCast::to_ref(child.r()).unwrap();
@ -434,9 +438,9 @@ pub enum FormMethod {
#[derive(Copy, Clone)]
pub enum FormSubmitter<'a> {
FormElement(JSRef<'a, HTMLFormElement>),
InputElement(JSRef<'a, HTMLInputElement>),
ButtonElement(JSRef<'a, HTMLButtonElement>)
FormElement(&'a HTMLFormElement),
InputElement(&'a HTMLInputElement),
ButtonElement(&'a HTMLButtonElement)
// TODO: image submit, etc etc
}
@ -525,28 +529,27 @@ impl<'a> FormSubmitter<'a> {
pub trait FormControl<'a> : Copy + Sized {
// FIXME: This is wrong (https://github.com/servo/servo/issues/3553)
// 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
let elem = self.to_element();
let owner = elem.get_string_attribute(&atom!("form"));
if !owner.is_empty() {
let doc = document_from_node(elem).root();
let owner = doc.r().GetElementById(owner).root();
let doc = document_from_node(elem);
let owner = doc.r().GetElementById(owner);
match owner {
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() {
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() {
let ancestor = ancestor.root();
if let Some(ancestor) = HTMLFormElementCast::to_ref(ancestor.r()) {
return Some(Temporary::from_rooted(ancestor))
return Some(Root::from_ref(ancestor))
}
}
None
@ -558,19 +561,19 @@ pub trait FormControl<'a> : Copy + Sized {
owner: OwnerFn)
-> DOMString
where InputFn: Fn(Self) -> DOMString,
OwnerFn: Fn(JSRef<HTMLFormElement>) -> DOMString
OwnerFn: Fn(&HTMLFormElement) -> DOMString
{
if self.to_element().has_attribute(attr) {
input(self)
} 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> {
Some(HTMLElementCast::from_borrowed_ref(self) as &VirtualMethods)
}

View file

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

View file

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

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLHeadElementBinding;
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLHeadElementDerived};
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -30,7 +30,7 @@ impl HTMLHeadElementDerived for EventTarget {
impl HTMLHeadElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLHeadElement {
document: &Document) -> HTMLHeadElement {
HTMLHeadElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLHeadElement, localName, prefix, document)
}
@ -39,15 +39,15 @@ impl HTMLHeadElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLHeadElement> {
document: &Document) -> Root<HTMLHeadElement> {
let element = HTMLHeadElement::new_inherited(localName, prefix, document);
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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
Some(htmlelement as &VirtualMethods)
}
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::InheritTypes::HTMLHeadingElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -39,7 +39,7 @@ impl HTMLHeadingElementDerived for EventTarget {
impl HTMLHeadingElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>,
document: &Document,
level: HeadingLevel) -> HTMLHeadingElement {
HTMLHeadingElement {
htmlelement:
@ -51,8 +51,8 @@ impl HTMLHeadingElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>,
level: HeadingLevel) -> Temporary<HTMLHeadingElement> {
document: &Document,
level: HeadingLevel) -> Root<HTMLHeadingElement> {
let element = HTMLHeadingElement::new_inherited(localName, prefix, document, level);
Node::reflect_node(box element, document, HTMLHeadingElementBinding::Wrap)
}

View file

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

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLHtmlElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLHtmlElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLHtmlElementDerived for EventTarget {
}
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 {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLHtmlElement, localName, prefix, document)
}
@ -35,7 +35,7 @@ impl HTMLHtmlElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLHtmlElement> {
document: &Document) -> Root<HTMLHtmlElement> {
let element = HTMLHtmlElement::new_inherited(localName, prefix, document);
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::Error::NotSupported;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, OptionalRootable, Rootable, Temporary};
use dom::bindings::js::{Root};
use dom::customevent::CustomEvent;
use dom::document::Document;
use dom::element::{self, AttributeHandlers, Element};
use dom::event::{Event, EventHelpers};
use dom::element::{self, AttributeHandlers};
use dom::event::EventHelpers;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@ -39,6 +39,8 @@ use std::borrow::ToOwned;
use std::cell::Cell;
use url::{Url, UrlParser};
use util::str::{self, LengthOrPercentageOrAuto};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;
enum SandboxAllowance {
AllowNothing = 0x00,
@ -82,19 +84,19 @@ pub trait RawHTMLIFrameElementHelpers {
fn get_height(&self) -> LengthOrPercentageOrAuto;
}
impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
impl<'a> HTMLIFrameElementHelpers for &'a HTMLIFrameElement {
fn is_sandboxed(self) -> bool {
self.sandbox.get().is_some()
}
fn get_url(self) -> Option<Url> {
let element: JSRef<Element> = ElementCast::from_ref(self);
element.get_attribute(&ns!(""), &atom!("src")).root().and_then(|src| {
let element = ElementCast::from_ref(self);
element.get_attribute(&ns!(""), &atom!("src")).and_then(|src| {
let url = src.r().value();
if url.is_empty() {
None
} else {
let window = window_from_node(self).root();
let window = window_from_node(self);
UrlParser::new().base_url(&window.r().get_url())
.parse(&url).ok()
}
@ -103,7 +105,7 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
fn generate_new_subpage_id(self) -> (SubpageId, Option<SubpageId>) {
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();
self.subpage_id.set(Some(subpage_id));
(subpage_id, old_subpage_id)
@ -116,7 +118,7 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
IFrameUnsandboxed
};
let window = window_from_node(self).root();
let window = window_from_node(self);
let window = window.r();
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());
if self.Mozbrowser() {
let window = window_from_node(self).root();
let window = window_from_node(self);
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()),
event.name().to_owned(),
true,
true,
event.detail().to_jsval(cx)).root();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
let event: JSRef<Event> = EventCast::from_ref(custom_event.r());
detail.handle());
let target = EventTargetCast::from_ref(self);
let event = EventCast::from_ref(custom_event.r());
event.fire(target);
}
}
@ -176,7 +180,7 @@ impl RawHTMLIFrameElementHelpers for HTMLIFrameElement {
element::get_attr_for_layout(ElementCast::from_actual(&*self),
&ns!(""),
&atom!("width")).map(|attribute| {
str::parse_length(&**(*attribute.unsafe_get()).value())
str::parse_length(&**(*attribute.unsafe_get()).value_for_layout())
}).unwrap_or(LengthOrPercentageOrAuto::Auto)
}
}
@ -187,7 +191,7 @@ impl RawHTMLIFrameElementHelpers for HTMLIFrameElement {
element::get_attr_for_layout(ElementCast::from_actual(&*self),
&ns!(""),
&atom!("height")).map(|attribute| {
str::parse_length(&**(*attribute.unsafe_get()).value())
str::parse_length(&**(*attribute.unsafe_get()).value_for_layout())
}).unwrap_or(LengthOrPercentageOrAuto::Auto)
}
}
@ -196,7 +200,7 @@ impl RawHTMLIFrameElementHelpers for HTMLIFrameElement {
impl HTMLIFrameElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLIFrameElement {
document: &Document) -> HTMLIFrameElement {
HTMLIFrameElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLIFrameElement, localName, prefix, document),
@ -209,7 +213,7 @@ impl HTMLIFrameElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLIFrameElement> {
document: &Document) -> Root<HTMLIFrameElement> {
let element = HTMLIFrameElement::new_inherited(localName, prefix, document);
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 {
let element: JSRef<Element> = ElementCast::from_ref(self);
let element = ElementCast::from_ref(self);
element.get_string_attribute(&atom!("src"))
}
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)
}
fn Sandbox(self) -> DOMString {
let element: JSRef<Element> = ElementCast::from_ref(self);
let element = ElementCast::from_ref(self);
element.get_string_attribute(&atom!("sandbox"))
}
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);
}
fn GetContentWindow(self) -> Option<Temporary<Window>> {
fn GetContentWindow(self) -> Option<Root<Window>> {
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 children = window.page().children.borrow();
children.iter().find(|page| {
let window = page.window().root();
let window = page.window();
window.r().subpage() == Some(subpage_id)
}).map(|page| page.window())
})
}
fn GetContentDocument(self) -> Option<Temporary<Document>> {
self.GetContentWindow().root().and_then(|window| {
fn GetContentDocument(self) -> Option<Root<Document>> {
self.GetContentWindow().and_then(|window| {
let self_url = match self.get_url() {
Some(self_url) => self_url,
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) {
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
fn Mozbrowser(self) -> bool {
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"))
} else {
false
@ -293,7 +297,7 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
fn SetMozbrowser(self, value: bool) -> ErrorResult {
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);
}
Ok(())
@ -302,9 +306,9 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goBack
fn GoBack(self) -> Fallible<()> {
if self.Mozbrowser() {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
if node.is_in_doc() {
let window = window_from_node(self).root();
let window = window_from_node(self);
let window = window.r();
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
fn GoForward(self) -> Fallible<()> {
if self.Mozbrowser() {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
if node.is_in_doc() {
let window = window_from_node(self).root();
let window = window_from_node(self);
let window = window.r();
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");
}
impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
impl<'a> VirtualMethods for &'a HTMLIFrameElement {
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)
}
fn after_set_attr(&self, attr: JSRef<Attr>) {
fn after_set_attr(&self, attr: &Attr) {
if let Some(ref s) = self.super_type() {
s.after_set_attr(attr);
}
@ -392,7 +396,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
self.sandbox.set(Some(modes));
}
&atom!("src") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
if node.is_in_doc() {
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() {
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
match (self.containing_page_pipeline_id(), self.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 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,
HTMLImageElementDerived};
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::document::{Document, DocumentHelpers};
use dom::element::Element;
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -51,7 +50,7 @@ pub trait HTMLImageElementHelpers {
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>{
self.url.borrow().clone()
}
@ -79,7 +78,7 @@ impl Responder {
impl ImageResponder for Responder {
fn respond(&self, image: ImageResponse) {
// Update the image field
let element = self.element.to_temporary().root();
let element = self.element.root();
let element_ref = element.r();
*element_ref.image.borrow_mut() = match image {
ImageResponse::Loaded(image) | ImageResponse::PlaceholderLoaded(image) => {
@ -90,17 +89,17 @@ impl ImageResponder for Responder {
// Mark the node dirty
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);
// 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()),
"load".to_owned(),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable).root();
EventCancelable::NotCancelable);
let event = event.r();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(node);
let target = EventTargetCast::from_ref(node);
event.fire(target);
// 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
/// prefetching the image. This method must be called after `src` is changed.
fn update_image(self, value: Option<(DOMString, &Url)>) {
let node: JSRef<Node> = NodeCast::from_ref(self);
let document = node.owner_doc().root();
let window = document.r().window().root();
let node = NodeCast::from_ref(self);
let document = node.owner_doc();
let window = document.r().window();
let window = window.r();
let image_cache = window.image_cache_task();
match value {
@ -137,7 +136,7 @@ impl<'a> PrivateHTMLImageElementHelpers for JSRef<'a, 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 {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLImageElement, localName, prefix, document),
url: DOMRefCell::new(None),
@ -148,7 +147,7 @@ impl HTMLImageElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLImageElement> {
document: &Document) -> Root<HTMLImageElement> {
let element = HTMLImageElement::new_inherited(localName, prefix, document);
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_setter!(SetAlt, "alt");
@ -190,29 +189,29 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
make_bool_getter!(IsMap);
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())
}
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();
rect.size.width.to_px() as 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)
}
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();
rect.size.height.to_px() as 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)
}
@ -264,20 +263,20 @@ impl<'a> HTMLImageElementMethods for JSRef<'a, HTMLImageElement> {
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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
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() {
s.after_set_attr(attr);
}
match attr.local_name() {
&atom!("src") => {
let window = window_from_node(*self).root();
let window = window_from_node(*self);
let url = window.r().get_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() {
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::KeyboardEventCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, LayoutJS, MutNullableHeap};
use dom::bindings::js::{OptionalRootable, ResultRootable, Root, Rootable};
use dom::bindings::js::{RootedReference, Temporary};
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
use dom::bindings::js::{Root};
use dom::bindings::js::RootedReference;
use dom::document::{Document, DocumentHelpers};
use dom::element::{AttributeHandlers, Element};
use dom::element::{RawLayoutElementHelpers, ActivationElementHelpers};
@ -77,6 +77,12 @@ pub struct HTMLInputElement {
activation_state: DOMRefCell<InputActivationState>,
}
impl PartialEq for HTMLInputElement {
fn eq(&self, other: &HTMLInputElement) -> bool {
self as *const HTMLInputElement == &*other
}
}
#[jstraceable]
#[must_root]
struct InputActivationState {
@ -114,8 +120,8 @@ impl HTMLInputElementDerived for EventTarget {
static DEFAULT_INPUT_SIZE: u32 = 20;
impl HTMLInputElement {
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLInputElement {
let chan = document.window().root().r().constellation_chan();
fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLInputElement {
let chan = document.window().r().constellation_chan();
HTMLInputElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLInputElement, localName, prefix, document),
input_type: Cell::new(InputType::InputText),
@ -133,7 +139,7 @@ impl HTMLInputElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLInputElement> {
document: &Document) -> Root<HTMLInputElement> {
let element = HTMLInputElement::new_inherited(localName, prefix, document);
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
make_bool_getter!(Disabled);
@ -335,27 +341,26 @@ pub trait HTMLInputElementHelpers {
fn radio_group_updated(self, group: Option<&str>);
fn get_radio_group_name(self) -> Option<String>;
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 mutable(self) -> bool;
fn reset(self);
}
#[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
let owner = broadcaster.form_owner().root();
let doc = document_from_node(broadcaster).root();
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r());
let owner = broadcaster.form_owner();
let doc = document_from_node(broadcaster);
let doc_node = NodeCast::from_ref(doc.r());
// This function is a workaround for lifetime constraint difficulties.
fn do_broadcast<'a>(doc_node: JSRef<'a, Node>, broadcaster: JSRef<'a, HTMLInputElement>,
owner: Option<JSRef<'a, HTMLFormElement>>, group: Option<&str>) {
fn do_broadcast(doc_node: &Node, broadcaster: &HTMLInputElement,
owner: Option<&HTMLFormElement>, group: Option<&str>) {
// There is no DOM tree manipulation here, so this is safe
let iter = unsafe {
doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_temporary)
.map(|t| t.root())
.filter_map(HTMLInputElementCast::to_root)
.filter(|r| in_same_group(r.r(), owner, group) && broadcaster != r.r())
};
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)
}
fn in_same_group<'a,'b>(other: JSRef<'a, HTMLInputElement>,
owner: Option<JSRef<'b, HTMLFormElement>>,
fn in_same_group<'a,'b>(other: &'a HTMLInputElement,
owner: Option<&'b HTMLFormElement>,
group: Option<&str>) -> bool {
let other_owner = other.form_owner().root();
let other_owner = other.form_owner();
let other_owner = other_owner.r();
other.input_type.get() == InputType::InputRadio &&
// 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) {
let doc = document_from_node(self).root();
let node: JSRef<Node> = NodeCast::from_ref(self);
let doc = document_from_node(self);
let node = NodeCast::from_ref(self);
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> {
//TODO: determine form owner
let elem: JSRef<Element> = ElementCast::from_ref(self);
let elem = ElementCast::from_ref(self);
elem.get_attribute(&ns!(""), &atom!("name"))
.root()
.map(|name| name.r().Value())
}
@ -423,7 +427,7 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> {
//TODO: dispatch change event
}
fn get_size(&self) -> u32 {
fn get_size(self) -> u32 {
self.size.get()
}
@ -435,7 +439,7 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> {
fn mutable(self) -> bool {
// https://html.spec.whatwg.org/multipage/#the-input-element: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())
}
@ -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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
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() {
s.after_set_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(true);
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() {
s.before_remove_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(false);
node.set_enabled_state(true);
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);
}
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
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);
}
let node: JSRef<Node> = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.root().r().is_htmlfieldsetelement()) {
let node = NodeCast::from_ref(*self);
if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) {
node.check_ancestors_disabled_state_for_form_control();
} else {
node.check_disabled_attribute();
}
}
fn handle_event(&self, event: JSRef<Event>) {
fn handle_event(&self, event: &Event) {
if let Some(s) = self.super_type() {
s.handle_event(event);
}
@ -617,12 +621,12 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
//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));
} else if &*event.Type() == "keydown" && !event.DefaultPrevented() &&
(self.input_type.get() == InputType::InputText ||
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| {
// This can't be inlined, as holding on to textinput.borrow_mut()
// 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> {
fn to_element(self) -> JSRef<'a, Element> {
impl<'a> FormControl<'a> for &'a HTMLInputElement {
fn to_element(self) -> &'a Element {
ElementCast::from_ref(self)
}
}
impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
fn as_element(&self) -> Temporary<Element> {
Temporary::from_rooted(ElementCast::from_ref(*self))
impl<'a> Activatable for &'a HTMLInputElement {
fn as_element<'b>(&'b self) -> &'b Element {
ElementCast::from_ref(*self)
}
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
InputType::InputRadio => {
//TODO: if not in document, use root ancestor instead of document
let owner = self.form_owner().root();
let doc = document_from_node(*self).root();
let doc_node: JSRef<Node> = NodeCast::from_ref(doc.r());
let owner = self.form_owner();
let doc = document_from_node(*self);
let doc_node = NodeCast::from_ref(doc.r());
let group = self.get_radio_group_name();;
// Safe since we only manipulate the DOM tree after finding an element
let checked_member = unsafe {
doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_temporary)
.map(|t| t.root())
.filter_map(HTMLInputElementCast::to_root)
.find(|r| {
in_same_group(r.r(), owner.r(), group.as_ref().map(|gr| &**gr)) &&
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();
self.SetChecked(true);
}
@ -748,7 +751,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
InputType::InputRadio => {
// We want to restore state only if the element had been changed in the first place
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();
match old_checked {
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
fn activation_behavior(&self, _event: JSRef<Event>, _target: JSRef<EventTarget>) {
fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
let ty = self.input_type.get();
if self.activation_state.borrow().old_type != ty {
// 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)
if self.mutable() /* and document owner is fully active */ {
self.form_owner().map(|o| {
o.root().r().submit(SubmittedFrom::NotFromFormSubmitMethod,
FormSubmitter::InputElement(self.clone()))
o.r().submit(SubmittedFrom::NotFromFormSubmitMethod,
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)
if self.mutable() /* and document owner is fully active */ {
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/#radio-button-state-(type=radio):activation-behavior
if self.mutable() {
let win = window_from_node(*self).root();
let win = window_from_node(*self);
let event = Event::new(GlobalRef::Window(win.r()),
"input".to_owned(),
EventBubbles::Bubbles,
EventCancelable::NotCancelable).root();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(*self);
EventCancelable::NotCancelable);
let target = EventTargetCast::from_ref(*self);
event.r().fire(target);
let event = Event::new(GlobalRef::Window(win.r()),
"change".to_owned(),
EventBubbles::Bubbles,
EventCancelable::NotCancelable).root();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(*self);
EventCancelable::NotCancelable);
let target = EventTargetCast::from_ref(*self);
event.r().fire(target);
}
},
@ -827,15 +830,15 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// https://html.spec.whatwg.org/multipage/#implicit-submission
#[allow(unsafe_code)]
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool) {
let doc = document_from_node(*self).root();
let node: JSRef<Node> = NodeCast::from_ref(doc.r());
let doc = document_from_node(*self);
let node = NodeCast::from_ref(doc.r());
let owner = self.form_owner();
let form = match owner {
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() {
return;
}
@ -844,8 +847,7 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
let submit_button;
unsafe {
submit_button = node.query_selector_iter("input[type=submit]".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_temporary)
.map(|t| t.root())
.filter_map(HTMLInputElementCast::to_root)
.find(|r| r.r().form_owner() == owner);
}
match submit_button {
@ -859,9 +861,8 @@ impl<'a> Activatable for JSRef<'a, HTMLInputElement> {
// Safe because we don't perform any DOM modification
// until we're done with the iterator.
let inputs = node.query_selector_iter("input".to_owned()).unwrap()
.filter_map(HTMLInputElementCast::to_temporary)
.filter_map(HTMLInputElementCast::to_root)
.filter(|input| {
let input = input.root();
input.r().form_owner() == owner && match &*input.r().Type() {
"text" | "search" | "url" | "tel" |
"email" | "password" | "datetime" |

View file

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

View file

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

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLLIElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLLIElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -26,7 +26,7 @@ impl HTMLLIElementDerived for EventTarget {
}
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 {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLLIElement, localName, prefix, document)
}
@ -35,7 +35,7 @@ impl HTMLLIElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLLIElement> {
document: &Document) -> Root<HTMLLIElement> {
let element = HTMLLIElement::new_inherited(localName, prefix, document);
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::{ElementCast, HTMLElementCast, NodeCast};
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, MutNullableHeap, Rootable, Temporary};
use dom::bindings::js::{OptionalRootable, RootedReference};
use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::js::{RootedReference};
use dom::bindings::refcounted::Trusted;
use dom::document::{Document, DocumentHelpers};
use dom::domtokenlist::DOMTokenList;
@ -53,7 +53,7 @@ impl HTMLLinkElementDerived for EventTarget {
}
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 {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLLinkElement, localName, prefix, document),
rel_list: Default::default(),
@ -63,14 +63,14 @@ impl HTMLLinkElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLLinkElement> {
document: &Document) -> Root<HTMLLinkElement> {
let element = HTMLLinkElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLLinkElementBinding::Wrap)
}
}
fn get_attr(element: JSRef<Element>, local_name: &Atom) -> Option<String> {
let elem = element.get_attribute(&ns!(""), local_name).root();
fn get_attr(element: &Element, local_name: &Atom) -> Option<String> {
let elem = element.get_attribute(&ns!(""), local_name);
elem.r().map(|e| {
let value = e.value();
(**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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
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() {
s.after_set_attr(attr);
}
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
if !node.is_in_doc() {
return;
}
let element: JSRef<Element> = ElementCast::from_ref(*self);
let element = ElementCast::from_ref(*self);
let rel = get_attr(element, &atom!("rel"));
match (rel, attr.local_name()) {
@ -149,7 +149,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
}
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 href = get_attr(element, &atom!("href"));
@ -172,15 +172,15 @@ trait PrivateHTMLLinkElementHelpers {
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) {
let window = window_from_node(self).root();
let window = window_from_node(self);
let window = window.r();
match UrlParser::new().base_url(&window.get_url()).parse(href) {
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 mq_str = match 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 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 load_dispatcher = StylesheetLoadDispatcher::new(link_element);
@ -202,7 +202,7 @@ impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
}
fn handle_favicon_url(self, href: &str) {
let window = window_from_node(self).root();
let window = window_from_node(self);
let window = window.r();
match UrlParser::new().base_url(&window.get_url()).parse(href) {
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_setter!(SetHref, "href");
@ -231,7 +231,7 @@ impl<'a> HTMLLinkElementMethods for JSRef<'a, HTMLLinkElement> {
make_getter!(Type);
make_setter!(SetType, "type");
fn RelList(self) -> Temporary<DOMTokenList> {
fn RelList(self) -> Root<DOMTokenList> {
self.rel_list.or_init(|| {
DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel"))
})
@ -252,11 +252,11 @@ impl StylesheetLoadDispatcher {
impl StylesheetLoadResponder for StylesheetLoadDispatcher {
fn respond(self: Box<StylesheetLoadDispatcher>) {
let elem = self.elem.to_temporary().root();
let window = window_from_node(elem.r()).root();
let elem = self.elem.root();
let window = window_from_node(elem.r());
let event = Event::new(GlobalRef::Window(window.r()), "load".to_owned(),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable).root();
EventCancelable::NotCancelable);
let target = EventTargetCast::from_ref(elem.r());
event.r().fire(target);
}

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLMapElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLMapElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLMapElementDerived for EventTarget {
impl HTMLMapElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLMapElement {
document: &Document) -> HTMLMapElement {
HTMLMapElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLMapElement, localName, prefix, document)
}
@ -37,7 +37,7 @@ impl HTMLMapElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLMapElement> {
document: &Document) -> Root<HTMLMapElement> {
let element = HTMLMapElement::new_inherited(localName, prefix, document);
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
* 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::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -28,7 +27,7 @@ impl HTMLMediaElementDerived for EventTarget {
impl HTMLMediaElement {
pub fn new_inherited(type_id: HTMLMediaElementTypeId, tag_name: DOMString,
prefix: Option<DOMString>, document: JSRef<Document>)
prefix: Option<DOMString>, document: &Document)
-> HTMLMediaElement {
HTMLMediaElement {
htmlelement:

View file

@ -5,7 +5,7 @@
use dom::bindings::codegen::Bindings::HTMLMetaElementBinding;
use dom::bindings::codegen::Bindings::HTMLMetaElementBinding::HTMLMetaElementMethods;
use dom::bindings::codegen::InheritTypes::HTMLMetaElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -29,7 +29,7 @@ impl HTMLMetaElementDerived for EventTarget {
impl HTMLMetaElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLMetaElement {
document: &Document) -> HTMLMetaElement {
HTMLMetaElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLMetaElement, localName, prefix, document)
}
@ -38,13 +38,13 @@ impl HTMLMetaElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLMetaElement> {
document: &Document) -> Root<HTMLMetaElement> {
let element = HTMLMetaElement::new_inherited(localName, prefix, document);
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
make_getter!(Name, "name");

View file

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

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLModElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLModElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLModElementDerived for EventTarget {
impl HTMLModElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLModElement {
document: &Document) -> HTMLModElement {
HTMLModElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLModElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLModElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLModElement> {
document: &Document) -> Root<HTMLModElement> {
let element = HTMLModElement::new_inherited(localName, prefix, document);
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::InheritTypes::HTMLObjectElementDerived;
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::element::Element;
use dom::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -42,7 +41,7 @@ impl HTMLObjectElementDerived for EventTarget {
impl HTMLObjectElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLObjectElement {
document: &Document) -> HTMLObjectElement {
HTMLObjectElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLObjectElement, localName, prefix, document),
@ -53,7 +52,7 @@ impl HTMLObjectElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLObjectElement> {
document: &Document) -> Root<HTMLObjectElement> {
let element = HTMLObjectElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLObjectElementBinding::Wrap)
}
@ -63,15 +62,15 @@ trait ProcessDataURL {
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
/// prefetching the image. This method must be called after `data` is changed.
fn process_data_url(&self) {
let elem: JSRef<Element> = ElementCast::from_ref(*self);
let elem = ElementCast::from_ref(*self);
// TODO: support other values
match (elem.get_attribute(&ns!(""), &atom!("type")).map(|x| x.root().r().Value()),
elem.get_attribute(&ns!(""), &atom!("data")).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.r().Value())) {
(None, Some(_uri)) => {
// 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_))
}
impl<'a> HTMLObjectElementMethods for JSRef<'a, HTMLObjectElement> {
fn Validity(self) -> Temporary<ValidityState> {
let window = window_from_node(self).root();
impl<'a> HTMLObjectElementMethods for &'a HTMLObjectElement {
fn Validity(self) -> Root<ValidityState> {
let window = window_from_node(self);
ValidityState::new(window.r())
}
@ -98,13 +97,13 @@ impl<'a> HTMLObjectElementMethods for JSRef<'a, HTMLObjectElement> {
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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
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() {
s.after_set_attr(attr);
}

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLOListElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLOListElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLOListElementDerived for EventTarget {
impl HTMLOListElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLOListElement {
document: &Document) -> HTMLOListElement {
HTMLOListElement {
htmlelement: HTMLElement::new_inherited(HTMLElementTypeId::HTMLOListElement, localName, prefix, document)
}
@ -37,7 +37,7 @@ impl HTMLOListElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLOListElement> {
document: &Document) -> Root<HTMLOListElement> {
let element = HTMLOListElement::new_inherited(localName, prefix, document);
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::InheritTypes::{HTMLElementCast, NodeCast};
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::element::AttributeHandlers;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
@ -35,7 +35,7 @@ impl HTMLOptGroupElementDerived for EventTarget {
impl HTMLOptGroupElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLOptGroupElement {
document: &Document) -> HTMLOptGroupElement {
HTMLOptGroupElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLOptGroupElement, localName, prefix, document)
@ -45,13 +45,13 @@ impl HTMLOptGroupElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLOptGroupElement> {
document: &Document) -> Root<HTMLOptGroupElement> {
let element = HTMLOptGroupElement::new_inherited(localName, prefix, document);
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
make_bool_getter!(Disabled);
@ -59,24 +59,23 @@ impl<'a> HTMLOptGroupElementMethods for JSRef<'a, HTMLOptGroupElement> {
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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
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() {
s.after_set_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(true);
node.set_enabled_state(false);
for child in node.children() {
let child = child.root();
if child.r().is_htmloptionelement() {
child.r().set_disabled_state(true);
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() {
s.before_remove_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(false);
node.set_enabled_state(true);
for child in node.children() {
let child = child.root();
if child.r().is_htmloptionelement() {
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::HTMLOptionElementBinding;
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::{HTMLScriptElementDerived};
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::js::{JSRef, Rootable, Temporary};
use dom::characterdata::CharacterData;
use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::{AttributeHandlers, Element, ElementHelpers};
use dom::element::{AttributeHandlers, ElementHelpers};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@ -39,7 +38,7 @@ impl HTMLOptionElementDerived for EventTarget {
impl HTMLOptionElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLOptionElement {
document: &Document) -> HTMLOptionElement {
HTMLOptionElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLOptionElement, localName, prefix, document)
@ -49,23 +48,22 @@ impl HTMLOptionElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLOptionElement> {
document: &Document) -> Root<HTMLOptionElement> {
let element = HTMLOptionElement::new_inherited(localName, prefix, document);
Node::reflect_node(box element, document, HTMLOptionElementBinding::Wrap)
}
}
fn collect_text(node: &JSRef<Node>, value: &mut DOMString) {
let elem: JSRef<Element> = ElementCast::to_ref(*node).unwrap();
fn collect_text(node: &&Node, value: &mut DOMString) {
let elem = ElementCast::to_ref(*node).unwrap();
let svg_script = *elem.namespace() == ns!(SVG) && elem.local_name() == &atom!("script");
let html_script = node.is_htmlscriptelement();
if svg_script || html_script {
return;
} else {
for child in node.children() {
let child = child.root();
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());
} else {
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
make_bool_getter!(Disabled);
// https://www.whatwg.org/html/#dom-option-disabled
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)
}
// https://www.whatwg.org/html/#dom-option-text
fn Text(self) -> DOMString {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
let mut content = String::new();
collect_text(&node, &mut content);
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
fn SetText(self, value: DOMString) {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
node.SetTextContent(Some(value))
}
// https://html.spec.whatwg.org/multipage/#attr-option-value
fn Value(self) -> DOMString {
let element: JSRef<Element> = ElementCast::from_ref(self);
let element = ElementCast::from_ref(self);
let attr = &atom!("value");
if element.has_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
fn Label(self) -> DOMString {
let element: JSRef<Element> = ElementCast::from_ref(self);
let element = ElementCast::from_ref(self);
let attr = &atom!("label");
if element.has_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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
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() {
s.after_set_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(true);
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() {
s.before_remove_attr(attr);
}
match attr.local_name() {
&atom!("disabled") => {
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
node.set_disabled_state(false);
node.set_enabled_state(true);
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);
}
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
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);
}
let node: JSRef<Node> = NodeCast::from_ref(*self);
let node = NodeCast::from_ref(*self);
if node.GetParentNode().is_some() {
node.check_parent_disabled_state_for_option();
} else {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,7 @@
use dom::bindings::codegen::Bindings::HTMLQuoteElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLQuoteElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::element::ElementTypeId;
@ -28,7 +28,7 @@ impl HTMLQuoteElementDerived for EventTarget {
impl HTMLQuoteElement {
fn new_inherited(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> HTMLQuoteElement {
document: &Document) -> HTMLQuoteElement {
HTMLQuoteElement {
htmlelement:
HTMLElement::new_inherited(HTMLElementTypeId::HTMLQuoteElement, localName, prefix, document)
@ -38,7 +38,7 @@ impl HTMLQuoteElement {
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString,
prefix: Option<DOMString>,
document: JSRef<Document>) -> Temporary<HTMLQuoteElement> {
document: &Document) -> Root<HTMLQuoteElement> {
let element = HTMLQuoteElement::new_inherited(localName, prefix, document);
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::EventTargetCast;
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::refcounted::Trusted;
use dom::bindings::trace::JSTraceable;
use dom::document::{Document, DocumentHelpers};
use dom::element::{Element, AttributeHandlers, ElementCreator};
use dom::element::{AttributeHandlers, ElementCreator};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::element::ElementTypeId;
@ -33,6 +33,8 @@ use dom::virtualmethods::VirtualMethods;
use dom::window::{WindowHelpers, ScriptHelpers};
use network_listener::{NetworkListener, PreInvoke};
use script_task::{ScriptChan, ScriptMsg, Runnable};
use js::jsapi::RootedValue;
use js::jsval::UndefinedValue;
use encoding::all::UTF_8;
use encoding::label::encoding_from_whatwg_label;
@ -82,7 +84,7 @@ impl HTMLScriptElementDerived for EventTarget {
}
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 {
HTMLScriptElement {
htmlelement:
@ -91,14 +93,14 @@ impl HTMLScriptElement {
parser_inserted: Cell::new(creator == ElementCreator::ParserCreated),
non_blocking: Cell::new(creator != ElementCreator::ParserCreated),
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),
}
}
#[allow(unrooted_must_root)]
pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>,
creator: ElementCreator) -> Temporary<HTMLScriptElement> {
pub fn new(localName: DOMString, prefix: Option<DOMString>, document: &Document,
creator: ElementCreator) -> Root<HTMLScriptElement> {
let element = HTMLScriptElement::new_inherited(localName, prefix, document, creator);
Node::reflect_node(box element, document, HTMLScriptElementBinding::Wrap)
}
@ -190,22 +192,22 @@ impl AsyncResponseListener for ScriptContext {
let metadata = self.metadata.borrow_mut().take().unwrap();
(metadata, data)
});
let elem = self.elem.to_temporary().root();
let elem = self.elem.root();
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()));
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<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
impl<'a> HTMLScriptElementHelpers for &'a HTMLScriptElement {
fn prepare(self) -> NextParserState {
// https://html.spec.whatwg.org/multipage/#prepare-a-script
// Step 1.
@ -217,7 +219,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
self.parser_inserted.set(false);
// 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")) {
self.non_blocking.set(true);
}
@ -227,7 +229,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
return NextParserState::Continue;
}
// Step 5.
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
if !node.is_in_doc() {
return NextParserState::Continue;
}
@ -244,7 +246,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
self.already_started.set(true);
// 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();
if self.parser_inserted.get() && self.parser_document.root().r() != document_from_node_ref {
return NextParserState::Continue;
@ -256,8 +258,8 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
}
// Step 12.
let for_attribute = element.get_attribute(&ns!(""), &atom!("for")).root();
let event_attribute = element.get_attribute(&ns!(""), &Atom::from_slice("event")).root();
let for_attribute = element.get_attribute(&ns!(""), &atom!("for"));
let event_attribute = element.get_attribute(&ns!(""), &Atom::from_slice("event"));
match (for_attribute.r(), event_attribute.r()) {
(Some(for_attribute), Some(event_attribute)) => {
let for_value = for_attribute.Value()
@ -277,18 +279,18 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
}
// 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()) {
*self.block_character_encoding.borrow_mut() = encodingRef;
}
}
// Step 14.
let window = window_from_node(self).root();
let window = window_from_node(self);
let window = window.r();
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.
Some(ref src) => {
// 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
// the origin of the script element's node document, and the default origin
// behaviour set to taint.
let doc = document_from_node(self).root();
let doc = document_from_node(self);
let script_chan = window.script_chan();
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);
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;
}
@ -409,18 +411,20 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
// document. Let neutralised doc be that Document.
// Step 2.b.4.
let document = document_from_node(self).root();
let document = document_from_node(self);
let document = document.r();
let old_script = document.GetCurrentScript().root();
let old_script = document.GetCurrentScript();
// Step 2.b.5.
document.set_current_script(Some(self));
// Step 2.b.6.
// 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,
&*url.serialize());
&*url.serialize(),
rval.handle_mut());
// Step 2.b.7.
document.set_current_script(old_script.r());
@ -447,7 +451,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
}
fn queue_error_event(self) {
let window = window_from_node(self).root();
let window = window_from_node(self);
let window = window.r();
let chan = window.script_chan();
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 {
let element: JSRef<Element> = ElementCast::from_ref(self);
match element.get_attribute(&ns!(""), &atom!("type")).root().map(|s| s.r().Value()) {
let element = ElementCast::from_ref(self);
match element.get_attribute(&ns!(""), &atom!("type")).map(|s| s.r().Value()) {
Some(ref s) if s.is_empty() => {
// type attr exists, but empty means js
debug!("script type empty, inferring js");
@ -497,7 +501,6 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
None => {
debug!("no script type");
match element.get_attribute(&ns!(""), &atom!("language"))
.root()
.map(|s| s.r().Value()) {
Some(ref s) if s.is_empty() => {
debug!("script language empty, inferring js");
@ -528,44 +531,44 @@ trait PrivateHTMLScriptElementHelpers {
cancelable: EventCancelable) -> bool;
}
impl<'a> PrivateHTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
impl<'a> PrivateHTMLScriptElementHelpers for &'a HTMLScriptElement {
fn dispatch_event(self,
type_: DOMString,
bubbles: EventBubbles,
cancelable: EventCancelable) -> bool {
let window = window_from_node(self).root();
let window = window_from_node(self);
let window = window.r();
let event = Event::new(GlobalRef::Window(window),
type_,
bubbles,
cancelable).root();
cancelable);
let event = event.r();
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
let target = EventTargetCast::from_ref(self);
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> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self);
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() {
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() {
self.prepare();
}
}
fn child_inserted(&self, child: JSRef<Node>) {
fn child_inserted(&self, child: &Node) {
if let Some(ref s) = self.super_type() {
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() {
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) {
if let Some(ref s) = self.super_type() {
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
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();
}
}
}
impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> {
impl<'a> HTMLScriptElementMethods for &'a HTMLScriptElement {
make_url_getter!(Src);
make_setter!(SetSrc, "src");
@ -607,7 +610,7 @@ impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> {
// https://www.whatwg.org/html/#dom-script-text
fn SetText(self, value: DOMString) {
let node: JSRef<Node> = NodeCast::from_ref(self);
let node = NodeCast::from_ref(self);
node.SetTextContent(Some(value))
}
}
@ -619,7 +622,7 @@ struct EventDispatcher {
impl Runnable for EventDispatcher {
fn handler(self: Box<EventDispatcher>) {
let target = self.element.to_temporary().root();
let target = self.element.root();
if self.is_error {
target.r().dispatch_error_event();
} else {

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