Merge branch 'master' into calc

This commit is contained in:
Simon Sapin 2015-09-01 18:39:16 +02:00
commit 80d471d5cf
400 changed files with 8129 additions and 11782 deletions

View file

@ -112,14 +112,12 @@ impl WebGLPaintTask {
gl::enable_vertex_attrib_array(attrib_id), gl::enable_vertex_attrib_array(attrib_id),
CanvasWebGLMsg::GetAttribLocation(program_id, name, chan) => CanvasWebGLMsg::GetAttribLocation(program_id, name, chan) =>
self.get_attrib_location(program_id, name, chan), self.get_attrib_location(program_id, name, chan),
CanvasWebGLMsg::GetShaderInfoLog(shader_id, chan) =>
self.get_shader_info_log(shader_id, chan),
CanvasWebGLMsg::GetShaderParameter(shader_id, param_id, chan) => CanvasWebGLMsg::GetShaderParameter(shader_id, param_id, chan) =>
self.get_shader_parameter(shader_id, param_id, chan), self.get_shader_parameter(shader_id, param_id, chan),
CanvasWebGLMsg::GetUniformLocation(program_id, name, chan) => CanvasWebGLMsg::GetUniformLocation(program_id, name, chan) =>
self.get_uniform_location(program_id, name, chan), self.get_uniform_location(program_id, name, chan),
CanvasWebGLMsg::CompileShader(shader_id) => CanvasWebGLMsg::CompileShader(shader_id, source) =>
self.compile_shader(shader_id), self.compile_shader(shader_id, source),
CanvasWebGLMsg::CreateBuffer(chan) => CanvasWebGLMsg::CreateBuffer(chan) =>
self.create_buffer(chan), self.create_buffer(chan),
CanvasWebGLMsg::CreateFramebuffer(chan) => CanvasWebGLMsg::CreateFramebuffer(chan) =>
@ -154,8 +152,6 @@ impl WebGLPaintTask {
gl::bind_texture(target, id), gl::bind_texture(target, id),
CanvasWebGLMsg::LinkProgram(program_id) => CanvasWebGLMsg::LinkProgram(program_id) =>
gl::link_program(program_id), gl::link_program(program_id),
CanvasWebGLMsg::ShaderSource(shader_id, source) =>
gl::shader_source(shader_id, &[source.as_bytes()]),
CanvasWebGLMsg::Uniform4fv(uniform_id, data) => CanvasWebGLMsg::Uniform4fv(uniform_id, data) =>
gl::uniform_4f(uniform_id, data[0], data[1], data[2], data[3]), gl::uniform_4f(uniform_id, data[0], data[1], data[2], data[3]),
CanvasWebGLMsg::UseProgram(program_id) => CanvasWebGLMsg::UseProgram(program_id) =>
@ -303,11 +299,9 @@ impl WebGLPaintTask {
gl::bind_framebuffer(target, id); gl::bind_framebuffer(target, id);
} }
// TODO(ecoal95): This is not spec-compliant, we must check
// the version of GLSL used. This functionality should probably
// be in the WebGLShader object
#[inline] #[inline]
fn compile_shader(&self, shader_id: u32) { fn compile_shader(&self, shader_id: u32, source: String) {
gl::shader_source(shader_id, &[source.as_bytes()]);
gl::compile_shader(shader_id); gl::compile_shader(shader_id);
} }
@ -323,13 +317,6 @@ impl WebGLPaintTask {
chan.send(attrib_location).unwrap(); chan.send(attrib_location).unwrap();
} }
fn get_shader_info_log(&self, shader_id: u32, chan: IpcSender<Option<String>>) {
// TODO(ecoal95): Right now we always return a value, we should
// check for gl errors and return None there
let info = gl::get_shader_info_log(shader_id);
chan.send(Some(info)).unwrap();
}
fn get_shader_parameter(&self, fn get_shader_parameter(&self,
shader_id: u32, shader_id: u32,
param_id: u32, param_id: u32,

View file

@ -138,7 +138,7 @@ pub enum CanvasWebGLMsg {
DepthRange(f64, f64), DepthRange(f64, f64),
Enable(u32), Enable(u32),
Disable(u32), Disable(u32),
CompileShader(u32), CompileShader(u32, String),
CreateBuffer(IpcSender<Option<NonZero<u32>>>), CreateBuffer(IpcSender<Option<NonZero<u32>>>),
CreateFramebuffer(IpcSender<Option<NonZero<u32>>>), CreateFramebuffer(IpcSender<Option<NonZero<u32>>>),
CreateRenderbuffer(IpcSender<Option<NonZero<u32>>>), CreateRenderbuffer(IpcSender<Option<NonZero<u32>>>),
@ -157,7 +157,6 @@ pub enum CanvasWebGLMsg {
BindTexture(u32, u32), BindTexture(u32, u32),
DrawArrays(u32, i32, i32), DrawArrays(u32, i32, i32),
EnableVertexAttribArray(u32), EnableVertexAttribArray(u32),
GetShaderInfoLog(u32, IpcSender<Option<String>>),
GetShaderParameter(u32, u32, IpcSender<WebGLShaderParameter>), GetShaderParameter(u32, u32, IpcSender<WebGLShaderParameter>),
GetAttribLocation(u32, String, IpcSender<Option<i32>>), GetAttribLocation(u32, String, IpcSender<Option<i32>>),
GetUniformLocation(u32, String, IpcSender<Option<i32>>), GetUniformLocation(u32, String, IpcSender<Option<i32>>),
@ -166,7 +165,6 @@ pub enum CanvasWebGLMsg {
LineWidth(f32), LineWidth(f32),
PixelStorei(u32, i32), PixelStorei(u32, i32),
LinkProgram(u32), LinkProgram(u32),
ShaderSource(u32, String),
Uniform4fv(i32, Vec<f32>), Uniform4fv(i32, Vec<f32>),
UseProgram(u32), UseProgram(u32),
VertexAttribPointer2f(u32, i32, bool, i32, u32), VertexAttribPointer2f(u32, i32, bool, i32, u32),

View file

@ -54,8 +54,8 @@ use style::viewport::ViewportConstraints;
use url::Url; use url::Url;
use util::cursor::Cursor; use util::cursor::Cursor;
use util::geometry::PagePx; use util::geometry::PagePx;
use util::opts;
use util::task::spawn_named; use util::task::spawn_named;
use util::{opts, prefs};
/// Maintains the pipelines and navigation context and grants permission to composite. /// Maintains the pipelines and navigation context and grants permission to composite.
/// ///
@ -891,7 +891,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
containing_pipeline_id: PipelineId, containing_pipeline_id: PipelineId,
subpage_id: SubpageId, subpage_id: SubpageId,
event: MozBrowserEvent) { event: MozBrowserEvent) {
assert!(opts::experimental_enabled()); assert!(prefs::get_pref("dom.mozbrowser.enabled", false));
// Find the script channel for the given parent pipeline, // Find the script channel for the given parent pipeline,
// and pass the event to that script task. // and pass the event to that script task.
@ -1373,7 +1373,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserlocationchange // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserlocationchange
fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) { fn trigger_mozbrowserlocationchange(&self, pipeline_id: PipelineId) {
if opts::experimental_enabled() { if prefs::get_pref("dom.mozbrowser.enabled", false) {
// Work around borrow checker // Work around borrow checker
let event_info = { let event_info = {
let pipeline = self.pipeline(pipeline_id); let pipeline = self.pipeline(pipeline_id);

View file

@ -7,6 +7,7 @@ use windowing::WindowEvent;
use euclid::scale_factor::ScaleFactor; use euclid::scale_factor::ScaleFactor;
use euclid::size::Size2D; use euclid::size::Size2D;
use msg::constellation_msg::AnimationState;
use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, WindowSizeData}; use msg::constellation_msg::{ConstellationChan, WindowSizeData};
use profile_traits::mem; use profile_traits::mem;
@ -88,6 +89,18 @@ impl CompositorEventListener for NullCompositor {
response_chan.send(()).unwrap(); response_chan.send(()).unwrap();
} }
Msg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
match animation_state {
AnimationState::AnimationsPresent |
AnimationState::NoAnimationsPresent |
AnimationState::NoAnimationCallbacksPresent => {}
AnimationState::AnimationCallbacksPresent => {
let msg = ConstellationMsg::TickAnimation(pipeline_id);
self.constellation_chan.0.send(msg).unwrap()
}
}
}
// Explicitly list ignored messages so that when we add a new one, // Explicitly list ignored messages so that when we add a new one,
// we'll notice and think about whether it needs a response, like // we'll notice and think about whether it needs a response, like
// SetFrameTree. // SetFrameTree.
@ -95,7 +108,6 @@ impl CompositorEventListener for NullCompositor {
Msg::InitializeLayersForPipeline(..) | Msg::InitializeLayersForPipeline(..) |
Msg::SetLayerRect(..) | Msg::SetLayerRect(..) |
Msg::AssignPaintedBuffers(..) | Msg::AssignPaintedBuffers(..) |
Msg::ChangeRunningAnimationsState(..) |
Msg::ScrollFragmentPoint(..) | Msg::ScrollFragmentPoint(..) |
Msg::Status(..) | Msg::Status(..) |
Msg::LoadStart(..) | Msg::LoadStart(..) |

View file

@ -39,9 +39,9 @@ extern crate clipboard;
extern crate time; extern crate time;
extern crate url; extern crate url;
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
extern crate core_graphics; extern crate core_graphics;
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
extern crate core_text; extern crate core_text;
pub use compositor_task::{CompositorEventListener, CompositorProxy, CompositorTask}; pub use compositor_task::{CompositorEventListener, CompositorProxy, CompositorTask};

View file

@ -31,7 +31,7 @@ use url::Url;
use util; use util;
use util::geometry::{PagePx, ViewportPx}; use util::geometry::{PagePx, ViewportPx};
use util::ipc::OptionalIpcSender; use util::ipc::OptionalIpcSender;
use util::opts; use util::prefs;
/// A uniquely-identifiable pipeline of script task, layout task, and paint task. /// A uniquely-identifiable pipeline of script task, layout task, and paint task.
pub struct Pipeline { pub struct Pipeline {
@ -269,7 +269,7 @@ impl Pipeline {
pub fn trigger_mozbrowser_event(&self, pub fn trigger_mozbrowser_event(&self,
subpage_id: SubpageId, subpage_id: SubpageId,
event: MozBrowserEvent) { event: MozBrowserEvent) {
assert!(opts::experimental_enabled()); assert!(prefs::get_pref("dom.mozbrowser.enabled", false));
let event = ConstellationControlMsg::MozBrowserEvent(self.id, let event = ConstellationControlMsg::MozBrowserEvent(self.id,
subpage_id, subpage_id,

View file

@ -6,13 +6,11 @@
use devtools_traits::PreciseTime; use devtools_traits::PreciseTime;
use rustc_serialize::json; use rustc_serialize::json;
use std::any::{Any, TypeId}; use std::any::Any;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::HashMap; use std::collections::HashMap;
use std::marker::Reflect; use std::mem::replace;
use std::mem::{replace, transmute};
use std::net::TcpStream; use std::net::TcpStream;
use std::raw::TraitObject;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
#[derive(PartialEq)] #[derive(PartialEq)]
@ -24,7 +22,7 @@ pub enum ActorMessageStatus {
/// A common trait for all devtools actors that encompasses an immutable name /// A common trait for all devtools actors that encompasses an immutable name
/// and the ability to process messages that are directed to particular actors. /// and the ability to process messages that are directed to particular actors.
/// TODO: ensure the name is immutable /// TODO: ensure the name is immutable
pub trait Actor: Any { pub trait Actor: Any + ActorAsAny {
fn handle_message(&self, fn handle_message(&self,
registry: &ActorRegistry, registry: &ActorRegistry,
msg_type: &str, msg_type: &str,
@ -33,55 +31,14 @@ pub trait Actor: Any {
fn name(&self) -> String; fn name(&self) -> String;
} }
impl Actor + Send { trait ActorAsAny {
/// Returns true if the boxed type is the same as `T` fn actor_as_any(&self) -> &Any;
#[inline] fn actor_as_any_mut(&mut self) -> &mut Any;
pub fn is<T: Reflect + 'static>(&self) -> bool { }
// Get TypeId of the type this function is instantiated with
let t = TypeId::of::<T>();
// Get TypeId of the type in the trait object impl<T: Actor> ActorAsAny for T {
let boxed = self.get_type_id(); fn actor_as_any(&self) -> &Any { self }
fn actor_as_any_mut(&mut self) -> &mut Any { self }
// Compare both TypeIds on equality
t == boxed
}
/// Returns some reference to the boxed value if it is of type `T`, or
/// `None` if it isn't.
#[inline]
#[allow(unsafe_code)]
pub fn downcast_ref<T: Reflect + 'static>(&self) -> Option<&T> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
let to: TraitObject = transmute(self);
// Extract the data pointer
Some(transmute(to.data))
}
} else {
None
}
}
/// Returns some mutable reference to the boxed value if it is of type `T`, or
/// `None` if it isn't.
#[inline]
#[allow(unsafe_code)]
pub fn downcast_mut<T: Reflect + 'static>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
unsafe {
// Get the raw representation of the trait object
let to: TraitObject = transmute(self);
// Extract the data pointer
Some(transmute(to.data))
}
} else {
None
}
}
} }
/// A list of known, owned actors. /// A list of known, owned actors.
@ -179,15 +136,15 @@ impl ActorRegistry {
} }
/// Find an actor by registered name /// Find an actor by registered name
pub fn find<'a, T: Reflect + 'static>(&'a self, name: &str) -> &'a T { pub fn find<'a, T: Any>(&'a self, name: &str) -> &'a T {
let actor = self.actors.get(&name.to_string()).unwrap(); let actor = self.actors.get(&name.to_string()).unwrap();
actor.downcast_ref::<T>().unwrap() actor.actor_as_any().downcast_ref::<T>().unwrap()
} }
/// Find an actor by registered name /// Find an actor by registered name
pub fn find_mut<'a, T: Reflect + 'static>(&'a mut self, name: &str) -> &'a mut T { pub fn find_mut<'a, T: Any>(&'a mut self, name: &str) -> &'a mut T {
let actor = self.actors.get_mut(&name.to_string()).unwrap(); let actor = self.actors.get_mut(&name.to_string()).unwrap();
actor.downcast_mut::<T>().unwrap() actor.actor_as_any_mut().downcast_mut::<T>().unwrap()
} }
/// Attempt to process a message as directed by its `to` property. If the actor is not /// Attempt to process a message as directed by its `to` property. If the actor is not

View file

@ -17,9 +17,9 @@ use devtools_traits::EvaluateJSReply::{StringValue, BooleanValue, ActorValue};
use devtools_traits::{CachedConsoleMessageTypes, DevtoolScriptControlMsg, PAGE_ERROR, CONSOLE_API}; use devtools_traits::{CachedConsoleMessageTypes, DevtoolScriptControlMsg, PAGE_ERROR, CONSOLE_API};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use core::cell::RefCell;
use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::ipc::{self, IpcSender};
use rustc_serialize::json::{self, Json, ToJson}; use rustc_serialize::json::{self, Json, ToJson};
use std::cell::RefCell;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::net::TcpStream; use std::net::TcpStream;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;

View file

@ -6,7 +6,6 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use msg::constellation_msg::PipelineId; use msg::constellation_msg::PipelineId;
use rustc_serialize::{json, Encoder, Encodable}; use rustc_serialize::{json, Encoder, Encodable};
use std::cell::RefCell; use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::net::TcpStream; use std::net::TcpStream;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -17,7 +16,7 @@ use actors::framerate::FramerateActor;
use actors::memory::{MemoryActor, TimelineMemoryReply}; use actors::memory::{MemoryActor, TimelineMemoryReply};
use devtools_traits::DevtoolScriptControlMsg; use devtools_traits::DevtoolScriptControlMsg;
use devtools_traits::DevtoolScriptControlMsg::{SetTimelineMarkers, DropTimelineMarkers}; use devtools_traits::DevtoolScriptControlMsg::{SetTimelineMarkers, DropTimelineMarkers};
use devtools_traits::{PreciseTime, TimelineMarker, TracingMetadata, TimelineMarkerType}; use devtools_traits::{PreciseTime, TimelineMarker, TimelineMarkerType};
use protocol::JsonPacketStream; use protocol::JsonPacketStream;
use util::task; use util::task;
@ -148,72 +147,15 @@ impl TimelineActor {
return; return;
} }
/// Select root(with depth 0) TimelineMarker pair (IntervalStart + IntervalEnd)
/// from queue and add marker to emitter
/// Return true if closed (IntervalStart + IntervalEnd) pair was founded
fn group(queue: &mut VecDeque<TimelineMarker>, depth: usize,
start_payload: Option<TimelineMarker>, emitter: &Emitter,
markers: &mut Vec<TimelineMarkerReply>) -> bool {
if let Some(start_payload) = start_payload {
if start_payload.metadata != TracingMetadata::IntervalStart {
panic!("Start payload doesn't have metadata IntervalStart");
}
if let Some(end_payload) = queue.pop_front() {
match end_payload.metadata {
TracingMetadata::IntervalEnd => {
if depth == 0 {
// Emit TimelineMarkerReply, pair was found
markers.push(emitter.marker(start_payload, end_payload));
}
return true;
}
TracingMetadata::IntervalStart => {
if group(queue, depth + 1, Some(end_payload), emitter, markers) {
return group(queue, depth, Some(start_payload), emitter, markers);
} else {
queue.push_front(start_payload);
}
}
_ => panic!("Unknown tracingMetadata")
}
} else {
queue.push_front(start_payload);
}
}
false
}
task::spawn_named("PullTimelineMarkers".to_string(), move || { task::spawn_named("PullTimelineMarkers".to_string(), move || {
let mut queues = HashMap::new();
queues.insert("Reflow".to_string(), VecDeque::new());
queues.insert("DOMEvent".to_string(), VecDeque::new());
loop { loop {
if !*is_recording.lock().unwrap() { if !*is_recording.lock().unwrap() {
break; break;
} }
// Creating queues by marker.name
loop {
match receiver.try_recv() {
Ok(marker) => {
if let Some(list) = queues.get_mut(&marker.name) {
list.push_back(marker);
}
}
Err(_) => break
}
}
// Emit all markers
let mut markers = vec![]; let mut markers = vec![];
for (_, queue) in &mut queues { while let Ok(marker) = receiver.try_recv() {
let start_payload = queue.pop_front(); markers.push(emitter.marker(marker));
group(queue, 0, start_payload, &emitter, &mut markers);
} }
emitter.send(markers); emitter.send(markers);
@ -336,14 +278,13 @@ impl Emitter {
} }
} }
fn marker(&self, start_payload: TimelineMarker, end_payload: TimelineMarker) fn marker(&self, payload: TimelineMarker) -> TimelineMarkerReply {
-> TimelineMarkerReply {
TimelineMarkerReply { TimelineMarkerReply {
name: start_payload.name, name: payload.name,
start: HighResolutionStamp::new(self.start_stamp, start_payload.time), start: HighResolutionStamp::new(self.start_stamp, payload.start_time),
end: HighResolutionStamp::new(self.start_stamp, end_payload.time), end: HighResolutionStamp::new(self.start_stamp, payload.end_time),
stack: start_payload.stack, stack: payload.start_stack,
endStack: end_payload.stack, endStack: payload.end_stack,
} }
} }

View file

@ -11,12 +11,8 @@
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(core)]
#![feature(custom_derive)] #![feature(custom_derive)]
#![feature(get_type_id)]
#![feature(plugin)] #![feature(plugin)]
#![feature(raw)]
#![feature(reflect_marker)]
#![plugin(serde_macros)] #![plugin(serde_macros)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
@ -25,7 +21,6 @@
#[macro_use] #[macro_use]
extern crate log; extern crate log;
extern crate core;
extern crate devtools_traits; extern crate devtools_traits;
extern crate rustc_serialize; extern crate rustc_serialize;
extern crate ipc_channel; extern crate ipc_channel;

View file

@ -124,21 +124,19 @@ pub struct NodeInfo {
pub incompleteValue: bool, pub incompleteValue: bool,
} }
#[derive(PartialEq, Eq, Deserialize, Serialize)] pub struct StartedTimelineMarker {
pub enum TracingMetadata { name: String,
Default, start_time: PreciseTime,
IntervalStart, start_stack: Option<Vec<()>>,
IntervalEnd,
Event,
EventBacktrace,
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct TimelineMarker { pub struct TimelineMarker {
pub name: String, pub name: String,
pub metadata: TracingMetadata, pub start_time: PreciseTime,
pub time: PreciseTime, pub start_stack: Option<Vec<()>>,
pub stack: Option<Vec<()>>, pub end_time: PreciseTime,
pub end_stack: Option<Vec<()>>,
} }
#[derive(PartialEq, Eq, Hash, Clone, Deserialize, Serialize)] #[derive(PartialEq, Eq, Hash, Clone, Deserialize, Serialize)]
@ -270,12 +268,23 @@ pub enum NetworkEvent {
} }
impl TimelineMarker { impl TimelineMarker {
pub fn new(name: String, metadata: TracingMetadata) -> TimelineMarker { pub fn start(name: String) -> StartedTimelineMarker {
TimelineMarker { StartedTimelineMarker {
name: name, name: name,
metadata: metadata, start_time: PreciseTime::now(),
time: PreciseTime::now(), start_stack: None,
stack: None, }
}
}
impl StartedTimelineMarker {
pub fn end(self) -> TimelineMarker {
TimelineMarker {
name: self.name,
start_time: self.start_time,
start_stack: self.start_stack,
end_time: PreciseTime::now(),
end_stack: None,
} }
} }
} }

View file

@ -101,13 +101,13 @@ pub struct Font {
bitflags! { bitflags! {
flags ShapingFlags: u8 { flags ShapingFlags: u8 {
#[doc="Set if the text is entirely whitespace."] #[doc = "Set if the text is entirely whitespace."]
const IS_WHITESPACE_SHAPING_FLAG = 0x01, const IS_WHITESPACE_SHAPING_FLAG = 0x01,
#[doc="Set if we are to ignore ligatures."] #[doc = "Set if we are to ignore ligatures."]
const IGNORE_LIGATURES_SHAPING_FLAG = 0x02, const IGNORE_LIGATURES_SHAPING_FLAG = 0x02,
#[doc="Set if we are to disable kerning."] #[doc = "Set if we are to disable kerning."]
const DISABLE_KERNING_SHAPING_FLAG = 0x04, const DISABLE_KERNING_SHAPING_FLAG = 0x04,
#[doc="Text direction is right-to-left."] #[doc = "Text direction is right-to-left."]
const RTL_FLAG = 0x08, const RTL_FLAG = 0x08,
} }
} }

View file

@ -31,16 +31,16 @@ use std::sync::Arc;
use azure::azure_hl::BackendType; use azure::azure_hl::BackendType;
use azure::scaled_font::ScaledFont; use azure::scaled_font::ScaledFont;
#[cfg(any(target_os="linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
use azure::scaled_font::FontInfo; use azure::scaled_font::FontInfo;
#[cfg(any(target_os="linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont { fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont {
ScaledFont::new(BackendType::Skia, FontInfo::FontData(&template.bytes), ScaledFont::new(BackendType::Skia, FontInfo::FontData(&template.bytes),
pt_size.to_f32_px()) pt_size.to_f32_px())
} }
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont { fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont {
let cgfont = template.ctfont().as_ref().unwrap().copy_to_CGFont(); let cgfont = template.ctfont().as_ref().unwrap().copy_to_CGFont();
ScaledFont::new(BackendType::Skia, &cgfont, pt_size.to_f32_px()) ScaledFont::new(BackendType::Skia, &cgfont, pt_size.to_f32_px())

View file

@ -3,12 +3,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#![feature(arc_weak)] #![feature(arc_weak)]
#![cfg_attr(any(target_os="linux", target_os = "android"), feature(box_raw))] #![cfg_attr(any(target_os = "linux", target_os = "android"), feature(box_raw))]
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(custom_attribute)] #![feature(custom_attribute)]
#![feature(custom_derive)] #![feature(custom_derive)]
#![feature(hashmap_hasher)] #![feature(hashmap_hasher)]
#![cfg_attr(any(target_os="linux", target_os = "android"), feature(heap_api))] #![cfg_attr(any(target_os = "linux", target_os = "android"), feature(heap_api))]
#![feature(mpsc_select)] #![feature(mpsc_select)]
#![feature(plugin)] #![feature(plugin)]
#![feature(str_char)] #![feature(str_char)]
@ -55,23 +55,23 @@ extern crate canvas_traits;
extern crate harfbuzz; extern crate harfbuzz;
// Linux and Android-specific library dependencies // Linux and Android-specific library dependencies
#[cfg(any(target_os="linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
extern crate fontconfig; extern crate fontconfig;
#[cfg(any(target_os="linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
extern crate freetype; extern crate freetype;
// Mac OS-specific library dependencies // Mac OS-specific library dependencies
#[cfg(target_os="macos")] extern crate core_foundation; #[cfg(target_os = "macos")] extern crate core_foundation;
#[cfg(target_os="macos")] extern crate core_graphics; #[cfg(target_os = "macos")] extern crate core_graphics;
#[cfg(target_os="macos")] extern crate core_text; #[cfg(target_os = "macos")] extern crate core_text;
pub use paint_context::PaintContext; pub use paint_context::PaintContext;
// Private painting modules // Private painting modules
mod paint_context; mod paint_context;
#[path="display_list/mod.rs"] #[path = "display_list/mod.rs"]
pub mod display_list; pub mod display_list;
pub mod paint_task; pub mod paint_task;
@ -85,7 +85,7 @@ pub mod font_template;
mod filters; mod filters;
// Platform-specific implementations. // Platform-specific implementations.
#[path="platform/mod.rs"] #[path = "platform/mod.rs"]
pub mod platform; pub mod platform;
// Text // Text

View file

@ -72,6 +72,19 @@ enum DashSize {
DashedBorder = 3 DashedBorder = 3
} }
#[derive(Copy, Clone, Debug)]
struct Ellipse {
origin: Point2D<f32>,
width: f32,
height: f32,
}
#[derive(Copy, Clone, Debug)]
struct Line {
start: Point2D<f32>,
end: Point2D<f32>,
}
impl<'a> PaintContext<'a> { impl<'a> PaintContext<'a> {
pub fn draw_target(&self) -> &DrawTarget { pub fn draw_target(&self) -> &DrawTarget {
&self.draw_target &self.draw_target
@ -355,6 +368,104 @@ impl<'a> PaintContext<'a> {
self.draw_target.push_clip(&path_builder.finish()); self.draw_target.push_clip(&path_builder.finish());
} }
fn solve_quadratic(a: f32, b: f32, c: f32) -> (Option<f32>, Option<f32>) {
let discriminant = b * b - 4. * a * c;
if discriminant < 0. {
return (None, None);
}
let x1 = (-b + discriminant.sqrt())/(2. * a);
let x2 = (-b - discriminant.sqrt())/(2. * a);
if discriminant == 0. {
return (Some(x1), None);
}
return (Some(x1), Some(x2));
}
fn intersect_ellipse_line(e: Ellipse, l: Line) -> (Option<Point2D<f32>>, Option<Point2D<f32>>) {
debug_assert!(l.end.x - l.start.x > f32::EPSILON, "Error line segment end.x > start.x!!");
// shift the origin to center of the ellipse.
let line = Line { start: l.start - e.origin,
end: l.end - e.origin };
let a = (line.end.y - line.start.y)/(line.end.x - line.start.x);
let b = line.start.y - (a * line.start.x);
// given the equation of a line,
// y = a * x + b,
// and the equation of an ellipse,
// x^2/w^2 + y^2/h^2 = 1,
// substitute y = a * x + b, giving
// x^2/w^2 + (a^2x^2 + 2abx + b^2)/h^2 = 1
// then simplify to
// (h^2 + w^2a^2)x^2 + 2abw^2x + (b^2w^2 - w^2h^2) = 0
// finally solve for w using the quadratic equation.
let w = e.width;
let h = e.height;
let quad_a = h * h + w * w * a * a;
let quad_b = 2. * a * b * w * w;
let quad_c = b * b * w * w - w * w * h * h;
let intersections = PaintContext::solve_quadratic(quad_a, quad_b, quad_c);
match intersections {
(Some(x0), Some(x1)) => {
let mut p0 = Point2D::new(x0, a * x0 + b) + e.origin;
let mut p1 = Point2D::new(x1, a * x1 + b) + e.origin;
if x0 > x1 {
mem::swap(&mut p0, &mut p1);
}
(Some(p0), Some(p1))
},
(Some(x0), None) => {
let p = Point2D::new(x0, a * x0 + b) + e.origin;
(Some(p), None)
},
(None, Some(x1)) => {
let p = Point2D::new(x1, a * x1 + b) + e.origin;
(Some(p), None)
},
(None, None) => (None, None),
}
}
// Given an ellipse and line segment, the line segment may intersect the
// ellipse at 0, 1, or 2 points. We compute those intersection points.
// For each intersection point the angle of the point on the ellipse relative to
// the top|bottom of the ellipse is computed.
// Examples:
// - intersection at ellipse.center + (0, ellipse.height), the angle is 0 rad.
// - intersection at ellipse.center + (0, -ellipse.height), the angle is 0 rad.
// - intersection at ellipse.center + (+-ellipse.width, 0), the angle is pi/2.
fn ellipse_line_intersection_angles(e: Ellipse, l: Line)
-> (Option<(Point2D<f32>, f32)>, Option<(Point2D<f32>, f32)>) {
fn point_angle(e: Ellipse, intersect_point: Point2D<f32>) -> f32 {
((intersect_point.y - e.origin.y).abs() / e.height).asin()
}
let intersection = PaintContext::intersect_ellipse_line(e, l);
match intersection {
(Some(p0), Some(p1)) => (Some((p0, point_angle(e, p0))), Some((p1, point_angle(e, p1)))),
(Some(p0), None) => (Some((p0, point_angle(e, p0))), None),
(None, Some(p1)) => (None, Some((p1, point_angle(e, p1)))),
(None, None) => (None, None),
}
}
fn ellipse_rightmost_line_intersection_angle(e: Ellipse, l: Line) -> Option<f32> {
match PaintContext::ellipse_line_intersection_angles(e, l) {
(Some((p0, angle0)), Some((p1, _))) if p0.x > p1.x => Some(angle0),
(_, Some((_, angle1))) => Some(angle1),
(Some((_, angle0)), None) => Some(angle0),
(None, None) => None,
}
}
fn ellipse_leftmost_line_intersection_angle(e: Ellipse, l: Line) -> Option<f32> {
match PaintContext::ellipse_line_intersection_angles(e, l) {
(Some((p0, angle0)), Some((p1, _))) if p0.x < p1.x => Some(angle0),
(_, Some((_, angle1))) => Some(angle1),
(Some((_, angle0)), None) => Some(angle0),
(None, None) => None,
}
}
// The following comment is wonderful, and stolen from // The following comment is wonderful, and stolen from
// gecko:gfx/thebes/gfxContext.cpp:RoundedRectangle for reference. // gecko:gfx/thebes/gfxContext.cpp:RoundedRectangle for reference.
// //
@ -450,6 +561,11 @@ impl<'a> PaintContext<'a> {
let box_BL = box_TL + Point2D::new(0.0, bounds.size.height); let box_BL = box_TL + Point2D::new(0.0, bounds.size.height);
let box_BR = box_TL + Point2D::new(bounds.size.width, bounds.size.height); let box_BR = box_TL + Point2D::new(bounds.size.width, bounds.size.height);
let inner_TL = box_TL + Point2D::new(border.left, border.top);
let inner_TR = box_TR + Point2D::new(-border.right, border.top);
let inner_BR = box_BR + Point2D::new(-border.right, -border.bottom);
let inner_BL = box_BL + Point2D::new(border.left, -border.bottom);
let rad_R: AzFloat = 0.; let rad_R: AzFloat = 0.;
let rad_BR = rad_R + f32::consts::FRAC_PI_4; let rad_BR = rad_R + f32::consts::FRAC_PI_4;
let rad_B = rad_BR + f32::consts::FRAC_PI_4; let rad_B = rad_BR + f32::consts::FRAC_PI_4;
@ -457,7 +573,6 @@ impl<'a> PaintContext<'a> {
let rad_L = rad_BL + f32::consts::FRAC_PI_4; let rad_L = rad_BL + f32::consts::FRAC_PI_4;
let rad_TL = rad_L + f32::consts::FRAC_PI_4; let rad_TL = rad_L + f32::consts::FRAC_PI_4;
let rad_T = rad_TL + f32::consts::FRAC_PI_4; let rad_T = rad_TL + f32::consts::FRAC_PI_4;
let rad_TR = rad_T + f32::consts::FRAC_PI_4;
fn dx(x: AzFloat) -> Point2D<AzFloat> { fn dx(x: AzFloat) -> Point2D<AzFloat> {
Point2D::new(x, 0.) Point2D::new(x, 0.)
@ -475,12 +590,41 @@ impl<'a> PaintContext<'a> {
Point2D::new(0., if cond { dy } else { 0. }) Point2D::new(0., if cond { dy } else { 0. })
} }
fn compatible_borders_corner(border1_width: f32, border2_width: f32) -> bool {
(border1_width - border2_width).abs() <= f32::EPSILON
}
let distance_to_elbow_TL =
if border.top == border.left {
(radius.top_left - border.top).max(0.)
} else {
0.
};
let distance_to_elbow_TR =
if border.top == border.right {
(radius.top_right - border.top).max(0.)
} else {
0.
};
let distance_to_elbow_BR =
if border.right == border.bottom {
(radius.bottom_right - border.bottom).max(0.)
} else {
0.
};
let distance_to_elbow_BL =
if border.left == border.bottom {
(radius.bottom_left - border.bottom).max(0.)
} else {
0.
};
match direction { match direction {
Direction::Top => { Direction::Top => {
let edge_TL = box_TL + dx(radius.top_left.max(border.left)); let edge_TL = box_TL + dx(radius.top_left.max(border.left));
let edge_TR = box_TR + dx(-radius.top_right.max(border.right)); let edge_TR = box_TR + dx(-radius.top_right.max(border.right));
let edge_BR = edge_TR + dy(border.top); let edge_BR = box_TR + dx(-border.right - distance_to_elbow_TR) + dy(border.top);
let edge_BL = edge_TL + dy(border.top); let edge_BL = box_TL + dx(border.left + distance_to_elbow_TL) + dy(border.top);
let corner_TL = edge_TL + dx_if(radius.top_left == 0., -border.left); let corner_TL = edge_TL + dx_if(radius.top_left == 0., -border.left);
let corner_TR = edge_TR + dx_if(radius.top_right == 0., border.right); let corner_TR = edge_TR + dx_if(radius.top_right == 0., border.right);
@ -497,11 +641,18 @@ impl<'a> PaintContext<'a> {
// the origin is the center of the arcs we're about to draw. // the origin is the center of the arcs we're about to draw.
let origin = edge_TR + Point2D::new((border.right - radius.top_right).max(0.), let origin = edge_TR + Point2D::new((border.right - radius.top_right).max(0.),
radius.top_right); radius.top_right);
// the elbow is the inside of the border's curve. let angle = if compatible_borders_corner(border.top, border.right) {
let distance_to_elbow = (radius.top_right - border.top).max(0.); f32::consts::FRAC_PI_4
} else {
let line = Line { start: inner_TR, end: box_TR };
let ellipse = Ellipse { origin: origin, width: radius.top_right, height: radius.top_right };
PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap()
};
path_builder.arc(origin, radius.top_right, rad_T, rad_TR, false); path_builder.arc(origin, radius.top_right, rad_T, rad_R - angle, false);
path_builder.arc(origin, distance_to_elbow, rad_TR, rad_T, true); if distance_to_elbow_TR != 0. {
path_builder.arc(origin, distance_to_elbow_TR, rad_R - angle, rad_T, true);
}
} }
match mode { match mode {
@ -514,18 +665,26 @@ impl<'a> PaintContext<'a> {
if radius.top_left != 0. { if radius.top_left != 0. {
let origin = edge_TL + Point2D::new(-(border.left - radius.top_left).max(0.), let origin = edge_TL + Point2D::new(-(border.left - radius.top_left).max(0.),
radius.top_left); radius.top_left);
let distance_to_elbow = (radius.top_left - border.top).max(0.); let angle = if compatible_borders_corner(border.top, border.left) {
f32::consts::FRAC_PI_4
} else {
let line = Line { start: box_TL, end: inner_TL };
let ellipse = Ellipse { origin: origin, width: radius.top_left, height: radius.top_left };
PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap()
};
path_builder.arc(origin, distance_to_elbow, rad_T, rad_TL, true); if distance_to_elbow_TL != 0. {
path_builder.arc(origin, radius.top_left, rad_TL, rad_T, false); path_builder.arc(origin, distance_to_elbow_TL, rad_T, rad_L + angle, true);
}
path_builder.arc(origin, radius.top_left, rad_L + angle, rad_T, false);
} }
} }
Direction::Left => { Direction::Left => {
let edge_TL = box_TL + dy(radius.top_left.max(border.top)); let edge_TL = box_TL + dy(radius.top_left.max(border.top));
let edge_BL = box_BL + dy(-radius.bottom_left.max(border.bottom)); let edge_BL = box_BL + dy(-radius.bottom_left.max(border.bottom));
let edge_TR = edge_TL + dx(border.left); let edge_TR = box_TL + dx(border.left) + dy(border.top + distance_to_elbow_TL);
let edge_BR = edge_BL + dx(border.left); let edge_BR = box_BL + dx(border.left) + dy(-border.bottom - distance_to_elbow_BL);
let corner_TL = edge_TL + dy_if(radius.top_left == 0., -border.top); let corner_TL = edge_TL + dy_if(radius.top_left == 0., -border.top);
let corner_BL = edge_BL + dy_if(radius.bottom_left == 0., border.bottom); let corner_BL = edge_BL + dy_if(radius.bottom_left == 0., border.bottom);
@ -540,11 +699,20 @@ impl<'a> PaintContext<'a> {
if radius.top_left != 0. { if radius.top_left != 0. {
let origin = edge_TL + Point2D::new(radius.top_left, let origin = edge_TL + Point2D::new(radius.top_left,
-(border.top - radius.top_left).max(0.)); -(border.top - radius.top_left).max(0.));
let distance_to_elbow = (radius.top_left - border.left).max(0.);
path_builder.arc(origin, radius.top_left, rad_L, rad_TL, false); let angle = if compatible_borders_corner(border.top, border.left) {
path_builder.arc(origin, distance_to_elbow, rad_TL, rad_L, true); f32::consts::FRAC_PI_4
} else {
let line = Line { start: box_TL, end: inner_TL };
let ellipse = Ellipse { origin: origin, width: radius.top_left, height: radius.top_left };
PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap()
};
path_builder.arc(origin, radius.top_left, rad_L, rad_L + angle, false);
if distance_to_elbow_TL != 0. {
path_builder.arc(origin, distance_to_elbow_TL, rad_L + angle, rad_L, true);
}
} }
match mode { match mode {
@ -558,18 +726,28 @@ impl<'a> PaintContext<'a> {
if radius.bottom_left != 0. { if radius.bottom_left != 0. {
let origin = edge_BL + let origin = edge_BL +
Point2D::new(radius.bottom_left, Point2D::new(radius.bottom_left,
(border.bottom - radius.bottom_left).max(0.)); (border.bottom - radius.bottom_left).max(0.));
let distance_to_elbow = (radius.bottom_left - border.left).max(0.); let angle = if compatible_borders_corner(border.bottom, border.left) {
f32::consts::FRAC_PI_4
} else {
let line = Line { start: box_BL, end: inner_BL };
let ellipse = Ellipse { origin: origin,
width: radius.bottom_left,
height: radius.bottom_left };
PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap()
};
path_builder.arc(origin, distance_to_elbow, rad_L, rad_BL, true); if distance_to_elbow_BL != 0. {
path_builder.arc(origin, radius.bottom_left, rad_BL, rad_L, false); path_builder.arc(origin, distance_to_elbow_BL, rad_L, rad_L - angle, true);
}
path_builder.arc(origin, radius.bottom_left, rad_L - angle, rad_L, false);
} }
} }
Direction::Right => { Direction::Right => {
let edge_TR = box_TR + dy(radius.top_right.max(border.top)); let edge_TR = box_TR + dy(radius.top_right.max(border.top));
let edge_BR = box_BR + dy(-radius.bottom_right.max(border.bottom)); let edge_BR = box_BR + dy(-radius.bottom_right.max(border.bottom));
let edge_TL = edge_TR + dx(-border.right); let edge_TL = box_TR + dx(-border.right) + dy(border.top + distance_to_elbow_TR);
let edge_BL = edge_BR + dx(-border.right); let edge_BL = box_BR + dx(-border.right) + dy(-border.bottom - distance_to_elbow_BR);
let corner_TR = edge_TR + dy_if(radius.top_right == 0., -border.top); let corner_TR = edge_TR + dy_if(radius.top_right == 0., -border.top);
let corner_BR = edge_BR + dy_if(radius.bottom_right == 0., border.bottom); let corner_BR = edge_BR + dy_if(radius.bottom_right == 0., border.bottom);
@ -585,10 +763,18 @@ impl<'a> PaintContext<'a> {
if radius.top_right != 0. { if radius.top_right != 0. {
let origin = edge_TR + Point2D::new(-radius.top_right, let origin = edge_TR + Point2D::new(-radius.top_right,
-(border.top - radius.top_right).max(0.)); -(border.top - radius.top_right).max(0.));
let distance_to_elbow = (radius.top_right - border.right).max(0.); let angle = if compatible_borders_corner(border.top, border.right) {
f32::consts::FRAC_PI_4
} else {
let line = Line { start: inner_TR, end: box_TR };
let ellipse = Ellipse { origin: origin, width: radius.top_right, height: radius.top_right };
PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap()
};
path_builder.arc(origin, distance_to_elbow, rad_R, rad_TR, true); if distance_to_elbow_TR != 0. {
path_builder.arc(origin, radius.top_right, rad_TR, rad_R, false); path_builder.arc(origin, distance_to_elbow_TR, rad_R, rad_R - angle, true);
}
path_builder.arc(origin, radius.top_right, rad_R - angle, rad_R, false);
} }
match mode { match mode {
@ -602,18 +788,28 @@ impl<'a> PaintContext<'a> {
if radius.bottom_right != 0. { if radius.bottom_right != 0. {
let origin = edge_BR + let origin = edge_BR +
Point2D::new(-radius.bottom_right, Point2D::new(-radius.bottom_right,
(border.bottom - radius.bottom_right).max(0.)); (border.bottom - radius.bottom_right).max(0.));
let distance_to_elbow = (radius.bottom_right - border.right).max(0.); let angle = if compatible_borders_corner(border.bottom, border.right) {
f32::consts::FRAC_PI_4
} else {
let line = Line { start: inner_BR, end: box_BR };
let ellipse = Ellipse { origin: origin,
width: radius.bottom_right,
height: radius.bottom_right };
PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap()
};
path_builder.arc(origin, radius.bottom_right, rad_R, rad_BR, false); path_builder.arc(origin, radius.bottom_right, rad_R, rad_R + angle, false);
path_builder.arc(origin, distance_to_elbow, rad_BR, rad_R, true); if distance_to_elbow_BR != 0. {
path_builder.arc(origin, distance_to_elbow_BR, rad_R + angle, rad_R, true);
}
} }
} }
Direction::Bottom => { Direction::Bottom => {
let edge_BL = box_BL + dx(radius.bottom_left.max(border.left)); let edge_BL = box_BL + dx(radius.bottom_left.max(border.left));
let edge_BR = box_BR + dx(-radius.bottom_right.max(border.right)); let edge_BR = box_BR + dx(-radius.bottom_right.max(border.right));
let edge_TL = edge_BL + dy(-border.bottom); let edge_TL = box_BL + dy(-border.bottom) + dx(border.left + distance_to_elbow_BL);
let edge_TR = edge_BR + dy(-border.bottom); let edge_TR = box_BR + dy(-border.bottom) + dx(-border.right - distance_to_elbow_BR);
let corner_BR = edge_BR + dx_if(radius.bottom_right == 0., border.right); let corner_BR = edge_BR + dx_if(radius.bottom_right == 0., border.right);
let corner_BL = edge_BL + dx_if(radius.bottom_left == 0., -border.left); let corner_BL = edge_BL + dx_if(radius.bottom_left == 0., -border.left);
@ -629,10 +825,20 @@ impl<'a> PaintContext<'a> {
if radius.bottom_right != 0. { if radius.bottom_right != 0. {
let origin = edge_BR + Point2D::new((border.right - radius.bottom_right).max(0.), let origin = edge_BR + Point2D::new((border.right - radius.bottom_right).max(0.),
-radius.bottom_right); -radius.bottom_right);
let distance_to_elbow = (radius.bottom_right - border.bottom).max(0.); let angle = if compatible_borders_corner(border.bottom, border.right) {
f32::consts::FRAC_PI_4
} else {
let line = Line { start: inner_BR, end: box_BR };
let ellipse = Ellipse { origin: origin,
width: radius.bottom_right,
height: radius.bottom_right };
PaintContext::ellipse_rightmost_line_intersection_angle(ellipse, line).unwrap()
};
path_builder.arc(origin, distance_to_elbow, rad_B, rad_BR, true); if distance_to_elbow_BR != 0. {
path_builder.arc(origin, radius.bottom_right, rad_BR, rad_B, false); path_builder.arc(origin, distance_to_elbow_BR, rad_B, rad_R + angle, true);
}
path_builder.arc(origin, radius.bottom_right, rad_R + angle, rad_B, false);
} }
match mode { match mode {
@ -645,11 +851,21 @@ impl<'a> PaintContext<'a> {
if radius.bottom_left != 0. { if radius.bottom_left != 0. {
let origin = edge_BL - Point2D::new((border.left - radius.bottom_left).max(0.), let origin = edge_BL - Point2D::new((border.left - radius.bottom_left).max(0.),
radius.bottom_left); radius.bottom_left);
let distance_to_elbow = (radius.bottom_left - border.bottom).max(0.); let angle = if compatible_borders_corner(border.bottom, border.left) {
f32::consts::FRAC_PI_4
} else {
let line = Line { start: box_BL, end: inner_BL };
let ellipse = Ellipse { origin: origin,
width: radius.bottom_left,
height: radius.bottom_left };
PaintContext::ellipse_leftmost_line_intersection_angle(ellipse, line).unwrap()
};
path_builder.arc(origin, radius.bottom_left, rad_B, rad_BL, false); path_builder.arc(origin, radius.bottom_left, rad_B, rad_L - angle, false);
path_builder.arc(origin, distance_to_elbow, rad_BL, rad_B, true); if distance_to_elbow_BL != 0. {
path_builder.arc(origin, distance_to_elbow_BL, rad_L - angle, rad_B, true);
}
} }
} }
} }

View file

@ -139,7 +139,7 @@ pub fn get_system_default_family(generic_name: &str) -> Option<String> {
} }
} }
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
pub fn get_last_resort_font_families() -> Vec<String> { pub fn get_last_resort_font_families() -> Vec<String> {
vec!( vec!(
"Fira Sans".to_owned(), "Fira Sans".to_owned(),
@ -148,7 +148,7 @@ pub fn get_last_resort_font_families() -> Vec<String> {
) )
} }
#[cfg(target_os="android")] #[cfg(target_os = "android")]
pub fn get_last_resort_font_families() -> Vec<String> { pub fn get_last_resort_font_families() -> Vec<String> {
vec!("Roboto".to_owned()) vec!("Roboto".to_owned())
} }

View file

@ -33,11 +33,6 @@ pub struct FontTable {
data: CFData, data: CFData,
} }
// Noncopyable.
impl Drop for FontTable {
fn drop(&mut self) {}
}
impl FontTable { impl FontTable {
pub fn wrap(data: CFData) -> FontTable { pub fn wrap(data: CFData) -> FontTable {
FontTable { data: data } FontTable { data: data }

View file

@ -2,13 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#[cfg(any(target_os="linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
pub use platform::freetype::{font, font_context, font_list, font_template}; pub use platform::freetype::{font, font_context, font_list, font_template};
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
pub use platform::macos::{font, font_context, font_list, font_template}; pub use platform::macos::{font, font_context, font_list, font_template};
#[cfg(any(target_os="linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
pub mod freetype { pub mod freetype {
pub mod font; pub mod font;
pub mod font_context; pub mod font_context;
@ -16,7 +16,7 @@ pub mod freetype {
pub mod font_template; pub mod font_template;
} }
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
pub mod macos { pub mod macos {
pub mod font; pub mod font;
pub mod font_context; pub mod font_context;

View file

@ -58,17 +58,7 @@ impl GlyphEntry {
starts_ligature, starts_ligature,
glyph_count); glyph_count);
let mut val = FLAG_NOT_MISSING; GlyphEntry::new(glyph_count as u32)
if !starts_cluster {
val |= FLAG_NOT_CLUSTER_START;
}
if !starts_ligature {
val |= FLAG_NOT_LIGATURE_GROUP_START;
}
val |= (glyph_count as u32) << GLYPH_COUNT_SHIFT;
GlyphEntry::new(val)
} }
/// Create a GlyphEntry for the case where glyphs couldn't be found for the specified /// Create a GlyphEntry for the case where glyphs couldn't be found for the specified
@ -76,55 +66,22 @@ impl GlyphEntry {
fn missing(glyph_count: usize) -> GlyphEntry { fn missing(glyph_count: usize) -> GlyphEntry {
assert!(glyph_count <= u16::MAX as usize); assert!(glyph_count <= u16::MAX as usize);
GlyphEntry::new((glyph_count as u32) << GLYPH_COUNT_SHIFT) GlyphEntry::new(glyph_count as u32)
} }
} }
/// The id of a particular glyph within a font /// The id of a particular glyph within a font
pub type GlyphId = u32; pub type GlyphId = u32;
// TODO: unify with bit flags?
#[derive(PartialEq, Copy, Clone)]
pub enum BreakType {
None,
Normal,
Hyphen,
}
static BREAK_TYPE_NONE: u8 = 0x0;
static BREAK_TYPE_NORMAL: u8 = 0x1;
static BREAK_TYPE_HYPHEN: u8 = 0x2;
fn break_flag_to_enum(flag: u8) -> BreakType {
if (flag & BREAK_TYPE_NORMAL) != 0 {
BreakType::Normal
} else if (flag & BREAK_TYPE_HYPHEN) != 0 {
BreakType::Hyphen
} else {
BreakType::None
}
}
fn break_enum_to_flag(e: BreakType) -> u8 {
match e {
BreakType::None => BREAK_TYPE_NONE,
BreakType::Normal => BREAK_TYPE_NORMAL,
BreakType::Hyphen => BREAK_TYPE_HYPHEN,
}
}
// TODO: make this more type-safe. // TODO: make this more type-safe.
static FLAG_CHAR_IS_SPACE: u32 = 0x10000000; const FLAG_CHAR_IS_SPACE: u32 = 0x40000000;
// These two bits store some BREAK_TYPE_* flags const FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000;
static FLAG_CAN_BREAK_MASK: u32 = 0x60000000;
static FLAG_CAN_BREAK_SHIFT: u32 = 29;
static FLAG_IS_SIMPLE_GLYPH: u32 = 0x80000000;
// glyph advance; in Au's. // glyph advance; in Au's.
static GLYPH_ADVANCE_MASK: u32 = 0x0FFF0000; const GLYPH_ADVANCE_MASK: u32 = 0x3FFF0000;
static GLYPH_ADVANCE_SHIFT: u32 = 16; const GLYPH_ADVANCE_SHIFT: u32 = 16;
static GLYPH_ID_MASK: u32 = 0x0000FFFF; const GLYPH_ID_MASK: u32 = 0x0000FFFF;
// Non-simple glyphs (more than one glyph per char; missing glyph, // Non-simple glyphs (more than one glyph per char; missing glyph,
// newline, tab, large advance, or nonzero x/y offsets) may have one // newline, tab, large advance, or nonzero x/y offsets) may have one
@ -132,21 +89,8 @@ static GLYPH_ID_MASK: u32 = 0x0000FFFF;
// side array so that there is a 1:1 mapping of GlyphEntry to // side array so that there is a 1:1 mapping of GlyphEntry to
// unicode char. // unicode char.
// The number of detailed glyphs for this char. If the char couldn't // The number of detailed glyphs for this char.
// be mapped to a glyph (!FLAG_NOT_MISSING), then this actually holds const GLYPH_COUNT_MASK: u32 = 0x0000FFFF;
// the UTF8 code point instead.
static GLYPH_COUNT_MASK: u32 = 0x00FFFF00;
static GLYPH_COUNT_SHIFT: u32 = 8;
// N.B. following Gecko, these are all inverted so that a lot of
// missing chars can be memset with zeros in one fell swoop.
static FLAG_NOT_MISSING: u32 = 0x00000001;
static FLAG_NOT_CLUSTER_START: u32 = 0x00000002;
static FLAG_NOT_LIGATURE_GROUP_START: u32 = 0x00000004;
static FLAG_CHAR_IS_TAB: u32 = 0x00000008;
static FLAG_CHAR_IS_NEWLINE: u32 = 0x00000010;
//static FLAG_CHAR_IS_LOW_SURROGATE: u32 = 0x00000020;
//static CHAR_IDENTITY_FLAGS_MASK: u32 = 0x00000038;
fn is_simple_glyph_id(id: GlyphId) -> bool { fn is_simple_glyph_id(id: GlyphId) -> bool {
((id as u32) & GLYPH_ID_MASK) == id ((id as u32) & GLYPH_ID_MASK) == id
@ -164,7 +108,6 @@ type DetailedGlyphCount = u16;
// Getters and setters for GlyphEntry. Setter methods are functional, // Getters and setters for GlyphEntry. Setter methods are functional,
// because GlyphEntry is immutable and only a u32 in size. // because GlyphEntry is immutable and only a u32 in size.
impl GlyphEntry { impl GlyphEntry {
// getter methods
#[inline(always)] #[inline(always)]
fn advance(&self) -> Au { fn advance(&self) -> Au {
Au(((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT) as i32) Au(((self.value & GLYPH_ADVANCE_MASK) >> GLYPH_ADVANCE_SHIFT) as i32)
@ -174,62 +117,20 @@ impl GlyphEntry {
self.value & GLYPH_ID_MASK self.value & GLYPH_ID_MASK
} }
fn is_ligature_start(&self) -> bool { /// True if original char was normal (U+0020) space. Other chars may
self.has_flag(!FLAG_NOT_LIGATURE_GROUP_START) /// map to space glyph, but this does not account for them.
}
fn is_cluster_start(&self) -> bool {
self.has_flag(!FLAG_NOT_CLUSTER_START)
}
// True if original char was normal (U+0020) space. Other chars may
// map to space glyph, but this does not account for them.
fn char_is_space(&self) -> bool { fn char_is_space(&self) -> bool {
self.has_flag(FLAG_CHAR_IS_SPACE) self.has_flag(FLAG_CHAR_IS_SPACE)
} }
fn char_is_tab(&self) -> bool {
!self.is_simple() && self.has_flag(FLAG_CHAR_IS_TAB)
}
fn char_is_newline(&self) -> bool {
!self.is_simple() && self.has_flag(FLAG_CHAR_IS_NEWLINE)
}
fn can_break_before(&self) -> BreakType {
let flag = ((self.value & FLAG_CAN_BREAK_MASK) >> FLAG_CAN_BREAK_SHIFT) as u8;
break_flag_to_enum(flag)
}
// setter methods
#[inline(always)] #[inline(always)]
fn set_char_is_space(&self) -> GlyphEntry { fn set_char_is_space(&self) -> GlyphEntry {
GlyphEntry::new(self.value | FLAG_CHAR_IS_SPACE) GlyphEntry::new(self.value | FLAG_CHAR_IS_SPACE)
} }
#[inline(always)]
fn set_char_is_tab(&self) -> GlyphEntry {
assert!(!self.is_simple());
GlyphEntry::new(self.value | FLAG_CHAR_IS_TAB)
}
#[inline(always)]
fn set_char_is_newline(&self) -> GlyphEntry {
assert!(!self.is_simple());
GlyphEntry::new(self.value | FLAG_CHAR_IS_NEWLINE)
}
#[inline(always)]
fn set_can_break_before(&self, e: BreakType) -> GlyphEntry {
let flag = (break_enum_to_flag(e) as u32) << FLAG_CAN_BREAK_SHIFT;
GlyphEntry::new(self.value | flag)
}
// helper methods
fn glyph_count(&self) -> u16 { fn glyph_count(&self) -> u16 {
assert!(!self.is_simple()); assert!(!self.is_simple());
((self.value & GLYPH_COUNT_MASK) >> GLYPH_COUNT_SHIFT) as u16 (self.value & GLYPH_COUNT_MASK) as u16
} }
#[inline(always)] #[inline(always)]
@ -576,9 +477,6 @@ impl<'a> GlyphStore {
} }
}; };
// FIXME(pcwalton): Is this necessary? I think it's a no-op.
entry = entry.adapt_character_flags_of_entry(self.entry_buffer[i.to_usize()]);
if character == Some(' ') { if character == Some(' ') {
entry = entry.set_char_is_space() entry = entry.set_char_is_space()
} }
@ -647,62 +545,11 @@ impl<'a> GlyphStore {
.fold(Au(0), |advance, (_, glyph)| advance + glyph.advance()) .fold(Au(0), |advance, (_, glyph)| advance + glyph.advance())
} }
// getter methods
pub fn char_is_space(&self, i: CharIndex) -> bool { pub fn char_is_space(&self, i: CharIndex) -> bool {
assert!(i < self.char_len()); assert!(i < self.char_len());
self.entry_buffer[i.to_usize()].char_is_space() self.entry_buffer[i.to_usize()].char_is_space()
} }
pub fn char_is_tab(&self, i: CharIndex) -> bool {
assert!(i < self.char_len());
self.entry_buffer[i.to_usize()].char_is_tab()
}
pub fn char_is_newline(&self, i: CharIndex) -> bool {
assert!(i < self.char_len());
self.entry_buffer[i.to_usize()].char_is_newline()
}
pub fn is_ligature_start(&self, i: CharIndex) -> bool {
assert!(i < self.char_len());
self.entry_buffer[i.to_usize()].is_ligature_start()
}
pub fn is_cluster_start(&self, i: CharIndex) -> bool {
assert!(i < self.char_len());
self.entry_buffer[i.to_usize()].is_cluster_start()
}
pub fn can_break_before(&self, i: CharIndex) -> BreakType {
assert!(i < self.char_len());
self.entry_buffer[i.to_usize()].can_break_before()
}
// setter methods
pub fn set_char_is_space(&mut self, i: CharIndex) {
assert!(i < self.char_len());
let entry = self.entry_buffer[i.to_usize()];
self.entry_buffer[i.to_usize()] = entry.set_char_is_space();
}
pub fn set_char_is_tab(&mut self, i: CharIndex) {
assert!(i < self.char_len());
let entry = self.entry_buffer[i.to_usize()];
self.entry_buffer[i.to_usize()] = entry.set_char_is_tab();
}
pub fn set_char_is_newline(&mut self, i: CharIndex) {
assert!(i < self.char_len());
let entry = self.entry_buffer[i.to_usize()];
self.entry_buffer[i.to_usize()] = entry.set_char_is_newline();
}
pub fn set_can_break_before(&mut self, i: CharIndex, t: BreakType) {
assert!(i < self.char_len());
let entry = self.entry_buffer[i.to_usize()];
self.entry_buffer[i.to_usize()] = entry.set_can_break_before(t);
}
pub fn space_count_in_range(&self, range: &Range<CharIndex>) -> u32 { pub fn space_count_in_range(&self, range: &Range<CharIndex>) -> u32 {
let mut spaces = 0; let mut spaces = 0;
for index in range.each_index() { for index in range.each_index() {

View file

@ -576,13 +576,13 @@ extern fn glyph_h_advance_func(_: *mut hb_font_t,
fn glyph_space_advance(font: *mut Font) -> f64 { fn glyph_space_advance(font: *mut Font) -> f64 {
let space_unicode = ' '; let space_unicode = ' ';
let space_glyph: hb_codepoint_t; let space_glyph: hb_codepoint_t;
match unsafe {(*font).glyph_index(space_unicode)} { match unsafe { (*font).glyph_index(space_unicode) } {
Some(g) => { Some(g) => {
space_glyph = g as hb_codepoint_t; space_glyph = g as hb_codepoint_t;
} }
None => panic!("No space info") None => panic!("No space info")
} }
let space_advance = unsafe {(*font).glyph_h_advance(space_glyph as GlyphId)}; let space_advance = unsafe { (*font).glyph_h_advance(space_glyph as GlyphId) };
space_advance space_advance
} }

View file

@ -570,7 +570,7 @@ pub struct BlockFlow {
bitflags! { bitflags! {
flags BlockFlowFlags: u8 { flags BlockFlowFlags: u8 {
#[doc="If this is set, then this block flow is the root flow."] #[doc = "If this is set, then this block flow is the root flow."]
const IS_ROOT = 0x01, const IS_ROOT = 0x01,
} }
} }

View file

@ -54,7 +54,7 @@ impl PrivateLayoutData {
bitflags! { bitflags! {
flags LayoutDataFlags: u8 { flags LayoutDataFlags: u8 {
#[doc="Whether a flow has been newly constructed."] #[doc = "Whether a flow has been newly constructed."]
const HAS_NEWLY_CONSTRUCTED_FLOW = 0x01 const HAS_NEWLY_CONSTRUCTED_FLOW = 0x01
} }
} }

View file

@ -313,6 +313,10 @@ impl Flow for FlexFlow {
&mut self.block_flow &mut self.block_flow
} }
fn mark_as_root(&mut self) {
self.block_flow.mark_as_root();
}
fn bubble_inline_sizes(&mut self) { fn bubble_inline_sizes(&mut self) {
let _scope = layout_debug_scope!("flex::bubble_inline_sizes {:x}", let _scope = layout_debug_scope!("flex::bubble_inline_sizes {:x}",
self.block_flow.base.debug_id()); self.block_flow.base.debug_id());

View file

@ -2309,10 +2309,10 @@ bitflags! {
// Various flags we can use when splitting fragments. See // Various flags we can use when splitting fragments. See
// `calculate_split_position_using_breaking_strategy()`. // `calculate_split_position_using_breaking_strategy()`.
flags SplitOptions: u8 { flags SplitOptions: u8 {
#[doc="True if this is the first fragment on the line."] #[doc = "True if this is the first fragment on the line."]
const STARTS_LINE = 0x01, const STARTS_LINE = 0x01,
#[doc="True if we should attempt to split at character boundaries if this split fails. \ #[doc = "True if we should attempt to split at character boundaries if this split fails. \
This is used to implement `overflow-wrap: break-word`."] This is used to implement `overflow-wrap: break-word`."]
const RETRY_AT_CHARACTER_BOUNDARIES = 0x02, const RETRY_AT_CHARACTER_BOUNDARIES = 0x02,
} }
} }

View file

@ -42,8 +42,8 @@ bitflags! {
bitflags! { bitflags! {
flags SpecialRestyleDamage: u8 { flags SpecialRestyleDamage: u8 {
#[doc="If this flag is set, we need to reflow the entire document. This is more or less a \ #[doc = "If this flag is set, we need to reflow the entire document. This is more or less a \
temporary hack to deal with cases that we don't handle incrementally yet."] temporary hack to deal with cases that we don't handle incrementally yet."]
const REFLOW_ENTIRE_DOCUMENT = 0x01, const REFLOW_ENTIRE_DOCUMENT = 0x01,
} }
} }

View file

@ -183,9 +183,9 @@ int_range_index! {
bitflags! { bitflags! {
flags InlineReflowFlags: u8 { flags InlineReflowFlags: u8 {
#[doc="The `white-space: nowrap` property from CSS 2.1 § 16.6 is in effect."] #[doc = "The `white-space: nowrap` property from CSS 2.1 § 16.6 is in effect."]
const NO_WRAP_INLINE_REFLOW_FLAG = 0x01, const NO_WRAP_INLINE_REFLOW_FLAG = 0x01,
#[doc="The `white-space: pre` property from CSS 2.1 § 16.6 is in effect."] #[doc = "The `white-space: pre` property from CSS 2.1 § 16.6 is in effect."]
const WRAP_ON_NEWLINE_INLINE_REFLOW_FLAG = 0x02 const WRAP_ON_NEWLINE_INLINE_REFLOW_FLAG = 0x02
} }
} }

View file

@ -13,12 +13,12 @@
#![deny(unsafe_code)] #![deny(unsafe_code)]
use block::{BlockFlow, FloatNonReplaced, ISizeAndMarginsComputer, ISizeConstraintInput}; use block::{BlockFlow, FloatNonReplaced, AbsoluteNonReplaced, ISizeAndMarginsComputer, ISizeConstraintInput};
use block::{ISizeConstraintSolution, MarginsMayCollapseFlag}; use block::{ISizeConstraintSolution, MarginsMayCollapseFlag};
use context::LayoutContext; use context::LayoutContext;
use floats::FloatKind; use floats::FloatKind;
use flow::{FlowClass, Flow, ImmutableFlowUtils}; use flow::{FlowClass, Flow, ImmutableFlowUtils};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, OpaqueFlow}; use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC, OpaqueFlow};
use fragment::{Fragment, FragmentBorderBoxIterator}; use fragment::{Fragment, FragmentBorderBoxIterator};
use model::MaybeAuto; use model::MaybeAuto;
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize}; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
@ -242,6 +242,26 @@ impl TableWrapperFlow {
return return
} }
if !self.block_flow.base.flags.contains(INLINE_POSITION_IS_STATIC) {
let inline_size_computer = AbsoluteTable {
minimum_width_of_all_columns: minimum_width_of_all_columns,
preferred_width_of_all_columns: preferred_width_of_all_columns,
border_collapse: border_collapse,
};
let input =
inline_size_computer.compute_inline_size_constraint_inputs(&mut self.block_flow,
parent_flow_inline_size,
layout_context);
let solution = inline_size_computer.solve_inline_size_constraints(&mut self.block_flow,
&input);
inline_size_computer.set_inline_size_constraint_solutions(&mut self.block_flow,
solution);
inline_size_computer.set_inline_position_of_flow_if_necessary(&mut self.block_flow,
solution);
return
}
let inline_size_computer = Table { let inline_size_computer = Table {
minimum_width_of_all_columns: minimum_width_of_all_columns, minimum_width_of_all_columns: minimum_width_of_all_columns,
preferred_width_of_all_columns: preferred_width_of_all_columns, preferred_width_of_all_columns: preferred_width_of_all_columns,
@ -791,3 +811,54 @@ impl ISizeAndMarginsComputer for FloatedTable {
FloatNonReplaced.solve_inline_size_constraints(block, input) FloatNonReplaced.solve_inline_size_constraints(block, input)
} }
} }
struct AbsoluteTable {
minimum_width_of_all_columns: Au,
preferred_width_of_all_columns: Au,
border_collapse: border_collapse::T,
}
impl ISizeAndMarginsComputer for AbsoluteTable {
fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) {
block.fragment.compute_border_and_padding(containing_block_inline_size,
self.border_collapse)
}
fn initial_computed_inline_size(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
layout_context: &LayoutContext)
-> MaybeAuto {
let containing_block_inline_size =
self.containing_block_inline_size(block,
parent_flow_inline_size,
layout_context);
initial_computed_inline_size(block,
containing_block_inline_size,
self.minimum_width_of_all_columns,
self.preferred_width_of_all_columns)
}
fn containing_block_inline_size(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
layout_context: &LayoutContext)
-> Au {
AbsoluteNonReplaced.containing_block_inline_size(block, parent_flow_inline_size, layout_context)
}
fn solve_inline_size_constraints(&self,
block: &mut BlockFlow,
input: &ISizeConstraintInput)
-> ISizeConstraintSolution {
AbsoluteNonReplaced.solve_inline_size_constraints(block, input)
}
fn set_inline_position_of_flow_if_necessary(&self,
block: &mut BlockFlow,
solution: ISizeConstraintSolution) {
AbsoluteNonReplaced.set_inline_position_of_flow_if_necessary(block, solution);
}
}

View file

@ -20,9 +20,9 @@ extern crate util;
extern crate url; extern crate url;
extern crate style; extern crate style;
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
extern crate core_foundation; extern crate core_foundation;
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
extern crate io_surface; extern crate io_surface;
pub mod compositor_msg; pub mod compositor_msg;

View file

@ -2,49 +2,47 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, NetworkEvent}; use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg, NetworkEvent};
use hsts::{HSTSList, secure_url}; use file_loader;
use flate2::read::{DeflateDecoder, GzDecoder};
use hsts::secure_url;
use hyper::Error as HttpError;
use hyper::client::{Request, Response};
use hyper::header::{AcceptEncoding, Accept, ContentLength, ContentType, Host};
use hyper::header::{Location, qitem, StrictTransportSecurity};
use hyper::header::{Quality, QualityItem, Headers, ContentEncoding, Encoding};
use hyper::http::RawStatus;
use hyper::method::Method;
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::net::{Fresh, HttpsConnector, Openssl};
use hyper::status::{StatusCode, StatusClass};
use ipc_channel::ipc::{self, IpcSender};
use log;
use mime_classifier::MIMEClassifier; use mime_classifier::MIMEClassifier;
use net_traits::ProgressMsg::{Payload, Done}; use net_traits::ProgressMsg::{Payload, Done};
use net_traits::hosts::replace_hosts; use net_traits::hosts::replace_hosts;
use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer, IncludeSubdomains}; use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer, IncludeSubdomains};
use resource_task::{start_sending_opt, start_sending_sniffed_opt};
use file_loader;
use flate2::read::{DeflateDecoder, GzDecoder};
use hyper::Error as HttpError;
use hyper::client::Request;
use hyper::header::StrictTransportSecurity;
use hyper::header::{AcceptEncoding, Accept, ContentLength, ContentType, Host, Location, qitem, Quality, QualityItem};
use hyper::method::Method;
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::net::{HttpConnector, HttpsConnector, Openssl};
use hyper::status::{StatusCode, StatusClass};
use ipc_channel::ipc::{self, IpcSender};
use log;
use openssl::ssl::{SslContext, SslMethod, SSL_VERIFY_PEER}; use openssl::ssl::{SslContext, SslMethod, SSL_VERIFY_PEER};
use resource_task::{start_sending_opt, start_sending_sniffed_opt};
use std::borrow::ToOwned;
use std::boxed::FnBox;
use std::collections::HashSet; use std::collections::HashSet;
use std::error::Error; use std::error::Error;
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex;
use std::sync::mpsc::{Sender, channel}; use std::sync::mpsc::{Sender, channel};
use url::{Url, UrlParser}; use url::{Url, UrlParser};
use util::opts;
use util::resource_files::resources_dir_path; use util::resource_files::resources_dir_path;
use util::task::spawn_named; use util::task::spawn_named;
use std::borrow::ToOwned;
use std::boxed::FnBox;
use uuid; use uuid;
pub fn factory(resource_mgr_chan: IpcSender<ControlMsg>, pub fn factory(resource_mgr_chan: IpcSender<ControlMsg>,
devtools_chan: Option<Sender<DevtoolsControlMsg>>, devtools_chan: Option<Sender<DevtoolsControlMsg>>)
hsts_list: Arc<Mutex<HSTSList>>)
-> Box<FnBox(LoadData, LoadConsumer, Arc<MIMEClassifier>) + Send> { -> Box<FnBox(LoadData, LoadConsumer, Arc<MIMEClassifier>) + Send> {
box move |load_data, senders, classifier| { box move |load_data: LoadData, senders, classifier| {
spawn_named("http_loader".to_owned(), spawn_named(format!("http_loader for {}", load_data.url.serialize()),
move || load(load_data, senders, classifier, resource_mgr_chan, devtools_chan, hsts_list)) move || load_for_consumer(load_data, senders, classifier, resource_mgr_chan, devtools_chan))
} }
} }
@ -76,21 +74,365 @@ fn read_block<R: Read>(reader: &mut R) -> Result<ReadResult, ()> {
} }
} }
fn request_must_be_secured(hsts_list: &HSTSList, url: &Url) -> bool { fn inner_url(url: &Url) -> Url {
match url.domain() { let inner_url = url.non_relative_scheme_data().unwrap();
Some(ref h) => { Url::parse(inner_url).unwrap()
hsts_list.is_host_secure(h) }
},
_ => false fn load_for_consumer(load_data: LoadData,
start_chan: LoadConsumer,
classifier: Arc<MIMEClassifier>,
resource_mgr_chan: IpcSender<ControlMsg>,
devtools_chan: Option<Sender<DevtoolsControlMsg>>) {
match load::<WrappedHttpRequest>(load_data, resource_mgr_chan, devtools_chan, &NetworkHttpRequestFactory) {
Err(LoadError::UnsupportedScheme(url)) => {
let s = format!("{} request, but we don't support that scheme", &*url.scheme);
send_error(url, s, start_chan)
}
Err(LoadError::Connection(url, e)) => {
send_error(url, e, start_chan)
}
Err(LoadError::MaxRedirects(url)) => {
send_error(url, "too many redirects".to_string(), start_chan)
}
Err(LoadError::Cors(url, msg)) |
Err(LoadError::InvalidRedirect(url, msg)) |
Err(LoadError::Decoding(url, msg)) => {
send_error(url, msg, start_chan)
}
Err(LoadError::Ssl(url, msg)) => {
info!("ssl validation error {}, '{}'", url.serialize(), msg);
let mut image = resources_dir_path();
image.push("badcert.html");
let load_data = LoadData::new(Url::from_file_path(&*image).unwrap(), None);
file_loader::factory(load_data, start_chan, classifier)
}
Ok(mut load_response) => {
let metadata = load_response.metadata.clone();
send_data(&mut load_response, start_chan, metadata, classifier)
}
} }
} }
fn load(mut load_data: LoadData, pub trait HttpResponse: Read {
start_chan: LoadConsumer, fn headers(&self) -> &Headers;
classifier: Arc<MIMEClassifier>, fn status(&self) -> StatusCode;
resource_mgr_chan: IpcSender<ControlMsg>, fn status_raw(&self) -> &RawStatus;
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
hsts_list: Arc<Mutex<HSTSList>>) { fn content_encoding(&self) -> Option<Encoding> {
self.headers().get::<ContentEncoding>().and_then(|h| {
match h {
&ContentEncoding(ref encodings) => {
if encodings.contains(&Encoding::Gzip) {
Some(Encoding::Gzip)
} else if encodings.contains(&Encoding::Deflate) {
Some(Encoding::Deflate)
} else {
// TODO: Is this the correct behaviour?
None
}
}
}
})
}
}
struct WrappedHttpResponse {
response: Response
}
impl Read for WrappedHttpResponse {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.response.read(buf)
}
}
impl HttpResponse for WrappedHttpResponse {
fn headers(&self) -> &Headers {
&self.response.headers
}
fn status(&self) -> StatusCode {
self.response.status
}
fn status_raw(&self) -> &RawStatus {
self.response.status_raw()
}
}
pub trait HttpRequestFactory {
type R: HttpRequest;
fn create(&self, url: Url, method: Method) -> Result<Self::R, LoadError>;
}
struct NetworkHttpRequestFactory;
impl HttpRequestFactory for NetworkHttpRequestFactory {
type R = WrappedHttpRequest;
fn create(&self, url: Url, method: Method) -> Result<WrappedHttpRequest, LoadError> {
let mut context = SslContext::new(SslMethod::Sslv23).unwrap();
context.set_verify(SSL_VERIFY_PEER, None);
context.set_CA_file(&resources_dir_path().join("certs")).unwrap();
let connector = HttpsConnector::new(Openssl { context: Arc::new(context) });
let connection = Request::with_connector(method, url.clone(), &connector);
let ssl_err_string = "Some(OpenSslErrors([UnknownError { library: \"SSL routines\", \
function: \"SSL3_GET_SERVER_CERTIFICATE\", \
reason: \"certificate verify failed\" }]))";
let request = match connection {
Ok(req) => req,
Err(HttpError::Io(ref io_error)) if (
io_error.kind() == io::ErrorKind::Other &&
io_error.description() == "Error in OpenSSL" &&
// FIXME: This incredibly hacky. Make it more robust, and at least test it.
format!("{:?}", io_error.cause()) == ssl_err_string
) => {
return Err(
LoadError::Ssl(
url,
format!("ssl error {:?}: {:?} {:?}",
io_error.kind(),
io_error.description(),
io_error.cause())
)
)
},
Err(e) => {
return Err(LoadError::Connection(url, e.description().to_string()))
}
};
Ok(WrappedHttpRequest { request: request })
}
}
pub trait HttpRequest {
type R: HttpResponse + 'static;
fn headers_mut(&mut self) -> &mut Headers;
fn send(self, body: &Option<Vec<u8>>) -> Result<Self::R, LoadError>;
}
struct WrappedHttpRequest {
request: Request<Fresh>
}
impl HttpRequest for WrappedHttpRequest {
type R = WrappedHttpResponse;
fn headers_mut(&mut self) -> &mut Headers {
self.request.headers_mut()
}
fn send(self, body: &Option<Vec<u8>>) -> Result<WrappedHttpResponse, LoadError> {
let url = self.request.url.clone();
let mut request_writer = match self.request.start() {
Ok(streaming) => streaming,
Err(e) => return Err(LoadError::Connection(url, e.description().to_string()))
};
if let Some(ref data) = *body {
match request_writer.write_all(&data) {
Err(e) => {
return Err(LoadError::Connection(url, e.description().to_string()))
}
_ => {}
}
}
let response = match request_writer.send() {
Ok(w) => w,
Err(e) => return Err(LoadError::Connection(url, e.description().to_string()))
};
Ok(WrappedHttpResponse { response: response })
}
}
#[derive(Debug)]
pub enum LoadError {
UnsupportedScheme(Url),
Connection(Url, String),
Cors(Url, String),
Ssl(Url, String),
InvalidRedirect(Url, String),
Decoding(Url, String),
MaxRedirects(Url)
}
fn set_default_accept_encoding(headers: &mut Headers) {
if headers.has::<AcceptEncoding>() {
return
}
headers.set_raw("Accept-Encoding".to_owned(), vec![b"gzip, deflate".to_vec()]);
}
fn set_default_accept(headers: &mut Headers) {
if !headers.has::<Accept>() {
let accept = Accept(vec![
qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_string()), vec![])),
QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900u16)),
QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800u16)),
]);
headers.set(accept);
}
}
fn set_request_cookies(url: Url, headers: &mut Headers, resource_mgr_chan: &IpcSender<ControlMsg>) {
let (tx, rx) = ipc::channel().unwrap();
resource_mgr_chan.send(ControlMsg::GetCookiesForUrl(url, tx, CookieSource::HTTP)).unwrap();
if let Some(cookie_list) = rx.recv().unwrap() {
let mut v = Vec::new();
v.push(cookie_list.into_bytes());
headers.set_raw("Cookie".to_owned(), v);
}
}
fn set_cookies_from_response(url: Url, response: &HttpResponse, resource_mgr_chan: &IpcSender<ControlMsg>) {
if let Some(cookies) = response.headers().get_raw("set-cookie") {
for cookie in cookies.iter() {
if let Ok(cookies) = String::from_utf8(cookie.clone()) {
resource_mgr_chan.send(ControlMsg::SetCookiesForUrl(url.clone(),
cookies,
CookieSource::HTTP)).unwrap();
}
}
}
}
fn request_must_be_secured(url: &Url, resource_mgr_chan: &IpcSender<ControlMsg>) -> bool {
let (tx, rx) = ipc::channel().unwrap();
resource_mgr_chan.send(
ControlMsg::GetHostMustBeSecured(url.domain().unwrap().to_string(), tx)
).unwrap();
rx.recv().unwrap()
}
fn update_sts_list_from_response(url: &Url, response: &HttpResponse, resource_mgr_chan: &IpcSender<ControlMsg>) {
if url.scheme != "https" {
return;
}
if let Some(header) = response.headers().get::<StrictTransportSecurity>() {
if let Some(host) = url.domain() {
info!("adding host {} to the strict transport security list", host);
info!("- max-age {}", header.max_age);
let include_subdomains = if header.include_subdomains {
info!("- includeSubdomains");
IncludeSubdomains::Included
} else {
IncludeSubdomains::NotIncluded
};
let msg = ControlMsg::SetHSTSEntryForHost(
host.to_string(),
include_subdomains,
header.max_age
);
resource_mgr_chan.send(msg).unwrap();
}
}
}
pub struct StreamedResponse<R: HttpResponse> {
decoder: Decoder<R>,
pub metadata: Metadata
}
impl<R: HttpResponse> Read for StreamedResponse<R> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.decoder {
Decoder::Gzip(ref mut d) => d.read(buf),
Decoder::Deflate(ref mut d) => d.read(buf),
Decoder::Plain(ref mut d) => d.read(buf)
}
}
}
impl<R: HttpResponse> StreamedResponse<R> {
fn new(m: Metadata, d: Decoder<R>) -> StreamedResponse<R> {
StreamedResponse { metadata: m, decoder: d }
}
fn from_http_response(response: R, m: Metadata) -> Result<StreamedResponse<R>, LoadError> {
match response.content_encoding() {
Some(Encoding::Gzip) => {
let result = GzDecoder::new(response);
match result {
Ok(response_decoding) => {
return Ok(StreamedResponse::new(m, Decoder::Gzip(response_decoding)));
}
Err(err) => {
return Err(LoadError::Decoding(m.final_url, err.to_string()));
}
}
}
Some(Encoding::Deflate) => {
let response_decoding = DeflateDecoder::new(response);
return Ok(StreamedResponse::new(m, Decoder::Deflate(response_decoding)));
}
_ => {
return Ok(StreamedResponse::new(m, Decoder::Plain(response)));
}
}
}
}
enum Decoder<R: Read> {
Gzip(GzDecoder<R>),
Deflate(DeflateDecoder<R>),
Plain(R)
}
fn send_request_to_devtools(devtools_chan: Option<Sender<DevtoolsControlMsg>>,
request_id: String,
url: Url,
method: Method,
headers: Headers,
body: Option<Vec<u8>>) {
if let Some(ref chan) = devtools_chan {
let net_event = NetworkEvent::HttpRequest(url, method, headers, body);
let msg = ChromeToDevtoolsControlMsg::NetworkEvent(request_id, net_event);
chan.send(DevtoolsControlMsg::FromChrome(msg)).unwrap();
}
}
fn send_response_to_devtools(devtools_chan: Option<Sender<DevtoolsControlMsg>>,
request_id: String,
headers: Option<Headers>,
status: Option<RawStatus>) {
if let Some(ref chan) = devtools_chan {
let net_event_response = NetworkEvent::HttpResponse(headers, status, None);
let msg = ChromeToDevtoolsControlMsg::NetworkEvent(request_id, net_event_response);
chan.send(DevtoolsControlMsg::FromChrome(msg)).unwrap();
}
}
pub fn load<A>(load_data: LoadData,
resource_mgr_chan: IpcSender<ControlMsg>,
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
request_factory: &HttpRequestFactory<R=A>)
-> Result<StreamedResponse<A::R>, LoadError> where A: HttpRequest + 'static {
// FIXME: At the time of writing this FIXME, servo didn't have any central // FIXME: At the time of writing this FIXME, servo didn't have any central
// location for configuration. If you're reading this and such a // location for configuration. If you're reading this and such a
// repository DOES exist, please update this constant to use it. // repository DOES exist, please update this constant to use it.
@ -102,6 +444,7 @@ fn load(mut load_data: LoadData,
// specified in the hosts file. // specified in the hosts file.
let mut url = replace_hosts(&load_data.url); let mut url = replace_hosts(&load_data.url);
let mut redirected_to = HashSet::new(); let mut redirected_to = HashSet::new();
let mut method = load_data.method.clone();
// If the URL is a view-source scheme then the scheme data contains the // If the URL is a view-source scheme then the scheme data contains the
// real URL that should be used for which the source is to be viewed. // real URL that should be used for which the source is to be viewed.
@ -109,80 +452,30 @@ fn load(mut load_data: LoadData,
// the source rather than rendering the contents of the URL. // the source rather than rendering the contents of the URL.
let viewing_source = url.scheme == "view-source"; let viewing_source = url.scheme == "view-source";
if viewing_source { if viewing_source {
let inner_url = load_data.url.non_relative_scheme_data().unwrap(); url = inner_url(&load_data.url);
doc_url = Url::parse(inner_url).unwrap(); doc_url = url.clone();
url = replace_hosts(&doc_url);
match &*url.scheme {
"http" | "https" => {}
_ => {
let s = format!("The {} scheme with view-source is not supported", url.scheme);
send_error(url, s, start_chan);
return;
}
};
} }
// Loop to handle redirects. // Loop to handle redirects.
loop { loop {
iters = iters + 1; iters = iters + 1;
if &*url.scheme != "https" && request_must_be_secured(&hsts_list.lock().unwrap(), &url) { if &*url.scheme == "http" && request_must_be_secured(&url, &resource_mgr_chan) {
info!("{} is in the strict transport security list, requesting secure host", url); info!("{} is in the strict transport security list, requesting secure host", url);
url = secure_url(&url); url = secure_url(&url);
} }
if iters > max_redirects { if iters > max_redirects {
send_error(url, "too many redirects".to_string(), start_chan); return Err(LoadError::MaxRedirects(url));
return;
} }
match &*url.scheme { if &*url.scheme != "http" && &*url.scheme != "https" {
"http" | "https" => {} return Err(LoadError::UnsupportedScheme(url));
_ => {
let s = format!("{} request, but we don't support that scheme", url.scheme);
send_error(url, s, start_chan);
return;
}
} }
info!("requesting {}", url.serialize()); info!("requesting {}", url.serialize());
let ssl_err_string = "Some(OpenSslErrors([UnknownError { library: \"SSL routines\", \ // Ensure that the host header is set from the original url
function: \"SSL3_GET_SERVER_CERTIFICATE\", \
reason: \"certificate verify failed\" }]))";
let req = if opts::get().nossl {
Request::with_connector(load_data.method.clone(), url.clone(), &HttpConnector)
} else {
let mut context = SslContext::new(SslMethod::Sslv23).unwrap();
context.set_verify(SSL_VERIFY_PEER, None);
context.set_CA_file(&resources_dir_path().join("certs")).unwrap();
Request::with_connector(load_data.method.clone(), url.clone(),
&HttpsConnector::new(Openssl { context: Arc::new(context) }))
};
let mut req = match req {
Ok(req) => req,
Err(HttpError::Io(ref io_error)) if (
io_error.kind() == io::ErrorKind::Other &&
io_error.description() == "Error in OpenSSL" &&
// FIXME: This incredibly hacky. Make it more robust, and at least test it.
format!("{:?}", io_error.cause()) == ssl_err_string
) => {
let mut image = resources_dir_path();
image.push("badcert.html");
let load_data = LoadData::new(Url::from_file_path(&*image).unwrap(), None);
file_loader::factory(load_data, start_chan, classifier);
return;
},
Err(e) => {
println!("{:?}", e);
send_error(url, e.description().to_string(), start_chan);
return;
}
};
//Ensure that the host header is set from the original url
let host = Host { let host = Host {
hostname: doc_url.serialize_host().unwrap(), hostname: doc_url.serialize_host().unwrap(),
port: doc_url.port_or_default() port: doc_url.port_or_default()
@ -192,156 +485,90 @@ reason: \"certificate verify failed\" }]))";
// See https://bugzilla.mozilla.org/show_bug.cgi?id=401564 and // See https://bugzilla.mozilla.org/show_bug.cgi?id=401564 and
// https://bugzilla.mozilla.org/show_bug.cgi?id=216828 . // https://bugzilla.mozilla.org/show_bug.cgi?id=216828 .
// Only preserve ones which have been explicitly marked as such. // Only preserve ones which have been explicitly marked as such.
if iters == 1 { let mut request_headers = if iters == 1 {
let mut combined_headers = load_data.headers.clone(); let mut combined_headers = load_data.headers.clone();
combined_headers.extend(load_data.preserved_headers.iter()); combined_headers.extend(load_data.preserved_headers.iter());
*req.headers_mut() = combined_headers; combined_headers
} else { } else {
*req.headers_mut() = load_data.preserved_headers.clone(); load_data.preserved_headers.clone()
} };
req.headers_mut().set(host); request_headers.set(host);
if !req.headers().has::<Accept>() { set_default_accept(&mut request_headers);
let accept = Accept(vec![ set_default_accept_encoding(&mut request_headers);
qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])), set_request_cookies(doc_url.clone(), &mut request_headers, &resource_mgr_chan);
qitem(Mime(TopLevel::Application, SubLevel::Ext("xhtml+xml".to_string()), vec![])),
QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]), Quality(900u16)),
QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]), Quality(800u16)),
]);
req.headers_mut().set(accept);
}
let (tx, rx) = ipc::channel().unwrap(); let mut req = try!(request_factory.create(url.clone(), method.clone()));
resource_mgr_chan.send(ControlMsg::GetCookiesForUrl(doc_url.clone(), *req.headers_mut() = request_headers;
tx,
CookieSource::HTTP)).unwrap();
if let Some(cookie_list) = rx.recv().unwrap() {
let mut v = Vec::new();
v.push(cookie_list.into_bytes());
req.headers_mut().set_raw("Cookie".to_owned(), v);
}
if !req.headers().has::<AcceptEncoding>() {
req.headers_mut().set_raw("Accept-Encoding".to_owned(), vec![b"gzip, deflate".to_vec()]);
}
if log_enabled!(log::LogLevel::Info) { if log_enabled!(log::LogLevel::Info) {
info!("{}", load_data.method); info!("{}", method);
for header in req.headers().iter() { for header in req.headers_mut().iter() {
info!(" - {}", header); info!(" - {}", header);
} }
info!("{:?}", load_data.data); info!("{:?}", load_data.data);
} }
// Avoid automatically sending request body if a redirect has occurred. // Avoid automatically sending request body if a redirect has occurred.
let writer = match load_data.data { //
Some(ref data) if iters == 1 => { // TODO - This is the wrong behaviour according to the RFC. However, I'm not
req.headers_mut().set(ContentLength(data.len() as u64)); // sure how much "correctness" vs. real-world is important in this case.
let mut writer = match req.start() { //
Ok(w) => w, // https://tools.ietf.org/html/rfc7231#section-6.4
Err(e) => { let is_redirected_request = iters != 1;
send_error(url, e.description().to_string(), start_chan);
return;
}
};
match writer.write_all(&*data) {
Err(e) => {
send_error(url, e.description().to_string(), start_chan);
return;
}
_ => {}
};
writer
},
_ => {
match load_data.method {
Method::Get | Method::Head => (),
_ => req.headers_mut().set(ContentLength(0))
}
match req.start() {
Ok(w) => w,
Err(e) => {
send_error(url, e.description().to_string(), start_chan);
return;
}
}
}
};
// Send an HttpRequest message to devtools with a unique request_id
// TODO: Do this only if load_data has some pipeline_id, and send the pipeline_id in the message
let request_id = uuid::Uuid::new_v4().to_simple_string(); let request_id = uuid::Uuid::new_v4().to_simple_string();
if let Some(ref chan) = devtools_chan { let response = match load_data.data {
let net_event = NetworkEvent::HttpRequest(load_data.url.clone(), Some(ref data) if !is_redirected_request => {
load_data.method.clone(), req.headers_mut().set(ContentLength(data.len() as u64));
load_data.headers.clone(),
load_data.data.clone());
chan.send(DevtoolsControlMsg::FromChrome(
ChromeToDevtoolsControlMsg::NetworkEvent(request_id.clone(),
net_event))).unwrap();
}
let mut response = match writer.send() { // TODO: Do this only if load_data has some pipeline_id, and send the pipeline_id
Ok(r) => r, // in the message
Err(e) => { send_request_to_devtools(
send_error(url, e.description().to_string(), start_chan); devtools_chan.clone(), request_id.clone(), url.clone(),
return; method.clone(), load_data.headers.clone(),
load_data.data.clone()
);
try!(req.send(&load_data.data))
}
_ => {
if load_data.method != Method::Get && load_data.method != Method::Head {
req.headers_mut().set(ContentLength(0))
}
send_request_to_devtools(
devtools_chan.clone(), request_id.clone(), url.clone(),
method.clone(), load_data.headers.clone(),
None
);
try!(req.send(&None))
} }
}; };
// Dump headers, but only do the iteration if info!() is enabled. info!("got HTTP response {}, headers:", response.status());
info!("got HTTP response {}, headers:", response.status);
if log_enabled!(log::LogLevel::Info) { if log_enabled!(log::LogLevel::Info) {
for header in response.headers.iter() { for header in response.headers().iter() {
info!(" - {}", header); info!(" - {}", header);
} }
} }
if let Some(cookies) = response.headers.get_raw("set-cookie") { set_cookies_from_response(doc_url.clone(), &response, &resource_mgr_chan);
for cookie in cookies { update_sts_list_from_response(&url, &response, &resource_mgr_chan);
if let Ok(cookies) = String::from_utf8(cookie.clone()) {
resource_mgr_chan.send(ControlMsg::SetCookiesForUrl(doc_url.clone(),
cookies,
CookieSource::HTTP)).unwrap();
}
}
}
if url.scheme == "https" { // --- Loop if there's a redirect
if let Some(header) = response.headers.get::<StrictTransportSecurity>() { if response.status().class() == StatusClass::Redirection {
if let Some(host) = url.domain() { match response.headers().get::<Location>() {
info!("adding host {} to the strict transport security list", host);
info!("- max-age {}", header.max_age);
let include_subdomains = if header.include_subdomains {
info!("- includeSubdomains");
IncludeSubdomains::Included
} else {
IncludeSubdomains::NotIncluded
};
resource_mgr_chan.send(
ControlMsg::SetHSTSEntryForHost(
host.to_string(), include_subdomains, header.max_age
)
).unwrap();
}
}
}
if response.status.class() == StatusClass::Redirection {
match response.headers.get::<Location>() {
Some(&Location(ref new_url)) => { Some(&Location(ref new_url)) => {
// CORS (https://fetch.spec.whatwg.org/#http-fetch, status section, point 9, 10) // CORS (https://fetch.spec.whatwg.org/#http-fetch, status section, point 9, 10)
match load_data.cors { match load_data.cors {
Some(ref c) => { Some(ref c) => {
if c.preflight { if c.preflight {
// The preflight lied return Err(
send_error(url, LoadError::Cors(
"Preflight fetch inconsistent with main fetch".to_string(), url,
start_chan); "Preflight fetch inconsistent with main fetch".to_string()));
return;
} else { } else {
// XXXManishearth There are some CORS-related steps here, // XXXManishearth There are some CORS-related steps here,
// but they don't seem necessary until credentials are implemented // but they don't seem necessary until credentials are implemented
@ -349,28 +576,28 @@ reason: \"certificate verify failed\" }]))";
} }
_ => {} _ => {}
} }
let new_doc_url = match UrlParser::new().base_url(&doc_url).parse(&new_url) { let new_doc_url = match UrlParser::new().base_url(&doc_url).parse(&new_url) {
Ok(u) => u, Ok(u) => u,
Err(e) => { Err(e) => {
send_error(doc_url, e.to_string(), start_chan); return Err(LoadError::InvalidRedirect(doc_url, e.to_string()));
return;
} }
}; };
info!("redirecting to {}", new_doc_url); info!("redirecting to {}", new_doc_url);
url = replace_hosts(&new_doc_url); url = replace_hosts(&new_doc_url);
doc_url = new_doc_url; doc_url = new_doc_url;
// According to https://tools.ietf.org/html/rfc7231#section-6.4.2, // According to https://tools.ietf.org/html/rfc7231#section-6.4.2,
// historically UAs have rewritten POST->GET on 301 and 302 responses. // historically UAs have rewritten POST->GET on 301 and 302 responses.
if load_data.method == Method::Post && if method == Method::Post &&
(response.status == StatusCode::MovedPermanently || (response.status() == StatusCode::MovedPermanently ||
response.status == StatusCode::Found) { response.status() == StatusCode::Found) {
load_data.method = Method::Get; method = Method::Get;
} }
if redirected_to.contains(&doc_url) { if redirected_to.contains(&url) {
send_error(doc_url, "redirect loop".to_string(), start_chan); return Err(LoadError::InvalidRedirect(doc_url, "redirect loop".to_string()));
return;
} }
redirected_to.insert(doc_url.clone()); redirected_to.insert(doc_url.clone());
@ -380,11 +607,13 @@ reason: \"certificate verify failed\" }]))";
} }
} }
let mut adjusted_headers = response.headers.clone(); let mut adjusted_headers = response.headers().clone();
if viewing_source { if viewing_source {
adjusted_headers.set(ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec![]))); adjusted_headers.set(ContentType(Mime(TopLevel::Text, SubLevel::Plain, vec![])));
} }
let mut metadata: Metadata = Metadata::default(doc_url);
let mut metadata: Metadata = Metadata::default(doc_url.clone());
metadata.set_content_type(match adjusted_headers.get() { metadata.set_content_type(match adjusted_headers.get() {
Some(&ContentType(ref mime)) => Some(mime), Some(&ContentType(ref mime)) => Some(mime),
None => None None => None
@ -392,56 +621,16 @@ reason: \"certificate verify failed\" }]))";
metadata.headers = Some(adjusted_headers); metadata.headers = Some(adjusted_headers);
metadata.status = Some(response.status_raw().clone()); metadata.status = Some(response.status_raw().clone());
let mut encoding_str: Option<String> = None; // --- Tell devtools that we got a response
//FIXME: Implement Content-Encoding Header https://github.com/hyperium/hyper/issues/391
if let Some(encodings) = response.headers.get_raw("content-encoding") {
for encoding in encodings {
if let Ok(encodings) = String::from_utf8(encoding.clone()) {
if encodings == "gzip" || encodings == "deflate" {
encoding_str = Some(encodings);
break;
}
}
}
}
// Send an HttpResponse message to devtools with the corresponding request_id // Send an HttpResponse message to devtools with the corresponding request_id
// TODO: Send this message only if load_data has a pipeline_id that is not None // TODO: Send this message only if load_data has a pipeline_id that is not None
if let Some(ref chan) = devtools_chan { // TODO: Send this message even when the load fails?
let net_event_response = send_response_to_devtools(
NetworkEvent::HttpResponse(metadata.headers.clone(), devtools_chan, request_id,
metadata.status.clone(), metadata.headers.clone(), metadata.status.clone()
None); );
chan.send(DevtoolsControlMsg::FromChrome(
ChromeToDevtoolsControlMsg::NetworkEvent(request_id,
net_event_response))).unwrap();
}
match encoding_str { return StreamedResponse::from_http_response(response, metadata)
Some(encoding) => {
if encoding == "gzip" {
let result = GzDecoder::new(response);
match result {
Ok(mut response_decoding) => {
send_data(&mut response_decoding, start_chan, metadata, classifier);
}
Err(err) => {
send_error(metadata.final_url, err.to_string(), start_chan);
return;
}
}
} else if encoding == "deflate" {
let mut response_decoding = DeflateDecoder::new(response);
send_data(&mut response_decoding, start_chan, metadata, classifier);
}
},
None => {
send_data(&mut response, start_chan, metadata, classifier);
}
}
// We didn't get redirected.
break;
} }
} }

View file

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cmp::max;
pub struct MIMEClassifier { pub struct MIMEClassifier {
image_classifier: GroupedClassifier, image_classifier: GroupedClassifier,
@ -24,51 +23,34 @@ impl MIMEClassifier {
data: &[u8]) -> Option<(String, String)> { data: &[u8]) -> Option<(String, String)> {
match *supplied_type { match *supplied_type {
None => { None => self.sniff_unknown_type(!no_sniff, data),
return self.sniff_unknown_type(!no_sniff, data);
}
Some((ref media_type, ref media_subtype)) => { Some((ref media_type, ref media_subtype)) => {
match (&**media_type, &**media_subtype) { match (&**media_type, &**media_subtype) {
("unknown", "unknown") | ("application", "unknown") | ("*", "*") => { ("unknown", "unknown") |
return self.sniff_unknown_type(!no_sniff, data); ("application", "unknown") |
} ("*", "*") => self.sniff_unknown_type(!no_sniff, data),
_ => { _ => {
if no_sniff { if no_sniff {
return supplied_type.clone(); supplied_type.clone()
} } else if check_for_apache_bug {
if check_for_apache_bug { self.sniff_text_or_data(data)
return self.sniff_text_or_data(data); } else if MIMEClassifier::is_xml(media_type, media_subtype) {
} supplied_type.clone()
} else if MIMEClassifier::is_html(media_type, media_subtype) {
if MIMEClassifier::is_xml(media_type, media_subtype) { //Implied in section 7.3, but flow is not clear
return supplied_type.clone(); self.feeds_classifier.classify(data).or(supplied_type.clone())
} } else {
//Inplied in section 7.3, but flow is not clear match (&**media_type, &**media_subtype) {
if MIMEClassifier::is_html(media_type, media_subtype) { ("image", _) => self.image_classifier.classify(data),
return self.feeds_classifier ("audio", _) | ("video", _) | ("application", "ogg") =>
.classify(data) self.audio_video_classifer.classify(data),
.or(supplied_type.clone()); _ => None
} }.or(supplied_type.clone())
if &**media_type == "image" {
if let Some(tp) = self.image_classifier.classify(data) {
return Some(tp);
}
}
match (&**media_type, &**media_subtype) {
("audio", _) | ("video", _) | ("application", "ogg") => {
if let Some(tp) = self.audio_video_classifer.classify(data) {
return Some(tp);
}
}
_ => {}
} }
} }
} }
} }
} }
return supplied_type.clone();
} }
pub fn new() -> MIMEClassifier { pub fn new() -> MIMEClassifier {
@ -99,13 +81,15 @@ impl MIMEClassifier {
fn sniff_text_or_data(&self, data: &[u8]) -> Option<(String, String)> { fn sniff_text_or_data(&self, data: &[u8]) -> Option<(String, String)> {
self.binary_or_plaintext.classify(data) self.binary_or_plaintext.classify(data)
} }
fn is_xml(tp: &str, sub_tp: &str) -> bool { fn is_xml(tp: &str, sub_tp: &str) -> bool {
let suffix = &sub_tp[(max(sub_tp.len() as isize - "+xml".len() as isize, 0) as usize)..]; sub_tp.ends_with("+xml") ||
match (tp, sub_tp, suffix) { match (tp, sub_tp) {
(_, _, "+xml") | ("application", "xml",_) | ("text", "xml",_) => {true} ("application", "xml") | ("text", "xml") => true,
_ => {false} _ => false
} }
} }
fn is_html(tp: &str, sub_tp: &str) -> bool { fn is_html(tp: &str, sub_tp: &str) -> bool {
tp == "text" && sub_tp == "html" tp == "text" && sub_tp == "html"
} }
@ -141,13 +125,11 @@ impl <'a, T: Iterator<Item=&'a u8> + Clone> Matches for T {
// Side effects // Side effects
// moves the iterator when match is found // moves the iterator when match is found
fn matches(&mut self, matches: &[u8]) -> bool { fn matches(&mut self, matches: &[u8]) -> bool {
for (byte_a, byte_b) in self.clone().take(matches.len()).zip(matches) { let result = self.clone().zip(matches).all(|(s, m)| *s == *m);
if byte_a != byte_b { if result {
return false; self.nth(matches.len());
}
} }
self.nth(matches.len()); result
true
} }
} }
@ -155,36 +137,27 @@ struct ByteMatcher {
pattern: &'static [u8], pattern: &'static [u8],
mask: &'static [u8], mask: &'static [u8],
leading_ignore: &'static [u8], leading_ignore: &'static [u8],
content_type: (&'static str,&'static str) content_type: (&'static str, &'static str)
} }
impl ByteMatcher { impl ByteMatcher {
fn matches(&self, data: &[u8]) -> Option<usize> { fn matches(&self, data: &[u8]) -> Option<usize> {
if data.len() < self.pattern.len() { if data.len() < self.pattern.len() {
return None; None
} else if data == self.pattern {
Some(self.pattern.len())
} else {
data[..data.len() - self.pattern.len()].iter()
.position(|x| !self.leading_ignore.contains(x))
.and_then(|start|
if data[start..].iter()
.zip(self.pattern.iter()).zip(self.mask.iter())
.all(|((&data, &pattern), &mask)| (data & mask) == (pattern & mask)) {
Some(start + self.pattern.len())
} else {
None
})
} }
//TODO replace with iterators if I ever figure them out...
let mut i: usize = 0;
let max_i = data.len()-self.pattern.len();
loop {
if !self.leading_ignore.iter().any(|x| *x == data[i]) {
break;
}
i = i + 1;
if i > max_i {
return None;
}
}
for j in 0..self.pattern.len() {
if (data[i] & self.mask[j]) != (self.pattern[j] & self.mask[j]) {
return None;
}
i = i + 1;
}
Some(i)
} }
} }
@ -202,14 +175,13 @@ struct TagTerminatedByteMatcher {
impl MIMEChecker for TagTerminatedByteMatcher { impl MIMEChecker for TagTerminatedByteMatcher {
fn classify(&self, data: &[u8]) -> Option<(String, String)> { fn classify(&self, data: &[u8]) -> Option<(String, String)> {
let pattern = self.matcher.matches(data); self.matcher.matches(data).and_then(|j|
let pattern_matches = pattern.map(|j| j < data.len() && (data[j] == b' ' || data[j] == b'>')); if j < data.len() && (data[j] == b' ' || data[j] == b'>') {
if pattern_matches.unwrap_or(false) { Some((self.matcher.content_type.0.to_owned(),
Some((self.matcher.content_type.0.to_owned(), self.matcher.content_type.1.to_owned()))
self.matcher.content_type.1.to_owned())) } else {
} else { None
None })
}
} }
} }
pub struct Mp4Matcher; pub struct Mp4Matcher;
@ -219,48 +191,21 @@ impl Mp4Matcher {
if data.len() < 12 { if data.len() < 12 {
return false; return false;
} }
let box_size = ((data[0] as u32) << 3 | (data[1] as u32) << 2 | let box_size = ((data[0] as u32) << 3 | (data[1] as u32) << 2 |
(data[2] as u32) << 1 | (data[3] as u32)) as usize; (data[2] as u32) << 1 | (data[3] as u32)) as usize;
if (data.len() < box_size) || (box_size % 4 != 0) { if (data.len() < box_size) || (box_size % 4 != 0) {
return false; return false;
} }
//TODO replace with iterators
let ftyp = [0x66, 0x74, 0x79, 0x70]; let ftyp = [0x66, 0x74, 0x79, 0x70];
let mp4 = [0x6D, 0x70, 0x34]; if !data[4..].starts_with(&ftyp) {
return false;
for i in 4..8 {
if data[i] != ftyp[i - 4] {
return false;
}
}
let mut all_match = true;
for i in 8..11 {
if data[i] != mp4[i - 8] {
all_match = false;
break;
}
}
if all_match {
return true;
} }
let mut bytes_read: usize = 16; let mp4 = [0x6D, 0x70, 0x34];
data[8..].starts_with(&mp4) ||
while bytes_read < box_size { data[16..box_size].chunks(4).any(|chunk| chunk.starts_with(&mp4))
all_match = true;
for i in 0..3 {
if mp4[i] != data[i + bytes_read] {
all_match = false;
break;
}
}
if all_match {
return true;
}
bytes_read = bytes_read + 4;
}
false
} }
} }
@ -278,27 +223,24 @@ struct BinaryOrPlaintextClassifier;
impl BinaryOrPlaintextClassifier { impl BinaryOrPlaintextClassifier {
fn classify_impl(&self, data: &[u8]) -> (&'static str, &'static str) { fn classify_impl(&self, data: &[u8]) -> (&'static str, &'static str) {
if (data.len() >= 2 && if data == &[0xFFu8, 0xFEu8] ||
((data[0] == 0xFFu8 && data[1] == 0xFEu8) || data == &[0xFEu8, 0xFFu8] ||
(data[0] == 0xFEu8 && data[1] == 0xFFu8))) || data.starts_with(&[0xEFu8, 0xBBu8, 0xBFu8])
(data.len() >= 3 && data[0] == 0xEFu8 && data[1] == 0xBBu8 && data[2] == 0xBFu8)
{ {
("text", "plain") ("text", "plain")
} } else if data.iter().any(|&x| x <= 0x08u8 ||
else if data.len() >= 1 && data.iter().any(|&x| x <= 0x08u8 || x == 0x0Bu8 ||
x == 0x0Bu8 || (x >= 0x0Eu8 && x <= 0x1Au8) ||
(x >= 0x0Eu8 && x <= 0x1Au8) || (x >= 0x1Cu8 && x <= 0x1Fu8)) {
(x >= 0x1Cu8 && x <= 0x1Fu8)) {
("application", "octet-stream") ("application", "octet-stream")
} } else {
else {
("text", "plain") ("text", "plain")
} }
} }
} }
impl MIMEChecker for BinaryOrPlaintextClassifier { impl MIMEChecker for BinaryOrPlaintextClassifier {
fn classify(&self, data: &[u8]) -> Option<(String, String)> { fn classify(&self, data: &[u8]) -> Option<(String, String)> {
return as_string_option(Some(self.classify_impl(data))); as_string_option(Some(self.classify_impl(data)))
} }
} }
struct GroupedClassifier { struct GroupedClassifier {
@ -358,7 +300,6 @@ impl GroupedClassifier {
box ByteMatcher::application_pdf() box ByteMatcher::application_pdf()
] ]
} }
} }
fn plaintext_classifier() -> GroupedClassifier { fn plaintext_classifier() -> GroupedClassifier {
GroupedClassifier { GroupedClassifier {
@ -403,68 +344,95 @@ impl MIMEChecker for GroupedClassifier {
} }
} }
enum Match {
Start,
DidNotMatch,
StartAndEnd
}
impl Match {
fn chain<F: FnOnce() -> Match>(self, f: F) -> Match {
if let Match::DidNotMatch = self {
return f();
}
self
}
}
fn eats_until<'a, T>(matcher: &mut T, start: &[u8], end: &[u8]) -> Match
where T: Iterator<Item=&'a u8> + Clone {
if !matcher.matches(start) {
Match::DidNotMatch
} else if end.len() == 1 {
if matcher.any(|&x| x == end[0]) {
Match::StartAndEnd
} else {
Match::Start
}
} else {
while !matcher.matches(end) {
if matcher.next().is_none() {
return Match::Start;
}
}
Match::StartAndEnd
}
}
struct FeedsClassifier; struct FeedsClassifier;
impl FeedsClassifier { impl FeedsClassifier {
fn classify_impl(&self, data: &[u8]) -> Option<(&'static str, &'static str)> { fn classify_impl(&self, data: &[u8]) -> Option<(&'static str, &'static str)> {
let length = data.len();
let mut data_iterator = data.iter();
// acceptable byte sequences
let utf8_bom = &[0xEFu8, 0xBBu8, 0xBFu8];
// can not be feed unless length is > 3 // can not be feed unless length is > 3
if length < 3 { if data.len() < 3 {
return None; return None;
} }
// eat the first three bytes if they are equal to UTF-8 BOM let mut matcher = data.iter();
data_iterator.matches(utf8_bom);
// continuously search for next "<" until end of data_iterator // eat the first three acceptable byte sequences if they are equal to UTF-8 BOM
let utf8_bom = &[0xEFu8, 0xBBu8, 0xBFu8];
matcher.matches(utf8_bom);
// continuously search for next "<" until end of matcher
// TODO: need max_bytes to prevent inadvertently examining html document // TODO: need max_bytes to prevent inadvertently examining html document
// eg. an html page with a feed example // eg. an html page with a feed example
while !data_iterator.find(|&data_iterator| *data_iterator == b'<').is_none() { loop {
if data_iterator.matches(b"?") { if matcher.find(|&x| *x == b'<').is_none() {
// eat until ?> return None;
while !data_iterator.matches(b"?>") { }
if data_iterator.next().is_none() {
return None; match eats_until(&mut matcher, b"?", b"?>")
} .chain(|| eats_until(&mut matcher, b"!--", b"-->"))
} .chain(|| eats_until(&mut matcher, b"!", b">")) {
} else if data_iterator.matches(b"!--") { Match::StartAndEnd => continue,
// eat until --> Match::DidNotMatch => {},
while !data_iterator.matches(b"-->") { Match::Start => return None
if data_iterator.next().is_none() { }
return None;
} if matcher.matches(b"rss") {
}
} else if data_iterator.matches(b"!") {
data_iterator.find(|&data_iterator| *data_iterator == b'>');
} else if data_iterator.matches(b"rss") {
return Some(("application", "rss+xml")); return Some(("application", "rss+xml"));
} else if data_iterator.matches(b"feed") { }
if matcher.matches(b"feed") {
return Some(("application", "atom+xml")); return Some(("application", "atom+xml"));
} else if data_iterator.matches(b"rdf: RDF") { }
while !data_iterator.next().is_none() { if matcher.matches(b"rdf: RDF") {
if data_iterator.matches(b"http: //purl.org/rss/1.0/") { while matcher.next().is_some() {
while !data_iterator.next().is_none() { match eats_until(&mut matcher,
if data_iterator.matches(b"http: //www.w3.org/1999/02/22-rdf-syntax-ns#") { b"http: //purl.org/rss/1.0/",
return Some(("application", "rss+xml")); b"http: //www.w3.org/1999/02/22-rdf-syntax-ns#")
} .chain(|| eats_until(&mut matcher,
} b"http: //www.w3.org/1999/02/22-rdf-syntax-ns#",
} else if data_iterator.matches(b"http: //www.w3.org/1999/02/22-rdf-syntax-ns#") { b"http: //purl.org/rss/1.0/")) {
while !data_iterator.next().is_none() { Match::StartAndEnd => return Some(("application", "rss+xml")),
if data_iterator.matches(b"http: //purl.org/rss/1.0/") { Match::DidNotMatch => {},
return Some(("application", "rss+xml")); Match::Start => return None
}
}
} }
} }
return None;
} }
} }
None
} }
} }

View file

@ -29,7 +29,6 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::boxed::FnBox; use std::boxed::FnBox;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex;
use std::sync::mpsc::{channel, Sender}; use std::sync::mpsc::{channel, Sender};
pub enum ProgressSender { pub enum ProgressSender {
@ -161,23 +160,26 @@ impl ResourceChannelManager {
fn start(&mut self) { fn start(&mut self) {
loop { loop {
match self.from_client.recv().unwrap() { match self.from_client.recv().unwrap() {
ControlMsg::Load(load_data, consumer) => { ControlMsg::Load(load_data, consumer) => {
self.resource_manager.load(load_data, consumer) self.resource_manager.load(load_data, consumer)
} }
ControlMsg::SetCookiesForUrl(request, cookie_list, source) => { ControlMsg::SetCookiesForUrl(request, cookie_list, source) => {
self.resource_manager.set_cookies_for_url(request, cookie_list, source) self.resource_manager.set_cookies_for_url(request, cookie_list, source)
} }
ControlMsg::GetCookiesForUrl(url, consumer, source) => { ControlMsg::GetCookiesForUrl(url, consumer, source) => {
consumer.send(self.resource_manager.cookie_storage.cookies_for_url(&url, source)).unwrap(); consumer.send(self.resource_manager.cookie_storage.cookies_for_url(&url, source)).unwrap();
} }
ControlMsg::SetHSTSEntryForHost(host, include_subdomains, max_age) => { ControlMsg::SetHSTSEntryForHost(host, include_subdomains, max_age) => {
if let Some(entry) = HSTSEntry::new(host, include_subdomains, Some(max_age)) { if let Some(entry) = HSTSEntry::new(host, include_subdomains, Some(max_age)) {
self.resource_manager.add_hsts_entry(entry) self.resource_manager.add_hsts_entry(entry)
} }
} }
ControlMsg::Exit => { ControlMsg::GetHostMustBeSecured(host, consumer) => {
break consumer.send(self.resource_manager.is_host_sts(&*host)).unwrap();
} }
ControlMsg::Exit => {
break
}
} }
} }
} }
@ -189,7 +191,7 @@ pub struct ResourceManager {
resource_task: IpcSender<ControlMsg>, resource_task: IpcSender<ControlMsg>,
mime_classifier: Arc<MIMEClassifier>, mime_classifier: Arc<MIMEClassifier>,
devtools_chan: Option<Sender<DevtoolsControlMsg>>, devtools_chan: Option<Sender<DevtoolsControlMsg>>,
hsts_list: Arc<Mutex<HSTSList>> hsts_list: HSTSList
} }
impl ResourceManager { impl ResourceManager {
@ -203,7 +205,7 @@ impl ResourceManager {
resource_task: resource_task, resource_task: resource_task,
mime_classifier: Arc::new(MIMEClassifier::new()), mime_classifier: Arc::new(MIMEClassifier::new()),
devtools_chan: devtools_channel, devtools_chan: devtools_channel,
hsts_list: Arc::new(Mutex::new(hsts_list)) hsts_list: hsts_list
} }
} }
} }
@ -221,11 +223,11 @@ impl ResourceManager {
} }
pub fn add_hsts_entry(&mut self, entry: HSTSEntry) { pub fn add_hsts_entry(&mut self, entry: HSTSEntry) {
self.hsts_list.lock().unwrap().push(entry); self.hsts_list.push(entry);
} }
pub fn is_host_sts(&self, host: &str) -> bool { pub fn is_host_sts(&self, host: &str) -> bool {
self.hsts_list.lock().unwrap().is_host_secure(host) self.hsts_list.is_host_secure(host)
} }
fn load(&mut self, mut load_data: LoadData, consumer: LoadConsumer) { fn load(&mut self, mut load_data: LoadData, consumer: LoadConsumer) {
@ -241,7 +243,7 @@ impl ResourceManager {
let loader = match &*load_data.url.scheme { let loader = match &*load_data.url.scheme {
"file" => from_factory(file_loader::factory), "file" => from_factory(file_loader::factory),
"http" | "https" | "view-source" => "http" | "https" | "view-source" =>
http_loader::factory(self.resource_task.clone(), self.devtools_chan.clone(), self.hsts_list.clone()), http_loader::factory(self.resource_task.clone(), self.devtools_chan.clone()),
"data" => from_factory(data_loader::factory), "data" => from_factory(data_loader::factory),
"about" => from_factory(about_loader::factory), "about" => from_factory(about_loader::factory),
_ => { _ => {

View file

@ -161,6 +161,7 @@ pub enum ControlMsg {
GetCookiesForUrl(Url, IpcSender<Option<String>>, CookieSource), GetCookiesForUrl(Url, IpcSender<Option<String>>, CookieSource),
/// Store a domain's STS information /// Store a domain's STS information
SetHSTSEntryForHost(String, IncludeSubdomains, u64), SetHSTSEntryForHost(String, IncludeSubdomains, u64),
GetHostMustBeSecured(String, IpcSender<bool>),
Exit Exit
} }

View file

@ -17,6 +17,7 @@ pub fn expand_dom_struct(cx: &mut ExtCtxt, sp: Span, _: &MetaItem, anno: Annotat
item2.attrs.push(quote_attr!(cx, #[must_root])); item2.attrs.push(quote_attr!(cx, #[must_root]));
item2.attrs.push(quote_attr!(cx, #[privatize])); item2.attrs.push(quote_attr!(cx, #[privatize]));
item2.attrs.push(quote_attr!(cx, #[derive(JSTraceable)])); item2.attrs.push(quote_attr!(cx, #[derive(JSTraceable)]));
item2.attrs.push(quote_attr!(cx, #[derive(HeapSizeOf)]));
// The following attributes are only for internal usage // The following attributes are only for internal usage
item2.attrs.push(quote_attr!(cx, #[_generate_reflector])); item2.attrs.push(quote_attr!(cx, #[_generate_reflector]));

View file

@ -17,14 +17,14 @@ use syntax::ptr::P;
/// Try not to use this for types defined in crates you own, use match_lang_ty instead (for lint passes) /// Try not to use this for types defined in crates you own, use match_lang_ty instead (for lint passes)
pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> { pub fn match_ty_unwrap<'a>(ty: &'a Ty, segments: &[&str]) -> Option<&'a [P<Ty>]> {
match ty.node { match ty.node {
TyPath(_, Path {segments: ref seg, ..}) => { TyPath(_, Path { segments: ref seg, .. }) => {
// So ast::Path isn't the full path, just the tokens that were provided. // So ast::Path isn't the full path, just the tokens that were provided.
// I could muck around with the maps and find the full path // I could muck around with the maps and find the full path
// however the more efficient way is to simply reverse the iterators and zip them // however the more efficient way is to simply reverse the iterators and zip them
// which will compare them in reverse until one of them runs out of segments // which will compare them in reverse until one of them runs out of segments
if seg.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) { if seg.iter().rev().zip(segments.iter().rev()).all(|(a, b)| a.identifier.name.as_str() == *b) {
match seg.last() { match seg.last() {
Some(&PathSegment {parameters: AngleBracketedParameters(ref a), ..}) => { Some(&PathSegment { parameters: AngleBracketedParameters(ref a), .. }) => {
Some(&a.types) Some(&a.types)
} }
_ => None _ => None

View file

@ -13,9 +13,9 @@ extern crate ipc_channel;
extern crate libc; extern crate libc;
#[macro_use] #[macro_use]
extern crate profile_traits; extern crate profile_traits;
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
extern crate regex; extern crate regex;
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
extern crate task_info; extern crate task_info;
extern crate time as std_time; extern crate time as std_time;
extern crate util; extern crate util;

View file

@ -368,7 +368,7 @@ mod system_reporter {
use std::mem::size_of; use std::mem::size_of;
use std::ptr::null_mut; use std::ptr::null_mut;
use super::{JEMALLOC_HEAP_ALLOCATED_STR, SYSTEM_HEAP_ALLOCATED_STR}; use super::{JEMALLOC_HEAP_ALLOCATED_STR, SYSTEM_HEAP_ALLOCATED_STR};
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
use task_info::task_basic_info::{virtual_size, resident_size}; use task_info::task_basic_info::{virtual_size, resident_size};
/// Collects global measurements from the OS and heap allocators. /// Collects global measurements from the OS and heap allocators.
@ -418,12 +418,12 @@ mod system_reporter {
request.reports_channel.send(reports); request.reports_channel.send(reports);
} }
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
extern { extern {
fn mallinfo() -> struct_mallinfo; fn mallinfo() -> struct_mallinfo;
} }
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
#[repr(C)] #[repr(C)]
pub struct struct_mallinfo { pub struct struct_mallinfo {
arena: c_int, arena: c_int,
@ -438,7 +438,7 @@ mod system_reporter {
keepcost: c_int, keepcost: c_int,
} }
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
fn get_system_heap_allocated() -> Option<usize> { fn get_system_heap_allocated() -> Option<usize> {
let info: struct_mallinfo = unsafe { mallinfo() }; let info: struct_mallinfo = unsafe { mallinfo() };
@ -457,7 +457,7 @@ mod system_reporter {
} }
} }
#[cfg(not(target_os="linux"))] #[cfg(not(target_os = "linux"))]
fn get_system_heap_allocated() -> Option<usize> { fn get_system_heap_allocated() -> Option<usize> {
None None
} }
@ -507,14 +507,14 @@ mod system_reporter {
($e:expr) => (match $e { Some(e) => e, None => return None }) ($e:expr) => (match $e { Some(e) => e, None => return None })
); );
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
fn page_size() -> usize { fn page_size() -> usize {
unsafe { unsafe {
::libc::sysconf(::libc::_SC_PAGESIZE) as usize ::libc::sysconf(::libc::_SC_PAGESIZE) as usize
} }
} }
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
fn get_proc_self_statm_field(field: usize) -> Option<usize> { fn get_proc_self_statm_field(field: usize) -> Option<usize> {
use std::fs::File; use std::fs::File;
use std::io::Read; use std::io::Read;
@ -527,37 +527,37 @@ mod system_reporter {
Some(npages * page_size()) Some(npages * page_size())
} }
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
fn get_vsize() -> Option<usize> { fn get_vsize() -> Option<usize> {
get_proc_self_statm_field(0) get_proc_self_statm_field(0)
} }
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
fn get_resident() -> Option<usize> { fn get_resident() -> Option<usize> {
get_proc_self_statm_field(1) get_proc_self_statm_field(1)
} }
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
fn get_vsize() -> Option<usize> { fn get_vsize() -> Option<usize> {
virtual_size() virtual_size()
} }
#[cfg(target_os="macos")] #[cfg(target_os = "macos")]
fn get_resident() -> Option<usize> { fn get_resident() -> Option<usize> {
resident_size() resident_size()
} }
#[cfg(not(any(target_os="linux", target_os = "macos")))] #[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn get_vsize() -> Option<usize> { fn get_vsize() -> Option<usize> {
None None
} }
#[cfg(not(any(target_os="linux", target_os = "macos")))] #[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn get_resident() -> Option<usize> { fn get_resident() -> Option<usize> {
None None
} }
#[cfg(target_os="linux")] #[cfg(target_os = "linux")]
fn get_resident_segments() -> Vec<(String, usize)> { fn get_resident_segments() -> Vec<(String, usize)> {
use regex::Regex; use regex::Regex;
use std::collections::HashMap; use std::collections::HashMap;
@ -658,7 +658,7 @@ mod system_reporter {
segs segs
} }
#[cfg(not(target_os="linux"))] #[cfg(not(target_os = "linux"))]
fn get_resident_segments() -> Vec<(String, usize)> { fn get_resident_segments() -> Vec<(String, usize)> {
vec![] vec![]
} }

View file

@ -55,6 +55,10 @@ features = ["query_encoding", "serde_serialization"]
[dependencies.offscreen_gl_context] [dependencies.offscreen_gl_context]
git = "https://github.com/ecoal95/rust-offscreen-rendering-context" git = "https://github.com/ecoal95/rust-offscreen-rendering-context"
[dependencies.angle]
git = "https://github.com/ecoal95/angle"
branch = "servo"
[dependencies.cssparser] [dependencies.cssparser]
version = "0.3" version = "0.3"
features = [ "serde-serialization" ] features = [ "serde-serialization" ]

View file

@ -13,9 +13,7 @@ use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::jsstring_to_str; use dom::bindings::conversions::jsstring_to_str;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::document::DocumentHelpers; use dom::node::Node;
use dom::node::{Node, NodeHelpers};
use dom::window::{WindowHelpers, ScriptHelpers};
use ipc_channel::ipc::IpcSender; use ipc_channel::ipc::IpcSender;
use js::jsapi::{ObjectClassName, RootedObject, RootedValue}; use js::jsapi::{ObjectClassName, RootedObject, RootedValue};
use js::jsval::UndefinedValue; use js::jsval::UndefinedValue;

View file

@ -4,8 +4,8 @@
use dom::bindings::codegen::Bindings::EventBinding::EventMethods; use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast}; use dom::bindings::codegen::InheritTypes::{EventCast, EventTargetCast};
use dom::element::{Element, ActivationElementHelpers}; use dom::element::Element;
use dom::event::{Event, EventHelpers, EventBubbles, EventCancelable}; use dom::event::{Event, EventBubbles, EventCancelable};
use dom::eventtarget::EventTarget; use dom::eventtarget::EventTarget;
use dom::mouseevent::MouseEvent; use dom::mouseevent::MouseEvent;
use dom::node::window_from_node; use dom::node::window_from_node;

View file

@ -9,7 +9,7 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap}; use dom::bindings::js::{JS, MutNullableHeap};
use dom::bindings::js::{Root, RootedReference, LayoutJS}; use dom::bindings::js::{Root, RootedReference, LayoutJS};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers}; use dom::element::Element;
use dom::virtualmethods::vtable_for; use dom::virtualmethods::vtable_for;
use dom::window::Window; use dom::window::Window;
@ -111,7 +111,6 @@ impl Deref for AttrValue {
// https://dom.spec.whatwg.org/#interface-attr // https://dom.spec.whatwg.org/#interface-attr
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct Attr { pub struct Attr {
reflector_: Reflector, reflector_: Reflector,
local_name: Atom, local_name: Atom,
@ -163,19 +162,19 @@ impl Attr {
} }
} }
impl<'a> AttrMethods for &'a Attr { impl AttrMethods for Attr {
// https://dom.spec.whatwg.org/#dom-attr-localname // https://dom.spec.whatwg.org/#dom-attr-localname
fn LocalName(self) -> DOMString { fn LocalName(&self) -> DOMString {
(**self.local_name()).to_owned() (**self.local_name()).to_owned()
} }
// https://dom.spec.whatwg.org/#dom-attr-value // https://dom.spec.whatwg.org/#dom-attr-value
fn Value(self) -> DOMString { fn Value(&self) -> DOMString {
(**self.value()).to_owned() (**self.value()).to_owned()
} }
// https://dom.spec.whatwg.org/#dom-attr-value // https://dom.spec.whatwg.org/#dom-attr-value
fn SetValue(self, value: DOMString) { fn SetValue(&self, value: DOMString) {
match self.owner() { match self.owner() {
None => *self.value.borrow_mut() = AttrValue::String(value), None => *self.value.borrow_mut() = AttrValue::String(value),
Some(owner) => { Some(owner) => {
@ -186,32 +185,32 @@ impl<'a> AttrMethods for &'a Attr {
} }
// https://dom.spec.whatwg.org/#dom-attr-textcontent // https://dom.spec.whatwg.org/#dom-attr-textcontent
fn TextContent(self) -> DOMString { fn TextContent(&self) -> DOMString {
self.Value() self.Value()
} }
// https://dom.spec.whatwg.org/#dom-attr-textcontent // https://dom.spec.whatwg.org/#dom-attr-textcontent
fn SetTextContent(self, value: DOMString) { fn SetTextContent(&self, value: DOMString) {
self.SetValue(value) self.SetValue(value)
} }
// https://dom.spec.whatwg.org/#dom-attr-nodevalue // https://dom.spec.whatwg.org/#dom-attr-nodevalue
fn NodeValue(self) -> DOMString { fn NodeValue(&self) -> DOMString {
self.Value() self.Value()
} }
// https://dom.spec.whatwg.org/#dom-attr-nodevalue // https://dom.spec.whatwg.org/#dom-attr-nodevalue
fn SetNodeValue(self, value: DOMString) { fn SetNodeValue(&self, value: DOMString) {
self.SetValue(value) self.SetValue(value)
} }
// https://dom.spec.whatwg.org/#dom-attr-name // https://dom.spec.whatwg.org/#dom-attr-name
fn Name(self) -> DOMString { fn Name(&self) -> DOMString {
(*self.name).to_owned() (*self.name).to_owned()
} }
// https://dom.spec.whatwg.org/#dom-attr-namespaceuri // https://dom.spec.whatwg.org/#dom-attr-namespaceuri
fn GetNamespaceURI(self) -> Option<DOMString> { fn GetNamespaceURI(&self) -> Option<DOMString> {
let Namespace(ref atom) = self.namespace; let Namespace(ref atom) = self.namespace;
match &**atom { match &**atom {
"" => None, "" => None,
@ -220,32 +219,24 @@ impl<'a> AttrMethods for &'a Attr {
} }
// https://dom.spec.whatwg.org/#dom-attr-prefix // https://dom.spec.whatwg.org/#dom-attr-prefix
fn GetPrefix(self) -> Option<DOMString> { fn GetPrefix(&self) -> Option<DOMString> {
self.prefix().as_ref().map(|p| (**p).to_owned()) self.prefix().as_ref().map(|p| (**p).to_owned())
} }
// https://dom.spec.whatwg.org/#dom-attr-ownerelement // https://dom.spec.whatwg.org/#dom-attr-ownerelement
fn GetOwnerElement(self) -> Option<Root<Element>> { fn GetOwnerElement(&self) -> Option<Root<Element>> {
self.owner() self.owner()
} }
// https://dom.spec.whatwg.org/#dom-attr-specified // https://dom.spec.whatwg.org/#dom-attr-specified
fn Specified(self) -> bool { fn Specified(&self) -> bool {
true // Always returns true true // Always returns true
} }
} }
pub trait AttrHelpers<'a> {
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<&Element>);
fn owner(self) -> Option<Root<Element>>;
fn summarize(self) -> AttrInfo;
}
impl<'a> AttrHelpers<'a> for &'a Attr { impl Attr {
fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element) { pub fn set_value(&self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
assert!(Some(owner) == self.owner().r()); assert!(Some(owner) == self.owner().r());
let node = NodeCast::from_ref(owner); let node = NodeCast::from_ref(owner);
@ -264,17 +255,17 @@ impl<'a> AttrHelpers<'a> for &'a Attr {
} }
} }
fn value(self) -> Ref<'a, AttrValue> { pub fn value(&self) -> Ref<AttrValue> {
self.value.borrow() self.value.borrow()
} }
fn local_name(self) -> &'a Atom { pub fn local_name(&self) -> &Atom {
&self.local_name &self.local_name
} }
/// Sets the owner element. Should be called after the attribute is added /// Sets the owner element. Should be called after the attribute is added
/// or removed from its older parent. /// or removed from its older parent.
fn set_owner(self, owner: Option<&Element>) { pub fn set_owner(&self, owner: Option<&Element>) {
let ref ns = self.namespace; let ref ns = self.namespace;
match (self.owner().r(), owner) { match (self.owner().r(), owner) {
(None, Some(new)) => { (None, Some(new)) => {
@ -290,11 +281,11 @@ impl<'a> AttrHelpers<'a> for &'a Attr {
self.owner.set(owner.map(JS::from_ref)) self.owner.set(owner.map(JS::from_ref))
} }
fn owner(self) -> Option<Root<Element>> { pub fn owner(&self) -> Option<Root<Element>> {
self.owner.get().map(Root::from_rooted) self.owner.get().map(Root::from_rooted)
} }
fn summarize(self) -> AttrInfo { pub fn summarize(&self) -> AttrInfo {
let Namespace(ref ns) = self.namespace; let Namespace(ref ns) = self.namespace;
AttrInfo { AttrInfo {
namespace: (**ns).to_owned(), namespace: (**ns).to_owned(),

View file

@ -339,7 +339,7 @@ class CGMethodCall(CGThing):
code = ( code = (
"if argc < %d {\n" "if argc < %d {\n"
" throw_type_error(cx, \"Not enough arguments to %s.\");\n" " throw_type_error(cx, \"Not enough arguments to %s.\");\n"
" return 0;\n" " return JSFalse;\n"
"}" % (requiredArgs, methodName)) "}" % (requiredArgs, methodName))
self.cgRoot.prepend( self.cgRoot.prepend(
CGWrapper(CGGeneric(code), pre="\n", post="\n")) CGWrapper(CGGeneric(code), pre="\n", post="\n"))
@ -512,11 +512,11 @@ class CGMethodCall(CGThing):
CGSwitch("argcount", CGSwitch("argcount",
argCountCases, argCountCases,
CGGeneric("throw_type_error(cx, \"Not enough arguments to %s.\");\n" CGGeneric("throw_type_error(cx, \"Not enough arguments to %s.\");\n"
"return 0;" % methodName))) "return JSFalse;" % methodName)))
# XXXjdm Avoid unreachable statement warnings # XXXjdm Avoid unreachable statement warnings
# overloadCGThings.append( # overloadCGThings.append(
# CGGeneric('panic!("We have an always-returning default case");\n' # CGGeneric('panic!("We have an always-returning default case");\n'
# 'return 0;')) # 'return JSFalse;'))
self.cgRoot = CGWrapper(CGList(overloadCGThings, "\n"), self.cgRoot = CGWrapper(CGList(overloadCGThings, "\n"),
pre="\n") pre="\n")
@ -888,7 +888,11 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if invalidEnumValueFatal: if invalidEnumValueFatal:
handleInvalidEnumValueCode = exceptionCode handleInvalidEnumValueCode = exceptionCode
else: else:
handleInvalidEnumValueCode = "return 1;" handleInvalidEnumValueCode = "return JSTrue;"
transmute = "mem::transmute(index)"
if isMember == 'Dictionary':
transmute = 'unsafe { ' + transmute + ' }'
template = ( template = (
"match find_enum_string_index(cx, ${val}, %(values)s) {\n" "match find_enum_string_index(cx, ${val}, %(values)s) {\n"
@ -896,10 +900,11 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
" Ok(None) => { %(handleInvalidEnumValueCode)s },\n" " Ok(None) => { %(handleInvalidEnumValueCode)s },\n"
" Ok(Some(index)) => {\n" " Ok(Some(index)) => {\n"
" //XXXjdm need some range checks up in here.\n" " //XXXjdm need some range checks up in here.\n"
" unsafe { mem::transmute(index) }\n" " %(transmute)s\n"
" },\n" " },\n"
"}" % {"values": enum + "Values::strings", "}" % {"values": enum + "Values::strings",
"exceptionCode": exceptionCode, "exceptionCode": exceptionCode,
"transmute": transmute,
"handleInvalidEnumValueCode": handleInvalidEnumValueCode}) "handleInvalidEnumValueCode": handleInvalidEnumValueCode})
if defaultValue is not None: if defaultValue is not None:
@ -1012,7 +1017,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
declType = CGGeneric(typeName) declType = CGGeneric(typeName)
template = ("match %s::new(cx, ${val}) {\n" template = ("match %s::new(cx, ${val}) {\n"
" Ok(dictionary) => dictionary,\n" " Ok(dictionary) => dictionary,\n"
" Err(_) => return 0,\n" " Err(_) => return JSFalse,\n"
"}" % typeName) "}" % typeName)
return handleOptional(template, declType, handleDefaultNull("%s::empty(cx)" % typeName)) return handleOptional(template, declType, handleDefaultNull("%s::empty(cx)" % typeName))
@ -1037,7 +1042,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
conversionBehavior = "()" conversionBehavior = "()"
if failureCode is None: if failureCode is None:
failureCode = 'return 0' failureCode = 'return JSFalse'
declType = CGGeneric(builtinNames[type.tag()]) declType = CGGeneric(builtinNames[type.tag()])
if type.nullable(): if type.nullable():
@ -1216,7 +1221,7 @@ class CGArgumentConverter(CGThing):
return self.converter.define() return self.converter.define()
def wrapForType(jsvalRef, result='result', successCode='return 1;', pre=''): def wrapForType(jsvalRef, result='result', successCode='return JSTrue;', pre=''):
""" """
Reflect a Rust value into JS. Reflect a Rust value into JS.
@ -1472,6 +1477,7 @@ class AttrDefiner(PropertyDefiner):
def __init__(self, descriptor, name, static): def __init__(self, descriptor, name, static):
PropertyDefiner.__init__(self, descriptor, name) PropertyDefiner.__init__(self, descriptor, name)
self.name = name self.name = name
self.descriptor = descriptor
self.regular = [ self.regular = [
m m
for m in descriptor.interface.members for m in descriptor.interface.members
@ -1488,14 +1494,14 @@ class AttrDefiner(PropertyDefiner):
def getter(attr): def getter(attr):
if self.static: if self.static:
accessor = 'get_' + attr.identifier.name accessor = 'get_' + self.descriptor.internalNameFor(attr.identifier.name)
jitinfo = "0 as *const JSJitInfo" jitinfo = "0 as *const JSJitInfo"
else: else:
if attr.hasLenientThis(): if attr.hasLenientThis():
accessor = "generic_lenient_getter" accessor = "generic_lenient_getter"
else: else:
accessor = "generic_getter" accessor = "generic_getter"
jitinfo = "&%s_getterinfo" % attr.identifier.name jitinfo = "&%s_getterinfo" % self.descriptor.internalNameFor(attr.identifier.name)
return ("JSNativeWrapper { op: Some(%(native)s), info: %(info)s }" return ("JSNativeWrapper { op: Some(%(native)s), info: %(info)s }"
% {"info": jitinfo, % {"info": jitinfo,
@ -1506,14 +1512,14 @@ class AttrDefiner(PropertyDefiner):
return "JSNativeWrapper { op: None, info: 0 as *const JSJitInfo }" return "JSNativeWrapper { op: None, info: 0 as *const JSJitInfo }"
if self.static: if self.static:
accessor = 'set_' + attr.identifier.name accessor = 'set_' + self.descriptor.internalNameFor(attr.identifier.name)
jitinfo = "0 as *const JSJitInfo" jitinfo = "0 as *const JSJitInfo"
else: else:
if attr.hasLenientThis(): if attr.hasLenientThis():
accessor = "generic_lenient_setter" accessor = "generic_lenient_setter"
else: else:
accessor = "generic_setter" accessor = "generic_setter"
jitinfo = "&%s_setterinfo" % attr.identifier.name jitinfo = "&%s_setterinfo" % self.descriptor.internalNameFor(attr.identifier.name)
return ("JSNativeWrapper { op: Some(%(native)s), info: %(info)s }" return ("JSNativeWrapper { op: Some(%(native)s), info: %(info)s }"
% {"info": jitinfo, % {"info": jitinfo,
@ -1620,19 +1626,11 @@ class CGImports(CGWrapper):
""" """
if ignored_warnings is None: if ignored_warnings is None:
ignored_warnings = [ ignored_warnings = [
# Allow unreachable_code because we use 'break' in a way that
# sometimes produces two 'break's in a row. See for example
# CallbackMember.getArgConversions.
'unreachable_code',
'non_camel_case_types', 'non_camel_case_types',
'non_upper_case_globals', 'non_upper_case_globals',
'unused_parens',
'unused_imports', 'unused_imports',
'unused_variables', 'unused_variables',
'unused_unsafe',
'unused_mut',
'unused_assignments', 'unused_assignments',
'dead_code',
] ]
def componentTypes(type): def componentTypes(type):
@ -2049,7 +2047,7 @@ class CGAbstractMethod(CGThing):
""" """
def __init__(self, descriptor, name, returnType, args, inline=False, def __init__(self, descriptor, name, returnType, args, inline=False,
alwaysInline=False, extern=False, pub=False, templateArgs=None, alwaysInline=False, extern=False, pub=False, templateArgs=None,
unsafe=True): unsafe=False):
CGThing.__init__(self) CGThing.__init__(self)
self.descriptor = descriptor self.descriptor = descriptor
self.name = name self.name = name
@ -2111,7 +2109,7 @@ class CGAbstractMethod(CGThing):
def CreateBindingJSObject(descriptor, parent=None): def CreateBindingJSObject(descriptor, parent=None):
create = "let mut raw = Box::into_raw(object);\nlet _rt = RootedTraceable::new(&*raw);\n" create = "let raw = Box::into_raw(object);\nlet _rt = RootedTraceable::new(&*raw);\n"
if descriptor.proxy: if descriptor.proxy:
assert not descriptor.isGlobal() assert not descriptor.isGlobal()
create += """ create += """
@ -2160,12 +2158,13 @@ class CGWrapMethod(CGAbstractMethod):
assert not descriptor.interface.isCallback() assert not descriptor.interface.isCallback()
if not descriptor.isGlobal(): if not descriptor.isGlobal():
args = [Argument('*mut JSContext', 'cx'), Argument('GlobalRef', 'scope'), args = [Argument('*mut JSContext', 'cx'), Argument('GlobalRef', 'scope'),
Argument("Box<%s>" % descriptor.concreteType, 'object', mutable=True)] Argument("Box<%s>" % descriptor.concreteType, 'object')]
else: else:
args = [Argument('*mut JSContext', 'cx'), args = [Argument('*mut JSContext', 'cx'),
Argument("Box<%s>" % descriptor.concreteType, 'object', mutable=True)] Argument("Box<%s>" % descriptor.concreteType, 'object')]
retval = 'Root<%s>' % descriptor.concreteType retval = 'Root<%s>' % descriptor.concreteType
CGAbstractMethod.__init__(self, descriptor, 'Wrap', retval, args, pub=True) CGAbstractMethod.__init__(self, descriptor, 'Wrap', retval, args,
pub=True, unsafe=True)
def definition_body(self): def definition_body(self):
if not self.descriptor.isGlobal(): if not self.descriptor.isGlobal():
@ -2309,6 +2308,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
def definition_body(self): def definition_body(self):
protoChain = self.descriptor.prototypeChain protoChain = self.descriptor.prototypeChain
if len(protoChain) == 1: if len(protoChain) == 1:
self.unsafe = True
getParentProto = "parent_proto.ptr = JS_GetObjectPrototype(cx, global)" getParentProto = "parent_proto.ptr = JS_GetObjectPrototype(cx, global)"
else: else:
parentProtoName = self.descriptor.prototypeChain[-2] parentProtoName = self.descriptor.prototypeChain[-2]
@ -2382,7 +2382,7 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
Argument('HandleObject', 'receiver'), Argument('HandleObject', 'receiver'),
Argument('MutableHandleObject', 'rval')] Argument('MutableHandleObject', 'rval')]
CGAbstractMethod.__init__(self, descriptor, name, CGAbstractMethod.__init__(self, descriptor, name,
'void', args, pub=pub) 'void', args, pub=pub, unsafe=True)
self.id = idPrefix + "ID::" + self.descriptor.name self.id = idPrefix + "ID::" + self.descriptor.name
def definition_body(self): def definition_body(self):
@ -2452,7 +2452,9 @@ class CGDefineProxyHandler(CGAbstractMethod):
""" """
def __init__(self, descriptor): def __init__(self, descriptor):
assert descriptor.proxy assert descriptor.proxy
CGAbstractMethod.__init__(self, descriptor, 'DefineProxyHandler', '*const libc::c_void', [], pub=True) CGAbstractMethod.__init__(self, descriptor, 'DefineProxyHandler',
'*const libc::c_void', [],
pub=True, unsafe=True)
def define(self): def define(self):
return CGAbstractMethod.define(self) return CGAbstractMethod.define(self)
@ -2778,7 +2780,7 @@ class CGSetterCall(CGPerSignatureCall):
def wrap_return_value(self): def wrap_return_value(self):
# We have no return value # We have no return value
return "\nreturn 1;" return "\nreturn JSTrue;"
def getArgc(self): def getArgc(self):
return "1" return "1"
@ -2835,7 +2837,10 @@ class CGSpecializedMethod(CGAbstractExternMethod):
@staticmethod @staticmethod
def makeNativeName(descriptor, method): def makeNativeName(descriptor, method):
name = method.identifier.name name = method.identifier.name
return MakeNativeName(descriptor.binaryNameFor(name)) nativeName = descriptor.binaryNameFor(name)
if nativeName == name:
nativeName = descriptor.internalNameFor(name)
return MakeNativeName(nativeName)
class CGStaticMethod(CGAbstractStaticBindingMethod): class CGStaticMethod(CGAbstractStaticBindingMethod):
@ -2850,7 +2855,7 @@ class CGStaticMethod(CGAbstractStaticBindingMethod):
def generate_code(self): def generate_code(self):
nativeName = CGSpecializedMethod.makeNativeName(self.descriptor, nativeName = CGSpecializedMethod.makeNativeName(self.descriptor,
self.method) self.method)
setupArgs = CGGeneric("let mut args = CallArgs::from_vp(vp, argc);\n") setupArgs = CGGeneric("let args = CallArgs::from_vp(vp, argc);\n")
call = CGMethodCall(["global.r()"], nativeName, True, self.descriptor, self.method) call = CGMethodCall(["global.r()"], nativeName, True, self.descriptor, self.method)
return CGList([setupArgs, call]) return CGList([setupArgs, call])
@ -2862,7 +2867,7 @@ class CGSpecializedGetter(CGAbstractExternMethod):
""" """
def __init__(self, descriptor, attr): def __init__(self, descriptor, attr):
self.attr = attr self.attr = attr
name = 'get_' + attr.identifier.name name = 'get_' + descriptor.internalNameFor(attr.identifier.name)
args = [Argument('*mut JSContext', 'cx'), args = [Argument('*mut JSContext', 'cx'),
Argument('HandleObject', '_obj'), Argument('HandleObject', '_obj'),
Argument('*const %s' % descriptor.concreteType, 'this'), Argument('*const %s' % descriptor.concreteType, 'this'),
@ -2880,7 +2885,10 @@ class CGSpecializedGetter(CGAbstractExternMethod):
@staticmethod @staticmethod
def makeNativeName(descriptor, attr): def makeNativeName(descriptor, attr):
name = attr.identifier.name name = attr.identifier.name
nativeName = MakeNativeName(descriptor.binaryNameFor(name)) nativeName = descriptor.binaryNameFor(name)
if nativeName == name:
nativeName = descriptor.internalNameFor(name)
nativeName = MakeNativeName(nativeName)
infallible = ('infallible' in infallible = ('infallible' in
descriptor.getExtendedAttributes(attr, getter=True)) descriptor.getExtendedAttributes(attr, getter=True))
if attr.type.nullable() or not infallible: if attr.type.nullable() or not infallible:
@ -2901,7 +2909,7 @@ class CGStaticGetter(CGAbstractStaticBindingMethod):
def generate_code(self): def generate_code(self):
nativeName = CGSpecializedGetter.makeNativeName(self.descriptor, nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
self.attr) self.attr)
setupArgs = CGGeneric("let mut args = CallArgs::from_vp(vp, argc);\n") setupArgs = CGGeneric("let args = CallArgs::from_vp(vp, argc);\n")
call = CGGetterCall(["global.r()"], self.attr.type, nativeName, self.descriptor, call = CGGetterCall(["global.r()"], self.attr.type, nativeName, self.descriptor,
self.attr) self.attr)
return CGList([setupArgs, call]) return CGList([setupArgs, call])
@ -2914,7 +2922,7 @@ class CGSpecializedSetter(CGAbstractExternMethod):
""" """
def __init__(self, descriptor, attr): def __init__(self, descriptor, attr):
self.attr = attr self.attr = attr
name = 'set_' + attr.identifier.name name = 'set_' + descriptor.internalNameFor(attr.identifier.name)
args = [Argument('*mut JSContext', 'cx'), args = [Argument('*mut JSContext', 'cx'),
Argument('HandleObject', 'obj'), Argument('HandleObject', 'obj'),
Argument('*const %s' % descriptor.concreteType, 'this'), Argument('*const %s' % descriptor.concreteType, 'this'),
@ -2931,7 +2939,10 @@ class CGSpecializedSetter(CGAbstractExternMethod):
@staticmethod @staticmethod
def makeNativeName(descriptor, attr): def makeNativeName(descriptor, attr):
name = attr.identifier.name name = attr.identifier.name
return "Set" + MakeNativeName(descriptor.binaryNameFor(name)) nativeName = descriptor.binaryNameFor(name)
if nativeName == name:
nativeName = descriptor.internalNameFor(name)
return "Set" + MakeNativeName(nativeName)
class CGStaticSetter(CGAbstractStaticBindingMethod): class CGStaticSetter(CGAbstractStaticBindingMethod):
@ -2948,9 +2959,9 @@ class CGStaticSetter(CGAbstractStaticBindingMethod):
self.attr) self.attr)
checkForArg = CGGeneric( checkForArg = CGGeneric(
"let args = CallArgs::from_vp(vp, argc);\n" "let args = CallArgs::from_vp(vp, argc);\n"
"if (argc == 0) {\n" "if argc == 0 {\n"
" throw_type_error(cx, \"Not enough arguments to %s setter.\");\n" " throw_type_error(cx, \"Not enough arguments to %s setter.\");\n"
" return 0;\n" " return JSFalse;\n"
"}" % self.attr.identifier.name) "}" % self.attr.identifier.name)
call = CGSetterCall(["global.r()"], self.attr.type, nativeName, self.descriptor, call = CGSetterCall(["global.r()"], self.attr.type, nativeName, self.descriptor,
self.attr) self.attr)
@ -3045,8 +3056,9 @@ class CGMemberJITInfo(CGThing):
def define(self): def define(self):
if self.member.isAttr(): if self.member.isAttr():
getterinfo = ("%s_getterinfo" % self.member.identifier.name) internalMemberName = self.descriptor.internalNameFor(self.member.identifier.name)
getter = ("get_%s" % self.member.identifier.name) getterinfo = ("%s_getterinfo" % internalMemberName)
getter = ("get_%s" % internalMemberName)
getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True) getterinfal = "infallible" in self.descriptor.getExtendedAttributes(self.member, getter=True)
movable = self.mayBeMovable() and getterinfal movable = self.mayBeMovable() and getterinfal
@ -3070,8 +3082,8 @@ class CGMemberJITInfo(CGThing):
slotIndex, slotIndex,
[self.member.type], None) [self.member.type], None)
if (not self.member.readonly or self.member.getExtendedAttribute("PutForwards")): if (not self.member.readonly or self.member.getExtendedAttribute("PutForwards")):
setterinfo = ("%s_setterinfo" % self.member.identifier.name) setterinfo = ("%s_setterinfo" % internalMemberName)
setter = ("set_%s" % self.member.identifier.name) setter = ("set_%s" % internalMemberName)
# Setters are always fallible, since they have to do a typed unwrap. # Setters are always fallible, since they have to do a typed unwrap.
result += self.defineJitInfo(setterinfo, setter, "Setter", result += self.defineJitInfo(setterinfo, setter, "Setter",
False, False, "AliasEverything", False, False, "AliasEverything",
@ -3966,7 +3978,23 @@ class CGProxyIndexedSetter(CGProxySpecialOperation):
CGProxySpecialOperation.__init__(self, descriptor, 'IndexedSetter') CGProxySpecialOperation.__init__(self, descriptor, 'IndexedSetter')
class CGProxyNamedGetter(CGProxySpecialOperation): class CGProxyNamedOperation(CGProxySpecialOperation):
"""
Class to generate a call to a named operation.
"""
def __init__(self, descriptor, name):
CGProxySpecialOperation.__init__(self, descriptor, name)
def define(self):
# Our first argument is the id we're getting.
argName = self.arguments[0].identifier.name
return ("let %s = jsid_to_str(cx, id);\n"
"let this = UnwrapProxy(proxy);\n"
"let this = &*this;\n" % argName +
CGProxySpecialOperation.define(self))
class CGProxyNamedGetter(CGProxyNamedOperation):
""" """
Class to generate a call to an named getter. If templateValues is not None Class to generate a call to an named getter. If templateValues is not None
the returned value will be wrapped with wrapForType using templateValues. the returned value will be wrapped with wrapForType using templateValues.
@ -3976,7 +4004,16 @@ class CGProxyNamedGetter(CGProxySpecialOperation):
CGProxySpecialOperation.__init__(self, descriptor, 'NamedGetter') CGProxySpecialOperation.__init__(self, descriptor, 'NamedGetter')
class CGProxyNamedSetter(CGProxySpecialOperation): class CGProxyNamedPresenceChecker(CGProxyNamedGetter):
"""
Class to generate a call that checks whether a named property exists.
For now, we just delegate to CGProxyNamedGetter
"""
def __init__(self, descriptor):
CGProxyNamedGetter.__init__(self, descriptor)
class CGProxyNamedSetter(CGProxyNamedOperation):
""" """
Class to generate a call to a named setter. Class to generate a call to a named setter.
""" """
@ -3984,7 +4021,7 @@ class CGProxyNamedSetter(CGProxySpecialOperation):
CGProxySpecialOperation.__init__(self, descriptor, 'NamedSetter') CGProxySpecialOperation.__init__(self, descriptor, 'NamedSetter')
class CGProxyNamedDeleter(CGProxySpecialOperation): class CGProxyNamedDeleter(CGProxyNamedOperation):
""" """
Class to generate a call to a named deleter. Class to generate a call to a named deleter.
""" """
@ -3996,7 +4033,8 @@ class CGProxyUnwrap(CGAbstractMethod):
def __init__(self, descriptor): def __init__(self, descriptor):
args = [Argument('HandleObject', 'obj')] args = [Argument('HandleObject', 'obj')]
CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy", CGAbstractMethod.__init__(self, descriptor, "UnwrapProxy",
'*const ' + descriptor.concreteType, args, alwaysInline=True) '*const ' + descriptor.concreteType, args,
alwaysInline=True, unsafe=True)
def definition_body(self): def definition_body(self):
return CGGeneric("""\ return CGGeneric("""\
@ -4057,9 +4095,6 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(CGAbstractExternMethod):
# properties that shadow prototype properties. # properties that shadow prototype properties.
namedGet = ("\n" + namedGet = ("\n" +
"if RUST_JSID_IS_STRING(id) != 0 && !has_property_on_prototype(cx, proxy, id) {\n" + "if RUST_JSID_IS_STRING(id) != 0 && !has_property_on_prototype(cx, proxy, id) {\n" +
" let name = jsid_to_str(cx, id);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = &*this;\n" +
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" + CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + "\n" +
"}\n") "}\n")
else: else:
@ -4121,9 +4156,6 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
if not self.descriptor.operations['NamedCreator'] is namedSetter: if not self.descriptor.operations['NamedCreator'] is namedSetter:
raise TypeError("Can't handle creator that's different from the setter") raise TypeError("Can't handle creator that's different from the setter")
set += ("if RUST_JSID_IS_STRING(id) != 0 {\n" + set += ("if RUST_JSID_IS_STRING(id) != 0 {\n" +
" let name = jsid_to_str(cx, id);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = &*this;\n" +
CGIndenter(CGProxyNamedSetter(self.descriptor)).define() + CGIndenter(CGProxyNamedSetter(self.descriptor)).define() +
" (*opresult).code_ = 0; /* SpecialCodes::OkCode */\n" + " (*opresult).code_ = 0; /* SpecialCodes::OkCode */\n" +
" return JSTrue;\n" + " return JSTrue;\n" +
@ -4132,9 +4164,6 @@ class CGDOMJSProxyHandler_defineProperty(CGAbstractExternMethod):
"}\n") "}\n")
else: else:
set += ("if RUST_JSID_IS_STRING(id) != 0 {\n" + set += ("if RUST_JSID_IS_STRING(id) != 0 {\n" +
" let name = jsid_to_str(cx, id);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = &*this;\n" +
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + CGIndenter(CGProxyNamedGetter(self.descriptor)).define() +
" if (found) {\n" " if (found) {\n"
# TODO(Issue 5876) # TODO(Issue 5876)
@ -4165,10 +4194,7 @@ class CGDOMJSProxyHandler_delete(CGAbstractExternMethod):
def getBody(self): def getBody(self):
set = "" set = ""
if self.descriptor.operations['NamedDeleter']: if self.descriptor.operations['NamedDeleter']:
set += ("let name = jsid_to_str(cx, id);\n" + set += CGProxyNamedDeleter(self.descriptor).define()
"let this = UnwrapProxy(proxy);\n" +
"let this = &*this;\n" +
"%s") % (CGProxyNamedDeleter(self.descriptor).define())
set += "return proxyhandler::delete(%s) as u8;" % ", ".join(a.name for a in self.args) set += "return proxyhandler::delete(%s) as u8;" % ", ".join(a.name for a in self.args)
return set return set
@ -4205,7 +4231,7 @@ class CGDOMJSProxyHandler_ownPropertyKeys(CGAbstractExternMethod):
for name in (*unwrapped_proxy).SupportedPropertyNames() { for name in (*unwrapped_proxy).SupportedPropertyNames() {
let cstring = CString::new(name).unwrap(); let cstring = CString::new(name).unwrap();
let jsstring = JS_InternString(cx, cstring.as_ptr()); let jsstring = JS_InternString(cx, cstring.as_ptr());
let mut rooted = RootedString::new(cx, jsstring); let rooted = RootedString::new(cx, jsstring);
let jsid = INTERNED_STRING_TO_JSID(cx, rooted.handle().get()); let jsid = INTERNED_STRING_TO_JSID(cx, rooted.handle().get());
let rooted_jsid = RootedId::new(cx, jsid); let rooted_jsid = RootedId::new(cx, jsid);
AppendToAutoIdVector(props, rooted_jsid.handle().get()); AppendToAutoIdVector(props, rooted_jsid.handle().get());
@ -4253,9 +4279,6 @@ class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod):
namedGetter = self.descriptor.operations['NamedGetter'] namedGetter = self.descriptor.operations['NamedGetter']
if namedGetter: if namedGetter:
named = ("if RUST_JSID_IS_STRING(id) != 0 && !has_property_on_prototype(cx, proxy, id) {\n" + named = ("if RUST_JSID_IS_STRING(id) != 0 && !has_property_on_prototype(cx, proxy, id) {\n" +
" let name = jsid_to_str(cx, id);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = &*this;\n" +
CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" + CGIndenter(CGProxyNamedGetter(self.descriptor)).define() + "\n" +
" *bp = found as u8;\n" " *bp = found as u8;\n"
" return JSTrue;\n" " return JSTrue;\n"
@ -4328,10 +4351,7 @@ if !expando.ptr.is_null() {
namedGetter = self.descriptor.operations['NamedGetter'] namedGetter = self.descriptor.operations['NamedGetter']
if namedGetter: if namedGetter:
getNamed = ("if (RUST_JSID_IS_STRING(id) != 0) {\n" + getNamed = ("if RUST_JSID_IS_STRING(id) != 0 {\n" +
" let name = jsid_to_str(cx, id);\n" +
" let this = UnwrapProxy(proxy);\n" +
" let this = &*this;\n" +
CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() + CGIndenter(CGProxyNamedGetter(self.descriptor, templateValues)).define() +
"}\n") "}\n")
else: else:
@ -4564,7 +4584,7 @@ class CGInterfaceTrait(CGThing):
return "".join(", %s: %s" % argument for argument in arguments) return "".join(", %s: %s" % argument for argument in arguments)
methods = [ methods = [
CGGeneric("fn %s(self%s) -> %s;\n" % (name, fmt(arguments), rettype)) CGGeneric("fn %s(&self%s) -> %s;\n" % (name, fmt(arguments), rettype))
for name, arguments, rettype in members() for name, arguments, rettype in members()
] ]
if methods: if methods:
@ -5499,7 +5519,7 @@ class CallbackMember(CGNativeMember):
conversion = ( conversion = (
CGIfWrapper(CGGeneric(conversion), CGIfWrapper(CGGeneric(conversion),
"%s.is_some()" % arg.identifier.name).define() + "%s.is_some()" % arg.identifier.name).define() +
" else if (argc == %d) {\n" " else if argc == %d {\n"
" // This is our current trailing argument; reduce argc\n" " // This is our current trailing argument; reduce argc\n"
" argc -= 1;\n" " argc -= 1;\n"
"} else {\n" "} else {\n"
@ -5532,6 +5552,8 @@ class CallbackMember(CGNativeMember):
"}\n") "}\n")
def getArgcDecl(self): def getArgcDecl(self):
if self.argCount <= 1:
return CGGeneric("let argc = %s;" % self.argCountStr)
return CGGeneric("let mut argc = %s;" % self.argCountStr) return CGGeneric("let mut argc = %s;" % self.argCountStr)
@staticmethod @staticmethod
@ -5773,12 +5795,17 @@ class GlobalGenRoots():
CGGeneric("use std::mem;\n\n")] CGGeneric("use std::mem;\n\n")]
for descriptor in descriptors: for descriptor in descriptors:
name = descriptor.name name = descriptor.name
protos = [CGGeneric('pub trait %s : Sized {}\n' % (name + 'Base'))] protos = [CGGeneric("""\
/// Types which are derived from `%(name)s` and can be freely converted
/// to `%(name)s`
pub trait %(name)sBase : Sized {}\n""" % {'name': name})]
for proto in descriptor.prototypeChain: for proto in descriptor.prototypeChain:
protos += [CGGeneric('impl %s for %s {}\n' % (proto + 'Base', protos += [CGGeneric('impl %s for %s {}\n' % (proto + 'Base',
descriptor.concreteType))] descriptor.concreteType))]
derived = [CGGeneric('pub trait %s : Sized { fn %s(&self) -> bool; }\n' % derived = [CGGeneric("""\
(name + 'Derived', 'is_' + name.lower()))] /// Types which `%(name)s` derives from
pub trait %(name)sDerived : Sized { fn %(method)s(&self) -> bool; }\n""" %
{'name': name, 'method': 'is_' + name.lower()})]
for protoName in descriptor.prototypeChain[1:-1]: for protoName in descriptor.prototypeChain[1:-1]:
protoDescriptor = config.getDescriptor(protoName) protoDescriptor = config.getDescriptor(protoName)
delegate = string.Template("""\ delegate = string.Template("""\
@ -5800,6 +5827,8 @@ impl ${selfName} for ${baseName} {
pub struct ${name}Cast; pub struct ${name}Cast;
impl ${name}Cast { impl ${name}Cast {
#[inline] #[inline]
/// Downcast an instance of a base class of `${name}` to an instance of
/// `${name}`, if it internally is an instance of `${name}`
pub fn to_ref<'a, T: ${toBound}+Reflectable>(base: &'a T) -> Option<&'a ${name}> { pub fn to_ref<'a, T: ${toBound}+Reflectable>(base: &'a T) -> Option<&'a ${name}> {
match base.${checkFn}() { match base.${checkFn}() {
true => Some(unsafe { mem::transmute(base) }), true => Some(unsafe { mem::transmute(base) }),
@ -5807,14 +5836,6 @@ impl ${name}Cast {
} }
} }
#[inline]
pub fn to_borrowed_ref<'a, 'b, T: ${toBound}+Reflectable>(base: &'a &'b T) -> Option<&'a &'b ${name}> {
match base.${checkFn}() {
true => Some(unsafe { mem::transmute(base) }),
false => None
}
}
#[inline] #[inline]
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn to_layout_js<T: ${toBound}+Reflectable>(base: &LayoutJS<T>) -> Option<LayoutJS<${name}>> { pub fn to_layout_js<T: ${toBound}+Reflectable>(base: &LayoutJS<T>) -> Option<LayoutJS<${name}>> {
@ -5835,15 +5856,11 @@ impl ${name}Cast {
} }
#[inline] #[inline]
/// Upcast an instance of a derived class of `${name}` to `${name}`
pub fn from_ref<'a, T: ${fromBound}+Reflectable>(derived: &'a T) -> &'a ${name} { pub fn from_ref<'a, T: ${fromBound}+Reflectable>(derived: &'a T) -> &'a ${name} {
unsafe { mem::transmute(derived) } unsafe { mem::transmute(derived) }
} }
#[inline]
pub fn from_borrowed_ref<'a, 'b, T: ${fromBound}+Reflectable>(derived: &'a &'b T) -> &'a &'b ${name} {
unsafe { mem::transmute(derived) }
}
#[inline] #[inline]
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn from_layout_js<T: ${fromBound}+Reflectable>(derived: &LayoutJS<T>) -> LayoutJS<${name}> { pub fn from_layout_js<T: ${fromBound}+Reflectable>(derived: &LayoutJS<T>) -> LayoutJS<${name}> {

View file

@ -263,6 +263,8 @@ class Descriptor(DescriptorProvider):
self._binaryNames.setdefault('__legacycaller', 'LegacyCall') self._binaryNames.setdefault('__legacycaller', 'LegacyCall')
self._binaryNames.setdefault('__stringifier', 'Stringifier') self._binaryNames.setdefault('__stringifier', 'Stringifier')
self._internalNames = desc.get('internalNames', {})
for member in self.interface.members: for member in self.interface.members:
if not member.isAttr() and not member.isMethod(): if not member.isAttr() and not member.isMethod():
continue continue
@ -272,6 +274,8 @@ class Descriptor(DescriptorProvider):
assert len(binaryName) == 1 assert len(binaryName) == 1
self._binaryNames.setdefault(member.identifier.name, self._binaryNames.setdefault(member.identifier.name,
binaryName[0]) binaryName[0])
self._internalNames.setdefault(member.identifier.name,
member.identifier.name.replace('-', '_'))
# Build the prototype chain. # Build the prototype chain.
self.prototypeChain = [] self.prototypeChain = []
@ -285,6 +289,9 @@ class Descriptor(DescriptorProvider):
def binaryNameFor(self, name): def binaryNameFor(self, name):
return self._binaryNames.get(name, name) return self._binaryNames.get(name, name)
def internalNameFor(self, name):
return self._internalNames.get(name, name)
def getExtendedAttributes(self, member, getter=False, setter=False): def getExtendedAttributes(self, member, getter=False, setter=False):
def maybeAppendInfallibleToAttrs(attrs, throws): def maybeAppendInfallibleToAttrs(attrs, throws):
if throws is None: if throws is None:

View file

@ -12,9 +12,8 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::conversions::native_from_reflector_jsmanaged; use dom::bindings::conversions::native_from_reflector_jsmanaged;
use dom::bindings::js::{JS, Root}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::document::DocumentHelpers; use dom::window::{self, ScriptHelpers};
use dom::window::{self, WindowHelpers, ScriptHelpers}; use dom::workerglobalscope::WorkerGlobalScope;
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers};
use script_task::{ScriptChan, ScriptPort, CommonScriptMsg, ScriptTask}; use script_task::{ScriptChan, ScriptPort, CommonScriptMsg, ScriptTask};
use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId}; use msg::constellation_msg::{ConstellationChan, PipelineId, WorkerId};

View file

@ -207,6 +207,7 @@ impl MutHeapJSVal {
/// `JS<T>`. /// `JS<T>`.
#[must_root] #[must_root]
#[derive(JSTraceable)] #[derive(JSTraceable)]
#[derive(HeapSizeOf)]
pub struct MutHeap<T: HeapGCValue + Copy> { pub struct MutHeap<T: HeapGCValue + Copy> {
val: Cell<T>, val: Cell<T>,
} }
@ -433,11 +434,6 @@ impl<T: Reflectable> Root<T> {
&**self &**self
} }
/// 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 /// Generate a new root from a JS<T> reference
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
pub fn from_rooted(js: JS<T>) -> Root<T> { pub fn from_rooted(js: JS<T>) -> Root<T> {

View file

@ -168,15 +168,13 @@ pub mod codegen {
pub mod PrototypeList { pub mod PrototypeList {
include!(concat!(env!("OUT_DIR"), "/PrototypeList.rs")); include!(concat!(env!("OUT_DIR"), "/PrototypeList.rs"));
} }
#[allow(unreachable_code, non_camel_case_types, non_upper_case_globals, unused_parens, #[allow(non_camel_case_types, non_upper_case_globals,
unused_imports, unused_variables, unused_unsafe, unused_mut, unused_assignments, unused_imports, unused_variables, unused_assignments)]
dead_code)]
pub mod RegisterBindings { pub mod RegisterBindings {
include!(concat!(env!("OUT_DIR"), "/RegisterBindings.rs")); include!(concat!(env!("OUT_DIR"), "/RegisterBindings.rs"));
} }
#[allow(unreachable_code, non_camel_case_types, non_upper_case_globals, unused_parens, #[allow(non_camel_case_types, non_upper_case_globals,
unused_imports, unused_variables, unused_unsafe, unused_mut, unused_assignments, unused_imports, unused_variables, unused_assignments)]
dead_code)]
pub mod UnionTypes { pub mod UnionTypes {
include!(concat!(env!("OUT_DIR"), "/UnionTypes.rs")); include!(concat!(env!("OUT_DIR"), "/UnionTypes.rs"));
} }

View file

@ -9,7 +9,7 @@ use num::Float;
use std::ops::Deref; use std::ops::Deref;
/// Encapsulates the IDL restricted float type. /// Encapsulates the IDL restricted float type.
#[derive(JSTraceable,Clone,Eq,PartialEq)] #[derive(JSTraceable, Clone, Eq, PartialEq)]
pub struct Finite<T: Float>(T); pub struct Finite<T: Float>(T);
unsafe impl<T: Float> Zeroable for Finite<T> {} unsafe impl<T: Float> Zeroable for Finite<T> {}

View file

@ -29,7 +29,7 @@
//! The `no_jsmanaged_fields!()` macro adds an empty implementation of `JSTraceable` to //! The `no_jsmanaged_fields!()` macro adds an empty implementation of `JSTraceable` to
//! a datatype. //! a datatype.
use dom::bindings::js::JS; use dom::bindings::js::{JS, Root};
use dom::bindings::refcounted::Trusted; use dom::bindings::refcounted::Trusted;
use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler}; use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler};
use script_task::ScriptChan; use script_task::ScriptChan;
@ -69,6 +69,7 @@ use std::collections::{HashMap, HashSet};
use std::ffi::CString; use std::ffi::CString;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::intrinsics::return_address; use std::intrinsics::return_address;
use std::iter::{FromIterator, IntoIterator};
use std::mem; use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::rc::Rc; use std::rc::Rc;
@ -511,6 +512,17 @@ impl<T: JSTraceable + Reflectable> DerefMut for RootedVec<T> {
} }
} }
impl<A: JSTraceable + Reflectable> FromIterator<Root<A>> for RootedVec<JS<A>> {
#[allow(moved_no_move)]
fn from_iter<T>(iterable: T) -> RootedVec<JS<A>> where T: IntoIterator<Item=Root<A>> {
let mut vec = RootedVec::new_with_destination_address(unsafe {
return_address() as *const libc::c_void
});
vec.extend(iterable.into_iter().map(|item| JS::from_rooted(&item)));
vec
}
}
/// SM Callback that traces the rooted traceables /// SM Callback that traces the rooted traceables
pub unsafe fn trace_traceables(tracer: *mut JSTracer) { pub unsafe fn trace_traceables(tracer: *mut JSTracer) {
ROOTED_TRACEABLES.with(|ref traceables| { ROOTED_TRACEABLES.with(|ref traceables| {

View file

@ -25,7 +25,6 @@ pub enum BlobTypeId {
// http://dev.w3.org/2006/webapi/FileAPI/#blob // http://dev.w3.org/2006/webapi/FileAPI/#blob
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct Blob { pub struct Blob {
reflector_: Reflector, reflector_: Reflector,
type_: BlobTypeId, type_: BlobTypeId,
@ -78,21 +77,15 @@ impl Blob {
}; };
Ok(Blob::new(global, bytes, &typeString.to_ascii_lowercase())) Ok(Blob::new(global, bytes, &typeString.to_ascii_lowercase()))
} }
}
pub trait BlobHelpers { pub fn read_out_buffer(&self, send: Sender<Vec<u8>>) {
fn read_out_buffer(self, send: Sender<Vec<u8>>);
}
impl<'a> BlobHelpers for &'a Blob {
fn read_out_buffer(self, send: Sender<Vec<u8>>) {
send.send(self.bytes.clone().unwrap_or(vec![])).unwrap(); send.send(self.bytes.clone().unwrap_or(vec![])).unwrap();
} }
} }
impl<'a> BlobMethods for &'a Blob { impl BlobMethods for Blob {
// https://dev.w3.org/2006/webapi/FileAPI/#dfn-size // https://dev.w3.org/2006/webapi/FileAPI/#dfn-size
fn Size(self) -> u64 { fn Size(&self) -> u64 {
match self.bytes { match self.bytes {
None => 0, None => 0,
Some(ref bytes) => bytes.len() as u64 Some(ref bytes) => bytes.len() as u64
@ -100,12 +93,12 @@ impl<'a> BlobMethods for &'a Blob {
} }
// https://dev.w3.org/2006/webapi/FileAPI/#dfn-type // https://dev.w3.org/2006/webapi/FileAPI/#dfn-type
fn Type(self) -> DOMString { fn Type(&self) -> DOMString {
self.typeString.clone() self.typeString.clone()
} }
// https://dev.w3.org/2006/webapi/FileAPI/#slice-method-algo // https://dev.w3.org/2006/webapi/FileAPI/#slice-method-algo
fn Slice(self, start: Option<i64>, end: Option<i64>, fn Slice(&self, start: Option<i64>, end: Option<i64>,
contentType: Option<DOMString>) -> Root<Blob> { contentType: Option<DOMString>) -> Root<Blob> {
let size: i64 = self.Size().to_i64().unwrap(); let size: i64 = self.Size().to_i64().unwrap();
let relativeStart: i64 = match start { let relativeStart: i64 = match start {
@ -153,12 +146,12 @@ impl<'a> BlobMethods for &'a Blob {
} }
// https://dev.w3.org/2006/webapi/FileAPI/#dfn-isClosed // https://dev.w3.org/2006/webapi/FileAPI/#dfn-isClosed
fn IsClosed(self) -> bool { fn IsClosed(&self) -> bool {
self.isClosed_.get() self.isClosed_.get()
} }
// https://dev.w3.org/2006/webapi/FileAPI/#dfn-close // https://dev.w3.org/2006/webapi/FileAPI/#dfn-close
fn Close(self) { fn Close(&self) {
// Step 1 // Step 1
if self.isClosed_.get() { if self.isClosed_.get() {
return; return;

View file

@ -8,10 +8,9 @@ use dom::bindings::js::{JS, Root};
use dom::bindings::proxyhandler::{get_property_descriptor, fill_property_descriptor}; use dom::bindings::proxyhandler::{get_property_descriptor, fill_property_descriptor};
use dom::bindings::utils::get_array_index_from_id; use dom::bindings::utils::get_array_index_from_id;
use dom::bindings::utils::{Reflectable, WindowProxyHandler}; use dom::bindings::utils::{Reflectable, WindowProxyHandler};
use dom::document::{Document, DocumentHelpers}; use dom::document::Document;
use dom::element::Element; use dom::element::Element;
use dom::window::Window; use dom::window::Window;
use dom::window::WindowHelpers;
use js::glue::{GetProxyPrivate}; use js::glue::{GetProxyPrivate};
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps}; use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};

View file

@ -16,7 +16,6 @@ use dom::canvasrenderingcontext2d::parse_color;
// https://html.spec.whatwg.org/multipage/#canvasgradient // https://html.spec.whatwg.org/multipage/#canvasgradient
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct CanvasGradient { pub struct CanvasGradient {
reflector_: Reflector, reflector_: Reflector,
style: CanvasGradientStyle, style: CanvasGradientStyle,
@ -44,9 +43,9 @@ impl CanvasGradient {
} }
} }
impl<'a> CanvasGradientMethods for &'a CanvasGradient { impl CanvasGradientMethods for CanvasGradient {
// https://html.spec.whatwg.org/multipage/#dom-canvasgradient-addcolorstop // https://html.spec.whatwg.org/multipage/#dom-canvasgradient-addcolorstop
fn AddColorStop(self, offset: Finite<f64>, color: String) -> ErrorResult { fn AddColorStop(&self, offset: Finite<f64>, color: String) -> ErrorResult {
if *offset < 0f64 || *offset > 1f64 { if *offset < 0f64 || *offset > 1f64 {
return Err(IndexSize); return Err(IndexSize);
} }

View file

@ -12,7 +12,6 @@ use euclid::size::Size2D;
// https://html.spec.whatwg.org/multipage/#canvaspattern // https://html.spec.whatwg.org/multipage/#canvaspattern
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct CanvasPattern { pub struct CanvasPattern {
reflector_: Reflector, reflector_: Reflector,
surface_data: Vec<u8>, surface_data: Vec<u8>,

View file

@ -17,11 +17,11 @@ use dom::bindings::num::Finite;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle};
use dom::canvaspattern::CanvasPattern; use dom::canvaspattern::CanvasPattern;
use dom::htmlcanvaselement::HTMLCanvasElement;
use dom::htmlcanvaselement::utils as canvas_utils; use dom::htmlcanvaselement::utils as canvas_utils;
use dom::htmlcanvaselement::{HTMLCanvasElement, HTMLCanvasElementHelpers}; use dom::htmlimageelement::HTMLImageElement;
use dom::htmlimageelement::{HTMLImageElement, HTMLImageElementHelpers}; use dom::imagedata::ImageData;
use dom::imagedata::{ImageData, ImageDataHelpers}; use dom::node::{window_from_node, NodeDamage};
use dom::node::{window_from_node, NodeHelpers, NodeDamage};
use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::Msg as ConstellationMsg;
use net_traits::image::base::PixelFormat; use net_traits::image::base::PixelFormat;
@ -61,7 +61,6 @@ pub enum CanvasFillOrStrokeStyle {
// https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d // https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct CanvasRenderingContext2D { pub struct CanvasRenderingContext2D {
reflector_: Reflector, reflector_: Reflector,
global: GlobalField, global: GlobalField,
@ -408,18 +407,11 @@ impl CanvasRenderingContext2D {
Some(Rect::new(Point2D::new(x as f32, y as f32), Size2D::new(w as f32, h as f32))) Some(Rect::new(Point2D::new(x as f32, y as f32), Size2D::new(w as f32, h as f32)))
} }
}
pub trait CanvasRenderingContext2DHelpers { pub fn get_renderer_id(&self) -> usize {
fn get_renderer_id(self) -> usize;
fn get_ipc_renderer(self) -> IpcSender<CanvasMsg>;
}
impl<'a> CanvasRenderingContext2DHelpers for &'a CanvasRenderingContext2D {
fn get_renderer_id(self) -> usize {
self.renderer_id self.renderer_id
} }
fn get_ipc_renderer(self) -> IpcSender<CanvasMsg> { pub fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
self.ipc_renderer.clone() self.ipc_renderer.clone()
} }
} }
@ -451,20 +443,20 @@ impl LayoutCanvasRenderingContext2DHelpers for LayoutJS<CanvasRenderingContext2D
// Restricted values are guarded in glue code. Therefore we need not add a guard. // Restricted values are guarded in glue code. Therefore we need not add a guard.
// //
// FIXME: this behavior should might be generated by some annotattions to idl. // FIXME: this behavior should might be generated by some annotattions to idl.
impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D { impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas // https://html.spec.whatwg.org/multipage/#dom-context-2d-canvas
fn Canvas(self) -> Root<HTMLCanvasElement> { fn Canvas(&self) -> Root<HTMLCanvasElement> {
self.canvas.root() self.canvas.root()
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-save // https://html.spec.whatwg.org/multipage/#dom-context-2d-save
fn Save(self) { fn Save(&self) {
self.saved_states.borrow_mut().push(self.state.borrow().clone()); self.saved_states.borrow_mut().push(self.state.borrow().clone());
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SaveContext)).unwrap(); self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SaveContext)).unwrap();
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-restore // https://html.spec.whatwg.org/multipage/#dom-context-2d-restore
fn Restore(self) { fn Restore(&self) {
let mut saved_states = self.saved_states.borrow_mut(); let mut saved_states = self.saved_states.borrow_mut();
if let Some(state) = saved_states.pop() { if let Some(state) = saved_states.pop() {
self.state.borrow_mut().clone_from(&state); self.state.borrow_mut().clone_from(&state);
@ -473,7 +465,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-scale // https://html.spec.whatwg.org/multipage/#dom-context-2d-scale
fn Scale(self, x: f64, y: f64) { fn Scale(&self, x: f64, y: f64) {
if !(x.is_finite() && y.is_finite()) { if !(x.is_finite() && y.is_finite()) {
return; return;
} }
@ -484,7 +476,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-rotate // https://html.spec.whatwg.org/multipage/#dom-context-2d-rotate
fn Rotate(self, angle: f64) { fn Rotate(&self, angle: f64) {
if angle == 0.0 || !angle.is_finite() { if angle == 0.0 || !angle.is_finite() {
return; return;
} }
@ -498,7 +490,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-translate // https://html.spec.whatwg.org/multipage/#dom-context-2d-translate
fn Translate(self, x: f64, y: f64) { fn Translate(&self, x: f64, y: f64) {
if !(x.is_finite() && y.is_finite()) { if !(x.is_finite() && y.is_finite()) {
return; return;
} }
@ -509,7 +501,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-transform // https://html.spec.whatwg.org/multipage/#dom-context-2d-transform
fn Transform(self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { fn Transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
if !(a.is_finite() && b.is_finite() && c.is_finite() && if !(a.is_finite() && b.is_finite() && c.is_finite() &&
d.is_finite() && e.is_finite() && f.is_finite()) { d.is_finite() && e.is_finite() && f.is_finite()) {
return; return;
@ -526,7 +518,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform // https://html.spec.whatwg.org/multipage/#dom-context-2d-settransform
fn SetTransform(self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { fn SetTransform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) {
if !(a.is_finite() && b.is_finite() && c.is_finite() && if !(a.is_finite() && b.is_finite() && c.is_finite() &&
d.is_finite() && e.is_finite() && f.is_finite()) { d.is_finite() && e.is_finite() && f.is_finite()) {
return; return;
@ -542,19 +534,19 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform // https://html.spec.whatwg.org/multipage/#dom-context-2d-resettransform
fn ResetTransform(self) { fn ResetTransform(&self) {
self.state.borrow_mut().transform = Matrix2D::identity(); self.state.borrow_mut().transform = Matrix2D::identity();
self.update_transform() self.update_transform()
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha
fn GlobalAlpha(self) -> f64 { fn GlobalAlpha(&self) -> f64 {
let state = self.state.borrow(); let state = self.state.borrow();
state.global_alpha state.global_alpha
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalalpha
fn SetGlobalAlpha(self, alpha: f64) { fn SetGlobalAlpha(&self, alpha: f64) {
if !alpha.is_finite() || alpha > 1.0 || alpha < 0.0 { if !alpha.is_finite() || alpha > 1.0 || alpha < 0.0 {
return; return;
} }
@ -566,7 +558,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation
fn GlobalCompositeOperation(self) -> DOMString { fn GlobalCompositeOperation(&self) -> DOMString {
let state = self.state.borrow(); let state = self.state.borrow();
match state.global_composition { match state.global_composition {
CompositionOrBlending::Composition(op) => op.to_str().to_owned(), CompositionOrBlending::Composition(op) => op.to_str().to_owned(),
@ -575,7 +567,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation // https://html.spec.whatwg.org/multipage/#dom-context-2d-globalcompositeoperation
fn SetGlobalCompositeOperation(self, op_str: DOMString) { fn SetGlobalCompositeOperation(&self, op_str: DOMString) {
if let Some(op) = CompositionOrBlending::from_str(&op_str) { if let Some(op) = CompositionOrBlending::from_str(&op_str) {
self.state.borrow_mut().global_composition = op; self.state.borrow_mut().global_composition = op;
self.ipc_renderer self.ipc_renderer
@ -585,7 +577,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect // https://html.spec.whatwg.org/multipage/#dom-context-2d-fillrect
fn FillRect(self, x: f64, y: f64, width: f64, height: f64) { fn FillRect(&self, x: f64, y: f64, width: f64, height: f64) {
if let Some(rect) = self.create_drawable_rect(x, y, width, height) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillRect(rect))).unwrap(); self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::FillRect(rect))).unwrap();
self.mark_as_dirty(); self.mark_as_dirty();
@ -593,7 +585,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect // https://html.spec.whatwg.org/multipage/#dom-context-2d-clearrect
fn ClearRect(self, x: f64, y: f64, width: f64, height: f64) { fn ClearRect(&self, x: f64, y: f64, width: f64, height: f64) {
if let Some(rect) = self.create_drawable_rect(x, y, width, height) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::Canvas2d(Canvas2dMsg::ClearRect(rect))) .send(CanvasMsg::Canvas2d(Canvas2dMsg::ClearRect(rect)))
@ -603,7 +595,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokerect
fn StrokeRect(self, x: f64, y: f64, width: f64, height: f64) { fn StrokeRect(&self, x: f64, y: f64, width: f64, height: f64) {
if let Some(rect) = self.create_drawable_rect(x, y, width, height) { if let Some(rect) = self.create_drawable_rect(x, y, width, height) {
self.ipc_renderer self.ipc_renderer
.send(CanvasMsg::Canvas2d(Canvas2dMsg::StrokeRect(rect))) .send(CanvasMsg::Canvas2d(Canvas2dMsg::StrokeRect(rect)))
@ -613,36 +605,36 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath // https://html.spec.whatwg.org/multipage/#dom-context-2d-beginpath
fn BeginPath(self) { fn BeginPath(&self) {
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::BeginPath)).unwrap(); self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::BeginPath)).unwrap();
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath // https://html.spec.whatwg.org/multipage/#dom-context-2d-closepath
fn ClosePath(self) { fn ClosePath(&self) {
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::ClosePath)).unwrap(); self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::ClosePath)).unwrap();
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-fill // https://html.spec.whatwg.org/multipage/#dom-context-2d-fill
fn Fill(self, _: CanvasWindingRule) { fn Fill(&self, _: CanvasWindingRule) {
// TODO: Process winding rule // TODO: Process winding rule
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Fill)).unwrap(); self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Fill)).unwrap();
self.mark_as_dirty(); self.mark_as_dirty();
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke // https://html.spec.whatwg.org/multipage/#dom-context-2d-stroke
fn Stroke(self) { fn Stroke(&self) {
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Stroke)).unwrap(); self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Stroke)).unwrap();
self.mark_as_dirty(); self.mark_as_dirty();
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-clip // https://html.spec.whatwg.org/multipage/#dom-context-2d-clip
fn Clip(self, _: CanvasWindingRule) { fn Clip(&self, _: CanvasWindingRule) {
// TODO: Process winding rule // TODO: Process winding rule
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Clip)).unwrap(); self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::Clip)).unwrap();
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, fn DrawImage(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
dx: f64, dy: f64) -> Fallible<()> { dx: f64, dy: f64) -> Fallible<()> {
if !(dx.is_finite() && dy.is_finite()) { if !(dx.is_finite() && dy.is_finite()) {
return Ok(()); return Ok(());
@ -652,7 +644,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage_(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, fn DrawImage_(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> { dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> {
if !(dx.is_finite() && dy.is_finite() && if !(dx.is_finite() && dy.is_finite() &&
dw.is_finite() && dh.is_finite()) { dw.is_finite() && dh.is_finite()) {
@ -663,7 +655,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage // https://html.spec.whatwg.org/multipage/#dom-context-2d-drawimage
fn DrawImage__(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, fn DrawImage__(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
sx: f64, sy: f64, sw: f64, sh: f64, sx: f64, sy: f64, sw: f64, sh: f64,
dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> { dx: f64, dy: f64, dw: f64, dh: f64) -> Fallible<()> {
if !(sx.is_finite() && sy.is_finite() && sw.is_finite() && sh.is_finite() && if !(sx.is_finite() && sy.is_finite() && sw.is_finite() && sh.is_finite() &&
@ -675,7 +667,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto // https://html.spec.whatwg.org/multipage/#dom-context-2d-moveto
fn MoveTo(self, x: f64, y: f64) { fn MoveTo(&self, x: f64, y: f64) {
if !(x.is_finite() && y.is_finite()) { if !(x.is_finite() && y.is_finite()) {
return; return;
} }
@ -687,7 +679,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto // https://html.spec.whatwg.org/multipage/#dom-context-2d-lineto
fn LineTo(self, x: f64, y: f64) { fn LineTo(&self, x: f64, y: f64) {
if !(x.is_finite() && y.is_finite()) { if !(x.is_finite() && y.is_finite()) {
return; return;
} }
@ -699,7 +691,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-rect // https://html.spec.whatwg.org/multipage/#dom-context-2d-rect
fn Rect(self, x: f64, y: f64, width: f64, height: f64) { fn Rect(&self, x: f64, y: f64, width: f64, height: f64) {
if [x, y, width, height].iter().all(|val| val.is_finite()) { if [x, y, width, height].iter().all(|val| val.is_finite()) {
let rect = Rect::new(Point2D::new(x as f32, y as f32), let rect = Rect::new(Point2D::new(x as f32, y as f32),
Size2D::new(width as f32, height as f32)); Size2D::new(width as f32, height as f32));
@ -709,7 +701,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto // https://html.spec.whatwg.org/multipage/#dom-context-2d-quadraticcurveto
fn QuadraticCurveTo(self, cpx: f64, cpy: f64, x: f64, y: f64) { fn QuadraticCurveTo(&self, cpx: f64, cpy: f64, x: f64, y: f64) {
if !(cpx.is_finite() && cpy.is_finite() && if !(cpx.is_finite() && cpy.is_finite() &&
x.is_finite() && y.is_finite()) { x.is_finite() && y.is_finite()) {
return; return;
@ -723,7 +715,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto // https://html.spec.whatwg.org/multipage/#dom-context-2d-beziercurveto
fn BezierCurveTo(self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) { fn BezierCurveTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, x: f64, y: f64) {
if !(cp1x.is_finite() && cp1y.is_finite() && cp2x.is_finite() && cp2y.is_finite() && if !(cp1x.is_finite() && cp1y.is_finite() && cp2x.is_finite() && cp2y.is_finite() &&
x.is_finite() && y.is_finite()) { x.is_finite() && y.is_finite()) {
return; return;
@ -738,7 +730,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-arc // https://html.spec.whatwg.org/multipage/#dom-context-2d-arc
fn Arc(self, x: f64, y: f64, r: f64, fn Arc(&self, x: f64, y: f64, r: f64,
start: f64, end: f64, ccw: bool) -> Fallible<()> { start: f64, end: f64, ccw: bool) -> Fallible<()> {
if !([x, y, r, start, end].iter().all(|x| x.is_finite())) { if !([x, y, r, start, end].iter().all(|x| x.is_finite())) {
return Ok(()); return Ok(());
@ -758,7 +750,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto // https://html.spec.whatwg.org/multipage/#dom-context-2d-arcto
fn ArcTo(self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> Fallible<()> { fn ArcTo(&self, cp1x: f64, cp1y: f64, cp2x: f64, cp2y: f64, r: f64) -> Fallible<()> {
if !([cp1x, cp1y, cp2x, cp2y, r].iter().all(|x| x.is_finite())) { if !([cp1x, cp1y, cp2x, cp2y, r].iter().all(|x| x.is_finite())) {
return Ok(()); return Ok(());
} }
@ -776,18 +768,18 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/#dom-context-2d-imagesmoothingenabled // https://html.spec.whatwg.org/#dom-context-2d-imagesmoothingenabled
fn ImageSmoothingEnabled(self) -> bool { fn ImageSmoothingEnabled(&self) -> bool {
let state = self.state.borrow(); let state = self.state.borrow();
state.image_smoothing_enabled state.image_smoothing_enabled
} }
// https://html.spec.whatwg.org/#dom-context-2d-imagesmoothingenabled // https://html.spec.whatwg.org/#dom-context-2d-imagesmoothingenabled
fn SetImageSmoothingEnabled(self, value: bool) -> () { fn SetImageSmoothingEnabled(&self, value: bool) -> () {
self.state.borrow_mut().image_smoothing_enabled = value; self.state.borrow_mut().image_smoothing_enabled = value;
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
fn StrokeStyle(self) -> StringOrCanvasGradientOrCanvasPattern { fn StrokeStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
match self.state.borrow().stroke_style { match self.state.borrow().stroke_style {
CanvasFillOrStrokeStyle::Color(ref rgba) => { CanvasFillOrStrokeStyle::Color(ref rgba) => {
let mut result = String::new(); let mut result = String::new();
@ -801,7 +793,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
fn SetStrokeStyle(self, value: StringOrCanvasGradientOrCanvasPattern) { fn SetStrokeStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
match value { match value {
StringOrCanvasGradientOrCanvasPattern::eString(string) => { StringOrCanvasGradientOrCanvasPattern::eString(string) => {
match parse_color(&string) { match parse_color(&string) {
@ -827,7 +819,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
fn FillStyle(self) -> StringOrCanvasGradientOrCanvasPattern { fn FillStyle(&self) -> StringOrCanvasGradientOrCanvasPattern {
match self.state.borrow().fill_style { match self.state.borrow().fill_style {
CanvasFillOrStrokeStyle::Color(ref rgba) => { CanvasFillOrStrokeStyle::Color(ref rgba) => {
let mut result = String::new(); let mut result = String::new();
@ -841,7 +833,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle // https://html.spec.whatwg.org/multipage/#dom-context-2d-strokestyle
fn SetFillStyle(self, value: StringOrCanvasGradientOrCanvasPattern) { fn SetFillStyle(&self, value: StringOrCanvasGradientOrCanvasPattern) {
match value { match value {
StringOrCanvasGradientOrCanvasPattern::eString(string) => { StringOrCanvasGradientOrCanvasPattern::eString(string) => {
if let Ok(rgba) = parse_color(&string) { if let Ok(rgba) = parse_color(&string) {
@ -867,7 +859,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
fn CreateImageData(self, sw: Finite<f64>, sh: Finite<f64>) -> Fallible<Root<ImageData>> { fn CreateImageData(&self, sw: Finite<f64>, sh: Finite<f64>) -> Fallible<Root<ImageData>> {
if *sw == 0.0 || *sh == 0.0 { if *sw == 0.0 || *sh == 0.0 {
return Err(IndexSize) return Err(IndexSize)
} }
@ -878,12 +870,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata // https://html.spec.whatwg.org/multipage/#dom-context-2d-createimagedata
fn CreateImageData_(self, imagedata: &ImageData) -> Fallible<Root<ImageData>> { fn CreateImageData_(&self, imagedata: &ImageData) -> Fallible<Root<ImageData>> {
Ok(ImageData::new(self.global.root().r(), imagedata.Width(), imagedata.Height(), None)) Ok(ImageData::new(self.global.root().r(), imagedata.Width(), imagedata.Height(), None))
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata // https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata
fn GetImageData(self, fn GetImageData(&self,
sx: Finite<f64>, sx: Finite<f64>,
sy: Finite<f64>, sy: Finite<f64>,
sw: Finite<f64>, sw: Finite<f64>,
@ -933,13 +925,13 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
fn PutImageData(self, imagedata: &ImageData, dx: Finite<f64>, dy: Finite<f64>) { fn PutImageData(&self, imagedata: &ImageData, dx: Finite<f64>, dy: Finite<f64>) {
self.PutImageData_(imagedata, dx, dy, Finite::wrap(0f64), Finite::wrap(0f64), self.PutImageData_(imagedata, dx, dy, Finite::wrap(0f64), Finite::wrap(0f64),
Finite::wrap(imagedata.Width() as f64), Finite::wrap(imagedata.Height() as f64)) Finite::wrap(imagedata.Width() as f64), Finite::wrap(imagedata.Height() as f64))
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata // https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
fn PutImageData_(self, imagedata: &ImageData, dx: Finite<f64>, dy: Finite<f64>, fn PutImageData_(&self, imagedata: &ImageData, dx: Finite<f64>, dy: Finite<f64>,
dirtyX: Finite<f64>, dirtyY: Finite<f64>, dirtyWidth: Finite<f64>, dirtyHeight: Finite<f64>) { dirtyX: Finite<f64>, dirtyY: Finite<f64>, dirtyWidth: Finite<f64>, dirtyHeight: Finite<f64>) {
let data = imagedata.get_data_array(&self.global.root().r()); let data = imagedata.get_data_array(&self.global.root().r());
let offset = Point2D::new(*dx, *dy); let offset = Point2D::new(*dx, *dy);
@ -954,14 +946,14 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient // https://html.spec.whatwg.org/multipage/#dom-context-2d-createlineargradient
fn CreateLinearGradient(self, x0: Finite<f64>, y0: Finite<f64>, fn CreateLinearGradient(&self, x0: Finite<f64>, y0: Finite<f64>,
x1: Finite<f64>, y1: Finite<f64>) -> Root<CanvasGradient> { x1: Finite<f64>, y1: Finite<f64>) -> Root<CanvasGradient> {
CanvasGradient::new(self.global.root().r(), CanvasGradient::new(self.global.root().r(),
CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, *x1, *y1, Vec::new()))) CanvasGradientStyle::Linear(LinearGradientStyle::new(*x0, *y0, *x1, *y1, Vec::new())))
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient // https://html.spec.whatwg.org/multipage/#dom-context-2d-createradialgradient
fn CreateRadialGradient(self, x0: Finite<f64>, y0: Finite<f64>, r0: Finite<f64>, fn CreateRadialGradient(&self, x0: Finite<f64>, y0: Finite<f64>, r0: Finite<f64>,
x1: Finite<f64>, y1: Finite<f64>, r1: Finite<f64>) x1: Finite<f64>, y1: Finite<f64>, r1: Finite<f64>)
-> Fallible<Root<CanvasGradient>> { -> Fallible<Root<CanvasGradient>> {
if *r0 < 0. || *r1 < 0. { if *r0 < 0. || *r1 < 0. {
@ -974,7 +966,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern // https://html.spec.whatwg.org/multipage/#dom-context-2d-createpattern
fn CreatePattern(self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D, fn CreatePattern(&self, image: HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D,
repetition: DOMString) -> Fallible<Root<CanvasPattern>> { repetition: DOMString) -> Fallible<Root<CanvasPattern>> {
let (image_data, image_size) = match image { let (image_data, image_size) = match image {
HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => { HTMLImageElementOrHTMLCanvasElementOrCanvasRenderingContext2D::eHTMLImageElement(image) => {
@ -1024,13 +1016,13 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
fn LineWidth(self) -> f64 { fn LineWidth(&self) -> f64 {
let state = self.state.borrow(); let state = self.state.borrow();
state.line_width state.line_width
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth // https://html.spec.whatwg.org/multipage/#dom-context-2d-linewidth
fn SetLineWidth(self, width: f64) { fn SetLineWidth(&self, width: f64) {
if !width.is_finite() || width <= 0.0 { if !width.is_finite() || width <= 0.0 {
return; return;
} }
@ -1042,7 +1034,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap
fn LineCap(self) -> DOMString { fn LineCap(&self) -> DOMString {
let state = self.state.borrow(); let state = self.state.borrow();
match state.line_cap { match state.line_cap {
LineCapStyle::Butt => "butt".to_owned(), LineCapStyle::Butt => "butt".to_owned(),
@ -1052,7 +1044,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap // https://html.spec.whatwg.org/multipage/#dom-context-2d-linecap
fn SetLineCap(self, cap_str: DOMString) { fn SetLineCap(&self, cap_str: DOMString) {
if let Some(cap) = LineCapStyle::from_str(&cap_str) { if let Some(cap) = LineCapStyle::from_str(&cap_str) {
self.state.borrow_mut().line_cap = cap; self.state.borrow_mut().line_cap = cap;
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineCap(cap))).unwrap() self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineCap(cap))).unwrap()
@ -1060,7 +1052,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin
fn LineJoin(self) -> DOMString { fn LineJoin(&self) -> DOMString {
let state = self.state.borrow(); let state = self.state.borrow();
match state.line_join { match state.line_join {
LineJoinStyle::Round => "round".to_owned(), LineJoinStyle::Round => "round".to_owned(),
@ -1070,7 +1062,7 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin // https://html.spec.whatwg.org/multipage/#dom-context-2d-linejoin
fn SetLineJoin(self, join_str: DOMString) { fn SetLineJoin(&self, join_str: DOMString) {
if let Some(join) = LineJoinStyle::from_str(&join_str) { if let Some(join) = LineJoinStyle::from_str(&join_str) {
self.state.borrow_mut().line_join = join; self.state.borrow_mut().line_join = join;
self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineJoin(join))).unwrap() self.ipc_renderer.send(CanvasMsg::Canvas2d(Canvas2dMsg::SetLineJoin(join))).unwrap()
@ -1078,13 +1070,13 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit
fn MiterLimit(self) -> f64 { fn MiterLimit(&self) -> f64 {
let state = self.state.borrow(); let state = self.state.borrow();
state.miter_limit state.miter_limit
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit // https://html.spec.whatwg.org/multipage/#dom-context-2d-miterlimit
fn SetMiterLimit(self, limit: f64) { fn SetMiterLimit(&self, limit: f64) {
if !limit.is_finite() || limit <= 0.0 { if !limit.is_finite() || limit <= 0.0 {
return; return;
} }
@ -1096,12 +1088,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx
fn ShadowOffsetX(self) -> f64 { fn ShadowOffsetX(&self) -> f64 {
self.state.borrow().shadow_offset_x self.state.borrow().shadow_offset_x
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsetx
fn SetShadowOffsetX(self, value: f64) { fn SetShadowOffsetX(&self, value: f64) {
if !value.is_finite() || value == self.state.borrow().shadow_offset_x { if !value.is_finite() || value == self.state.borrow().shadow_offset_x {
return; return;
} }
@ -1110,12 +1102,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety
fn ShadowOffsetY(self) -> f64 { fn ShadowOffsetY(&self) -> f64 {
self.state.borrow().shadow_offset_y self.state.borrow().shadow_offset_y
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowoffsety
fn SetShadowOffsetY(self, value: f64) { fn SetShadowOffsetY(&self, value: f64) {
if !value.is_finite() || value == self.state.borrow().shadow_offset_y { if !value.is_finite() || value == self.state.borrow().shadow_offset_y {
return; return;
} }
@ -1124,12 +1116,12 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur
fn ShadowBlur(self) -> f64 { fn ShadowBlur(&self) -> f64 {
self.state.borrow().shadow_blur self.state.borrow().shadow_blur
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowblur
fn SetShadowBlur(self, value: f64) { fn SetShadowBlur(&self, value: f64) {
if !value.is_finite() || value < 0f64 || value == self.state.borrow().shadow_blur { if !value.is_finite() || value < 0f64 || value == self.state.borrow().shadow_blur {
return; return;
} }
@ -1138,14 +1130,14 @@ impl<'a> CanvasRenderingContext2DMethods for &'a CanvasRenderingContext2D {
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor
fn ShadowColor(self) -> DOMString { fn ShadowColor(&self) -> DOMString {
let mut result = String::new(); let mut result = String::new();
serialize(&self.state.borrow().shadow_color, &mut result).unwrap(); serialize(&self.state.borrow().shadow_color, &mut result).unwrap();
result result
} }
// https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor // https://html.spec.whatwg.org/multipage/#dom-context-2d-shadowcolor
fn SetShadowColor(self, value: DOMString) { fn SetShadowColor(&self, value: DOMString) {
if let Ok(color) = parse_color(&value) { if let Ok(color) = parse_color(&value) {
self.state.borrow_mut().shadow_color = color; self.state.borrow_mut().shadow_color = color;
self.ipc_renderer self.ipc_renderer

View file

@ -15,16 +15,15 @@ use dom::bindings::js::{LayoutJS, Root};
use dom::document::Document; use dom::document::Document;
use dom::element::Element; use dom::element::Element;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::node::{Node, NodeHelpers, NodeTypeId}; use dom::node::{Node, NodeTypeId};
use util::str::{DOMString, slice_chars}; use util::str::DOMString;
use std::borrow::ToOwned; use std::borrow::ToOwned;
use std::cell::Ref; use std::cell::Ref;
// https://dom.spec.whatwg.org/#characterdata // https://dom.spec.whatwg.org/#characterdata
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct CharacterData { pub struct CharacterData {
node: Node, node: Node,
data: DOMRefCell<DOMString>, data: DOMRefCell<DOMString>,
@ -48,103 +47,111 @@ impl CharacterData {
} }
} }
impl<'a> CharacterDataMethods for &'a CharacterData { impl CharacterDataMethods for CharacterData {
// https://dom.spec.whatwg.org/#dom-characterdata-data // https://dom.spec.whatwg.org/#dom-characterdata-data
fn Data(self) -> DOMString { fn Data(&self) -> DOMString {
self.data.borrow().clone() self.data.borrow().clone()
} }
// https://dom.spec.whatwg.org/#dom-characterdata-data // https://dom.spec.whatwg.org/#dom-characterdata-data
fn SetData(self, data: DOMString) { fn SetData(&self, data: DOMString) {
*self.data.borrow_mut() = data; *self.data.borrow_mut() = data;
} }
// https://dom.spec.whatwg.org/#dom-characterdata-length // https://dom.spec.whatwg.org/#dom-characterdata-length
fn Length(self) -> u32 { fn Length(&self) -> u32 {
self.data.borrow().chars().count() as u32 self.data.borrow().chars().map(|c| c.len_utf16()).sum::<usize>() as u32
} }
// https://dom.spec.whatwg.org/#dom-characterdata-substringdataoffset-count // https://dom.spec.whatwg.org/#dom-characterdata-substringdata
fn SubstringData(self, offset: u32, count: u32) -> Fallible<DOMString> { fn SubstringData(&self, offset: u32, count: u32) -> Fallible<DOMString> {
let data = self.data.borrow(); let data = self.data.borrow();
// Step 1. // Step 1.
let length = data.chars().count() as u32; let data_from_offset = match find_utf16_code_unit_offset(&data, offset) {
if offset > length { Some(offset_bytes) => &data[offset_bytes..],
// Step 2. // Step 2.
return Err(IndexSize); None => return Err(IndexSize)
} };
// Steps 3-4. let substring = match find_utf16_code_unit_offset(data_from_offset, count) {
let end = if length - offset < count { length } else { offset + count }; // Steps 3.
Ok(slice_chars(&*data, offset as usize, end as usize).to_owned()) None => data_from_offset,
// Steps 4.
Some(count_bytes) => &data_from_offset[..count_bytes],
};
Ok(substring.to_owned())
} }
// https://dom.spec.whatwg.org/#dom-characterdata-appenddatadata // https://dom.spec.whatwg.org/#dom-characterdata-appenddatadata
fn AppendData(self, data: DOMString) { fn AppendData(&self, data: DOMString) {
self.append_data(&*data); self.append_data(&*data);
} }
// https://dom.spec.whatwg.org/#dom-characterdata-insertdataoffset-data // https://dom.spec.whatwg.org/#dom-characterdata-insertdataoffset-data
fn InsertData(self, offset: u32, arg: DOMString) -> ErrorResult { fn InsertData(&self, offset: u32, arg: DOMString) -> ErrorResult {
self.ReplaceData(offset, 0, arg) self.ReplaceData(offset, 0, arg)
} }
// https://dom.spec.whatwg.org/#dom-characterdata-deletedataoffset-count // https://dom.spec.whatwg.org/#dom-characterdata-deletedataoffset-count
fn DeleteData(self, offset: u32, count: u32) -> ErrorResult { fn DeleteData(&self, offset: u32, count: u32) -> ErrorResult {
self.ReplaceData(offset, count, "".to_owned()) self.ReplaceData(offset, count, "".to_owned())
} }
// https://dom.spec.whatwg.org/#dom-characterdata-replacedataoffset-count-data // https://dom.spec.whatwg.org/#dom-characterdata-replacedata
fn ReplaceData(self, offset: u32, count: u32, arg: DOMString) -> ErrorResult { fn ReplaceData(&self, offset: u32, count: u32, arg: DOMString) -> ErrorResult {
// Step 1. let new_data = {
let length = self.data.borrow().chars().count() as u32; let data = self.data.borrow();
if offset > length { let (prefix, data_from_offset) = match find_utf16_code_unit_offset(&data, offset) {
// Step 2. Some(offset_bytes) => data.split_at(offset_bytes),
return Err(IndexSize); // Step 2.
} None => return Err(IndexSize)
// Step 3. };
let count = match length - offset { let suffix = match find_utf16_code_unit_offset(data_from_offset, count) {
diff if diff < count => diff, // Steps 3.
_ => count, None => "",
Some(count_bytes) => &data_from_offset[count_bytes..],
};
// Step 4: Mutation observers.
// Step 5 to 7.
let mut new_data = String::with_capacity(prefix.len() + arg.len() + suffix.len());
new_data.push_str(prefix);
new_data.push_str(&arg);
new_data.push_str(suffix);
new_data
}; };
// Step 4: Mutation observers. *self.data.borrow_mut() = new_data;
// Step 5. // FIXME: Once we have `Range`, we should implement step 8 to step 11
let mut data = slice_chars(&*self.data.borrow(), 0, offset as usize).to_owned();
data.push_str(&arg);
data.push_str(slice_chars(&*self.data.borrow(), (offset + count) as usize, length as usize));
*self.data.borrow_mut() = data;
// FIXME: Once we have `Range`, we should implement step7 to step11
Ok(()) Ok(())
} }
// https://dom.spec.whatwg.org/#dom-childnode-before // https://dom.spec.whatwg.org/#dom-childnode-before
fn Before(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn Before(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).before(nodes) NodeCast::from_ref(self).before(nodes)
} }
// https://dom.spec.whatwg.org/#dom-childnode-after // https://dom.spec.whatwg.org/#dom-childnode-after
fn After(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn After(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).after(nodes) NodeCast::from_ref(self).after(nodes)
} }
// https://dom.spec.whatwg.org/#dom-childnode-replacewith // https://dom.spec.whatwg.org/#dom-childnode-replacewith
fn ReplaceWith(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn ReplaceWith(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).replace_with(nodes) NodeCast::from_ref(self).replace_with(nodes)
} }
// https://dom.spec.whatwg.org/#dom-childnode-remove // https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(self) { fn Remove(&self) {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.remove_self(); node.remove_self();
} }
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling // https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling
fn GetPreviousElementSibling(self) -> Option<Root<Element>> { fn GetPreviousElementSibling(&self) -> Option<Root<Element>> {
NodeCast::from_ref(self).preceding_siblings() NodeCast::from_ref(self).preceding_siblings()
.filter_map(ElementCast::to_root).next() .filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling // https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling
fn GetNextElementSibling(self) -> Option<Root<Element>> { fn GetNextElementSibling(&self) -> Option<Root<Element>> {
NodeCast::from_ref(self).following_siblings() NodeCast::from_ref(self).following_siblings()
.filter_map(ElementCast::to_root).next() .filter_map(ElementCast::to_root).next()
} }
@ -158,18 +165,14 @@ pub enum CharacterDataTypeId {
ProcessingInstruction, ProcessingInstruction,
} }
pub trait CharacterDataHelpers<'a> {
fn data(self) -> Ref<'a, DOMString>;
fn append_data(self, data: &str);
}
impl<'a> CharacterDataHelpers<'a> for &'a CharacterData { impl CharacterData {
#[inline] #[inline]
fn data(self) -> Ref<'a, DOMString> { pub fn data(&self) -> Ref<DOMString> {
self.data.borrow() self.data.borrow()
} }
#[inline] #[inline]
fn append_data(self, data: &str) { pub fn append_data(&self, data: &str) {
self.data.borrow_mut().push_str(data) self.data.borrow_mut().push_str(data)
} }
} }
@ -186,3 +189,32 @@ impl LayoutCharacterDataHelpers for LayoutJS<CharacterData> {
&(*self.unsafe_get()).data.borrow_for_layout() &(*self.unsafe_get()).data.borrow_for_layout()
} }
} }
/// Given a number of UTF-16 code units from the start of the given string,
/// return the corresponding number of UTF-8 bytes.
///
/// s[find_utf16_code_unit_offset(s, o).unwrap()..] == s.to_utf16()[o..].to_utf8()
fn find_utf16_code_unit_offset(s: &str, offset: u32) -> Option<usize> {
let mut code_units = 0;
for (i, c) in s.char_indices() {
if code_units == offset {
return Some(i)
}
code_units += 1;
if c > '\u{FFFF}' {
if code_units == offset {
panic!("\n\n\
Would split a surrogate pair in CharacterData API.\n\
If you see this in real content, please comment with the URL\n\
on https://github.com/servo/servo/issues/6873\n\
\n");
}
code_units += 1;
}
}
if code_units == offset {
Some(s.len())
} else {
None
}
}

View file

@ -16,7 +16,6 @@ use script_task::ScriptChan;
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct CloseEvent { pub struct CloseEvent {
event: Event, event: Event,
wasClean: bool, wasClean: bool,
@ -69,19 +68,19 @@ impl CloseEvent {
} }
} }
impl<'a> CloseEventMethods for &'a CloseEvent { impl CloseEventMethods for CloseEvent {
// https://html.spec.whatwg.org/multipage/#dom-closeevent-wasclean // https://html.spec.whatwg.org/multipage/#dom-closeevent-wasclean
fn WasClean(self) -> bool { fn WasClean(&self) -> bool {
self.wasClean self.wasClean
} }
// https://html.spec.whatwg.org/multipage/#dom-closeevent-code // https://html.spec.whatwg.org/multipage/#dom-closeevent-code
fn Code(self) -> u16 { fn Code(&self) -> u16 {
self.code self.code
} }
// https://html.spec.whatwg.org/multipage/#dom-closeevent-reason // https://html.spec.whatwg.org/multipage/#dom-closeevent-reason
fn Reason(self) -> DOMString { fn Reason(&self) -> DOMString {
self.reason.clone() self.reason.clone()
} }
} }

View file

@ -16,7 +16,6 @@ use util::str::DOMString;
/// An HTML comment. /// An HTML comment.
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct Comment { pub struct Comment {
characterdata: CharacterData, characterdata: CharacterData,
} }
@ -44,4 +43,3 @@ impl Comment {
Ok(Comment::new(data, document.r())) Ok(Comment::new(data, document.r()))
} }
} }

View file

@ -8,12 +8,10 @@ use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::window::WindowHelpers;
use util::str::DOMString; use util::str::DOMString;
// https://developer.mozilla.org/en-US/docs/Web/API/Console // https://developer.mozilla.org/en-US/docs/Web/API/Console
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct Console { pub struct Console {
reflector_: Reflector, reflector_: Reflector,
global: GlobalField, global: GlobalField,
@ -32,9 +30,9 @@ impl Console {
} }
} }
impl<'a> ConsoleMethods for &'a Console { impl ConsoleMethods for Console {
// https://developer.mozilla.org/en-US/docs/Web/API/Console/log // https://developer.mozilla.org/en-US/docs/Web/API/Console/log
fn Log(self, messages: Vec<DOMString>) { fn Log(&self, messages: Vec<DOMString>) {
for message in messages { for message in messages {
println!("{}", message); println!("{}", message);
propagate_console_msg(&self, prepare_message(LogLevel::Log, message)); propagate_console_msg(&self, prepare_message(LogLevel::Log, message));
@ -42,7 +40,7 @@ impl<'a> ConsoleMethods for &'a Console {
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console // https://developer.mozilla.org/en-US/docs/Web/API/Console
fn Debug(self, messages: Vec<DOMString>) { fn Debug(&self, messages: Vec<DOMString>) {
for message in messages { for message in messages {
println!("{}", message); println!("{}", message);
propagate_console_msg(&self, prepare_message(LogLevel::Debug, message)); propagate_console_msg(&self, prepare_message(LogLevel::Debug, message));
@ -50,7 +48,7 @@ impl<'a> ConsoleMethods for &'a Console {
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/info // https://developer.mozilla.org/en-US/docs/Web/API/Console/info
fn Info(self, messages: Vec<DOMString>) { fn Info(&self, messages: Vec<DOMString>) {
for message in messages { for message in messages {
println!("{}", message); println!("{}", message);
propagate_console_msg(&self, prepare_message(LogLevel::Info, message)); propagate_console_msg(&self, prepare_message(LogLevel::Info, message));
@ -58,7 +56,7 @@ impl<'a> ConsoleMethods for &'a Console {
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/warn // https://developer.mozilla.org/en-US/docs/Web/API/Console/warn
fn Warn(self, messages: Vec<DOMString>) { fn Warn(&self, messages: Vec<DOMString>) {
for message in messages { for message in messages {
println!("{}", message); println!("{}", message);
propagate_console_msg(&self, prepare_message(LogLevel::Warn, message)); propagate_console_msg(&self, prepare_message(LogLevel::Warn, message));
@ -66,7 +64,7 @@ impl<'a> ConsoleMethods for &'a Console {
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/error // https://developer.mozilla.org/en-US/docs/Web/API/Console/error
fn Error(self, messages: Vec<DOMString>) { fn Error(&self, messages: Vec<DOMString>) {
for message in messages { for message in messages {
println!("{}", message); println!("{}", message);
propagate_console_msg(&self, prepare_message(LogLevel::Error, message)); propagate_console_msg(&self, prepare_message(LogLevel::Error, message));
@ -74,7 +72,7 @@ impl<'a> ConsoleMethods for &'a Console {
} }
// https://developer.mozilla.org/en-US/docs/Web/API/Console/assert // https://developer.mozilla.org/en-US/docs/Web/API/Console/assert
fn Assert(self, condition: bool, message: Option<DOMString>) { fn Assert(&self, condition: bool, message: Option<DOMString>) {
if !condition { if !condition {
let message = match message { let message = match message {
Some(ref message) => &**message, Some(ref message) => &**message,

View file

@ -22,7 +22,6 @@ no_jsmanaged_fields!(OsRng);
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto // https://developer.mozilla.org/en-US/docs/Web/API/Crypto
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct Crypto { pub struct Crypto {
reflector_: Reflector, reflector_: Reflector,
rng: DOMRefCell<OsRng>, rng: DOMRefCell<OsRng>,
@ -41,10 +40,10 @@ impl Crypto {
} }
} }
impl<'a> CryptoMethods for &'a Crypto { impl CryptoMethods for Crypto {
#[allow(unsafe_code)] #[allow(unsafe_code)]
// https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#Crypto-method-getRandomValues // https://dvcs.w3.org/hg/webcrypto-api/raw-file/tip/spec/Overview.html#Crypto-method-getRandomValues
fn GetRandomValues(self, _cx: *mut JSContext, input: *mut JSObject) fn GetRandomValues(&self, _cx: *mut JSContext, input: *mut JSObject)
-> Fallible<*mut JSObject> { -> Fallible<*mut JSObject> {
let mut length = 0; let mut length = 0;
let mut data = ptr::null_mut(); let mut data = ptr::null_mut();

View file

@ -10,7 +10,6 @@ use util::str::DOMString;
use cssparser::serialize_identifier; use cssparser::serialize_identifier;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct CSS { pub struct CSS {
reflector_: Reflector, reflector_: Reflector,
} }

View file

@ -8,10 +8,9 @@ use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::document::DocumentHelpers; use dom::element::{StylePriority, Element};
use dom::element::{ElementHelpers, StylePriority, Element}; use dom::node::{window_from_node, document_from_node, NodeDamage};
use dom::node::{window_from_node, document_from_node, NodeDamage, NodeHelpers}; use dom::window::Window;
use dom::window::{Window, WindowHelpers};
use selectors::parser::PseudoElement; use selectors::parser::PseudoElement;
use string_cache::Atom; use string_cache::Atom;
use style::properties::PropertyDeclaration; use style::properties::PropertyDeclaration;
@ -24,7 +23,6 @@ use std::cell::Ref;
// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct CSSStyleDeclaration { pub struct CSSStyleDeclaration {
reflector_: Reflector, reflector_: Reflector,
owner: JS<Element>, owner: JS<Element>,
@ -41,10 +39,10 @@ pub enum CSSModificationAccess {
macro_rules! css_properties( macro_rules! css_properties(
( $([$getter:ident, $setter:ident, $cssprop:expr]),* ) => ( ( $([$getter:ident, $setter:ident, $cssprop:expr]),* ) => (
$( $(
fn $getter(self) -> DOMString { fn $getter(&self) -> DOMString {
self.GetPropertyValue($cssprop.to_owned()) self.GetPropertyValue($cssprop.to_owned())
} }
fn $setter(self, value: DOMString) -> ErrorResult { fn $setter(&self, value: DOMString) -> ErrorResult {
self.SetPropertyValue($cssprop.to_owned(), value) self.SetPropertyValue($cssprop.to_owned(), value)
} }
)* )*
@ -76,9 +74,7 @@ impl CSSStyleDeclaration {
GlobalRef::Window(global), GlobalRef::Window(global),
CSSStyleDeclarationBinding::Wrap) CSSStyleDeclarationBinding::Wrap)
} }
}
impl CSSStyleDeclaration {
fn get_computed_style(&self, property: &Atom) -> Option<DOMString> { fn get_computed_style(&self, property: &Atom) -> Option<DOMString> {
let owner = self.owner.root(); let owner = self.owner.root();
let node = NodeCast::from_ref(owner.r()); let node = NodeCast::from_ref(owner.r());
@ -92,9 +88,9 @@ impl CSSStyleDeclaration {
} }
} }
impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration { impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length
fn Length(self) -> u32 { fn Length(&self) -> u32 {
let owner = self.owner.root(); let owner = self.owner.root();
let elem = ElementCast::from_ref(owner.r()); let elem = ElementCast::from_ref(owner.r());
let len = match *elem.style_attribute().borrow() { let len = match *elem.style_attribute().borrow() {
@ -105,7 +101,7 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
} }
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item
fn Item(self, index: u32) -> DOMString { fn Item(&self, index: u32) -> DOMString {
let index = index as usize; let index = index as usize;
let owner = self.owner.root(); let owner = self.owner.root();
let elem = ElementCast::from_ref(owner.r()); let elem = ElementCast::from_ref(owner.r());
@ -126,7 +122,7 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
} }
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
fn GetPropertyValue(self, property: DOMString) -> DOMString { fn GetPropertyValue(&self, property: DOMString) -> DOMString {
let owner = self.owner.root(); let owner = self.owner.root();
// Step 1 // Step 1
@ -169,7 +165,7 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
} }
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
fn GetPropertyPriority(self, property: DOMString) -> DOMString { fn GetPropertyPriority(&self, property: DOMString) -> DOMString {
// Step 1 // Step 1
let property = Atom::from_slice(&property.to_ascii_lowercase()); let property = Atom::from_slice(&property.to_ascii_lowercase());
@ -197,7 +193,7 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
} }
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setproperty // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setproperty
fn SetProperty(self, property: DOMString, value: DOMString, fn SetProperty(&self, property: DOMString, value: DOMString,
priority: DOMString) -> ErrorResult { priority: DOMString) -> ErrorResult {
// Step 1 // Step 1
if self.readonly { if self.readonly {
@ -252,7 +248,7 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
} }
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setpropertypriority // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setpropertypriority
fn SetPropertyPriority(self, property: DOMString, priority: DOMString) -> ErrorResult { fn SetPropertyPriority(&self, property: DOMString, priority: DOMString) -> ErrorResult {
// Step 1 // Step 1
if self.readonly { if self.readonly {
return Err(Error::NoModificationAllowed); return Err(Error::NoModificationAllowed);
@ -286,12 +282,12 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
} }
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setpropertyvalue // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setpropertyvalue
fn SetPropertyValue(self, property: DOMString, value: DOMString) -> ErrorResult { fn SetPropertyValue(&self, property: DOMString, value: DOMString) -> ErrorResult {
self.SetProperty(property, value, "".to_owned()) self.SetProperty(property, value, "".to_owned())
} }
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-removeproperty // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-removeproperty
fn RemoveProperty(self, property: DOMString) -> Fallible<DOMString> { fn RemoveProperty(&self, property: DOMString) -> Fallible<DOMString> {
// Step 1 // Step 1
if self.readonly { if self.readonly {
return Err(Error::NoModificationAllowed); return Err(Error::NoModificationAllowed);
@ -322,21 +318,22 @@ impl<'a> CSSStyleDeclarationMethods for &'a CSSStyleDeclaration {
} }
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-cssfloat // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-cssfloat
fn CssFloat(self) -> DOMString { fn CssFloat(&self) -> DOMString {
self.GetPropertyValue("float".to_owned()) self.GetPropertyValue("float".to_owned())
} }
// https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-cssfloat // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-cssfloat
fn SetCssFloat(self, value: DOMString) -> ErrorResult { fn SetCssFloat(&self, value: DOMString) -> ErrorResult {
self.SetPropertyValue("float".to_owned(), value) self.SetPropertyValue("float".to_owned(), value)
} }
// https://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface // https://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
fn IndexedGetter(self, index: u32, found: &mut bool) -> DOMString { fn IndexedGetter(&self, index: u32, found: &mut bool) -> DOMString {
let rval = self.Item(index); let rval = self.Item(index);
*found = index < self.Length(); *found = index < self.Length();
rval rval
} }
// https://drafts.csswg.org/cssom/#cssstyledeclaration
css_properties_accessors!(css_properties); css_properties_accessors!(css_properties);
} }

View file

@ -17,7 +17,6 @@ use util::str::DOMString;
// https://dom.spec.whatwg.org/#interface-customevent // https://dom.spec.whatwg.org/#interface-customevent
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct CustomEvent { pub struct CustomEvent {
event: Event, event: Event,
#[ignore_heap_size_of = "Defined in rust-mozjs"] #[ignore_heap_size_of = "Defined in rust-mozjs"]
@ -63,14 +62,14 @@ impl CustomEvent {
} }
} }
impl<'a> CustomEventMethods for &'a CustomEvent { impl CustomEventMethods for CustomEvent {
// https://dom.spec.whatwg.org/#dom-customevent-detail // https://dom.spec.whatwg.org/#dom-customevent-detail
fn Detail(self, _cx: *mut JSContext) -> JSVal { fn Detail(&self, _cx: *mut JSContext) -> JSVal {
self.detail.get() self.detail.get()
} }
// https://dom.spec.whatwg.org/#dom-customevent-initcustomevent // https://dom.spec.whatwg.org/#dom-customevent-initcustomevent
fn InitCustomEvent(self, fn InitCustomEvent(&self,
_cx: *mut JSContext, _cx: *mut JSContext,
type_: DOMString, type_: DOMString,
can_bubble: bool, can_bubble: bool,
@ -85,4 +84,3 @@ impl<'a> CustomEventMethods for &'a CustomEvent {
event.InitEvent(type_, can_bubble, cancelable); event.InitEvent(type_, can_bubble, cancelable);
} }
} }

View file

@ -6,7 +6,6 @@ use devtools;
use dom::bindings::cell::DOMRefCell; use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding; use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding;
use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding::DedicatedWorkerGlobalScopeMethods; use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding::DedicatedWorkerGlobalScopeMethods;
use dom::bindings::codegen::Bindings::ErrorEventBinding::ErrorEventMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived; use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast};
@ -16,12 +15,12 @@ use dom::bindings::js::{RootCollection, Root};
use dom::bindings::refcounted::LiveDOMReferences; use dom::bindings::refcounted::LiveDOMReferences;
use dom::bindings::structuredclone::StructuredCloneData; use dom::bindings::structuredclone::StructuredCloneData;
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
use dom::errorevent::ErrorEvent; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use dom::messageevent::MessageEvent; use dom::messageevent::MessageEvent;
use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, WorkerEventHandler, WorkerErrorHandler}; use dom::worker::{TrustedWorkerAddress, WorkerMessageHandler, SimpleWorkerErrorHandler};
use dom::workerglobalscope::{WorkerGlobalScope, WorkerGlobalScopeHelpers}; use dom::workerglobalscope::WorkerGlobalScope;
use dom::workerglobalscope::{WorkerGlobalScopeTypeId, WorkerGlobalScopeInit}; use dom::workerglobalscope::{WorkerGlobalScopeTypeId, WorkerGlobalScopeInit};
use script_task::ScriptTaskEventCategory::WorkerEvent;
use script_task::{ScriptTask, ScriptChan, TimerSource, ScriptPort, StackRootTLS, CommonScriptMsg}; use script_task::{ScriptTask, ScriptChan, TimerSource, ScriptPort, StackRootTLS, CommonScriptMsg};
use devtools_traits::DevtoolScriptControlMsg; use devtools_traits::DevtoolScriptControlMsg;
@ -138,7 +137,6 @@ enum MixedMessage {
// https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope // https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DedicatedWorkerGlobalScope { pub struct DedicatedWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope, workerglobalscope: WorkerGlobalScope,
id: PipelineId, id: PipelineId,
@ -189,9 +187,7 @@ impl DedicatedWorkerGlobalScope {
own_sender, receiver); own_sender, receiver);
DedicatedWorkerGlobalScopeBinding::Wrap(runtime.cx(), scope) DedicatedWorkerGlobalScopeBinding::Wrap(runtime.cx(), scope)
} }
}
impl DedicatedWorkerGlobalScope {
pub fn run_worker_scope(init: WorkerGlobalScopeInit, pub fn run_worker_scope(init: WorkerGlobalScopeInit,
worker_url: Url, worker_url: Url,
id: PipelineId, id: PipelineId,
@ -210,8 +206,8 @@ impl DedicatedWorkerGlobalScope {
let (url, source) = match load_whole_resource(&init.resource_task, worker_url) { let (url, source) = match load_whole_resource(&init.resource_task, worker_url) {
Err(_) => { Err(_) => {
println!("error loading script {}", serialized_worker_url); println!("error loading script {}", serialized_worker_url);
parent_sender.send(CommonScriptMsg::RunnableMsg( parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
box WorkerEventHandler::new(worker))).unwrap(); box SimpleWorkerErrorHandler::new(worker))).unwrap();
return; return;
} }
Ok((metadata, bytes)) => { Ok((metadata, bytes)) => {
@ -244,28 +240,19 @@ impl DedicatedWorkerGlobalScope {
}, reporter_name, parent_sender, CommonScriptMsg::CollectReports); }, reporter_name, parent_sender, CommonScriptMsg::CollectReports);
}); });
} }
}
pub trait DedicatedWorkerGlobalScopeHelpers { pub fn script_chan(&self) -> Box<ScriptChan + Send> {
fn script_chan(self) -> Box<ScriptChan + Send>;
fn pipeline(self) -> PipelineId;
fn new_script_pair(self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>);
fn process_event(self, msg: CommonScriptMsg);
}
impl<'a> DedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope {
fn script_chan(self) -> Box<ScriptChan + Send> {
box WorkerThreadWorkerChan { box WorkerThreadWorkerChan {
sender: self.own_sender.clone(), sender: self.own_sender.clone(),
worker: self.worker.borrow().as_ref().unwrap().clone(), worker: self.worker.borrow().as_ref().unwrap().clone(),
} }
} }
fn pipeline(self) -> PipelineId { pub fn pipeline(&self) -> PipelineId {
self.id self.id
} }
fn new_script_pair(self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) { pub fn new_script_pair(&self) -> (Box<ScriptChan + Send>, Box<ScriptPort + Send>) {
let (tx, rx) = channel(); let (tx, rx) = channel();
let chan = box SendableWorkerScriptChan { let chan = box SendableWorkerScriptChan {
sender: tx, sender: tx,
@ -274,21 +261,12 @@ impl<'a> DedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope {
(chan, box rx) (chan, box rx)
} }
fn process_event(self, msg: CommonScriptMsg) { pub fn process_event(&self, msg: CommonScriptMsg) {
self.handle_script_event(WorkerScriptMsg::Common(msg)); self.handle_script_event(WorkerScriptMsg::Common(msg));
} }
}
trait PrivateDedicatedWorkerGlobalScopeHelpers {
fn handle_script_event(self, msg: WorkerScriptMsg);
fn dispatch_error_to_worker(self, &ErrorEvent);
fn receive_event(self) -> Result<MixedMessage, RecvError>;
fn handle_event(self, event: MixedMessage);
}
impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalScope {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn receive_event(self) -> Result<MixedMessage, RecvError> { fn receive_event(&self) -> Result<MixedMessage, RecvError> {
let scope = WorkerGlobalScopeCast::from_ref(self); let scope = WorkerGlobalScopeCast::from_ref(self);
let worker_port = &self.receiver; let worker_port = &self.receiver;
let devtools_port = scope.from_devtools_receiver(); let devtools_port = scope.from_devtools_receiver();
@ -312,7 +290,7 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalS
} }
} }
fn handle_script_event(self, msg: WorkerScriptMsg) { fn handle_script_event(&self, msg: WorkerScriptMsg) {
match msg { match msg {
WorkerScriptMsg::DOMMessage(data) => { WorkerScriptMsg::DOMMessage(data) => {
let scope = WorkerGlobalScopeCast::from_ref(self); let scope = WorkerGlobalScopeCast::from_ref(self);
@ -323,7 +301,7 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalS
data.read(GlobalRef::Worker(scope), message.handle_mut()); data.read(GlobalRef::Worker(scope), message.handle_mut());
MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle()); MessageEvent::dispatch_jsval(target, GlobalRef::Worker(scope), message.handle());
}, },
WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(runnable)) => { WorkerScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => {
runnable.handler() runnable.handler()
}, },
WorkerScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) => { WorkerScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) => {
@ -347,7 +325,7 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalS
} }
} }
fn handle_event(self, event: MixedMessage) { fn handle_event(&self, event: MixedMessage) {
match event { match event {
MixedMessage::FromDevtools(msg) => { MixedMessage::FromDevtools(msg) => {
let global_ref = GlobalRef::Worker(WorkerGlobalScopeCast::from_ref(self)); let global_ref = GlobalRef::Worker(WorkerGlobalScopeCast::from_ref(self));
@ -367,28 +345,19 @@ impl<'a> PrivateDedicatedWorkerGlobalScopeHelpers for &'a DedicatedWorkerGlobalS
}, },
} }
} }
fn dispatch_error_to_worker(self, errorevent: &ErrorEvent) {
let msg = errorevent.Message();
let file_name = errorevent.Filename();
let line_num = errorevent.Lineno();
let col_num = errorevent.Colno();
let worker = self.worker.borrow().as_ref().unwrap().clone();
self.parent_sender.send(CommonScriptMsg::RunnableMsg(
box WorkerErrorHandler::new(worker, msg, file_name, line_num, col_num))).unwrap();
}
} }
impl<'a> DedicatedWorkerGlobalScopeMethods for &'a DedicatedWorkerGlobalScope { impl DedicatedWorkerGlobalScopeMethods for DedicatedWorkerGlobalScope {
// https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage // https://html.spec.whatwg.org/multipage/#dom-dedicatedworkerglobalscope-postmessage
fn PostMessage(self, cx: *mut JSContext, message: HandleValue) -> ErrorResult { fn PostMessage(&self, cx: *mut JSContext, message: HandleValue) -> ErrorResult {
let data = try!(StructuredCloneData::write(cx, message)); let data = try!(StructuredCloneData::write(cx, message));
let worker = self.worker.borrow().as_ref().unwrap().clone(); let worker = self.worker.borrow().as_ref().unwrap().clone();
self.parent_sender.send(CommonScriptMsg::RunnableMsg( self.parent_sender.send(CommonScriptMsg::RunnableMsg(WorkerEvent,
box WorkerMessageHandler::new(worker, data))).unwrap(); box WorkerMessageHandler::new(worker, data))).unwrap();
Ok(()) Ok(())
} }
// https://html.spec.whatwg.org/multipage/#handler-dedicatedworkerglobalscope-onmessage
event_handler!(message, GetOnmessage, SetOnmessage); event_handler!(message, GetOnmessage, SetOnmessage);
} }

File diff suppressed because it is too large Load diff

View file

@ -15,13 +15,12 @@ use dom::document::Document;
use dom::element::Element; use dom::element::Element;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlcollection::HTMLCollection; use dom::htmlcollection::HTMLCollection;
use dom::node::{Node, NodeHelpers, NodeTypeId, window_from_node}; use dom::node::{Node, NodeTypeId, window_from_node};
use dom::nodelist::NodeList; use dom::nodelist::NodeList;
use util::str::DOMString; use util::str::DOMString;
// https://dom.spec.whatwg.org/#documentfragment // https://dom.spec.whatwg.org/#documentfragment
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DocumentFragment { pub struct DocumentFragment {
node: Node, node: Node,
} }
@ -52,48 +51,47 @@ impl DocumentFragment {
} }
} }
impl<'a> DocumentFragmentMethods for &'a DocumentFragment { impl DocumentFragmentMethods for DocumentFragment {
// https://dom.spec.whatwg.org/#dom-parentnode-children // https://dom.spec.whatwg.org/#dom-parentnode-children
fn Children(self) -> Root<HTMLCollection> { fn Children(&self) -> Root<HTMLCollection> {
let window = window_from_node(self); let window = window_from_node(self);
HTMLCollection::children(window.r(), NodeCast::from_ref(self)) HTMLCollection::children(window.r(), NodeCast::from_ref(self))
} }
// https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild // https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild
fn GetFirstElementChild(self) -> Option<Root<Element>> { fn GetFirstElementChild(&self) -> Option<Root<Element>> {
NodeCast::from_ref(self).child_elements().next() NodeCast::from_ref(self).child_elements().next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild // https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
fn GetLastElementChild(self) -> Option<Root<Element>> { fn GetLastElementChild(&self) -> Option<Root<Element>> {
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next() NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-childelementcount // https://dom.spec.whatwg.org/#dom-parentnode-childelementcount
fn ChildElementCount(self) -> u32 { fn ChildElementCount(&self) -> u32 {
NodeCast::from_ref(self).child_elements().count() as u32 NodeCast::from_ref(self).child_elements().count() as u32
} }
// https://dom.spec.whatwg.org/#dom-parentnode-prepend // https://dom.spec.whatwg.org/#dom-parentnode-prepend
fn Prepend(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn Prepend(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).prepend(nodes) NodeCast::from_ref(self).prepend(nodes)
} }
// https://dom.spec.whatwg.org/#dom-parentnode-append // https://dom.spec.whatwg.org/#dom-parentnode-append
fn Append(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn Append(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).append(nodes) NodeCast::from_ref(self).append(nodes)
} }
// https://dom.spec.whatwg.org/#dom-parentnode-queryselector // https://dom.spec.whatwg.org/#dom-parentnode-queryselector
fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Root<Element>>> { fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
let root = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
root.query_selector(selectors) root.query_selector(selectors)
} }
// https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall // https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Root<NodeList>> { fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<Root<NodeList>> {
let root = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
root.query_selector_all(selectors) root.query_selector_all(selectors)
} }
} }

View file

@ -10,7 +10,7 @@ use dom::bindings::error::ErrorResult;
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::node::{Node, NodeHelpers, NodeTypeId}; use dom::node::{Node, NodeTypeId};
use util::str::DOMString; use util::str::DOMString;
use std::borrow::ToOwned; use std::borrow::ToOwned;
@ -18,7 +18,6 @@ use std::borrow::ToOwned;
// https://dom.spec.whatwg.org/#documenttype // https://dom.spec.whatwg.org/#documenttype
/// The `DOCTYPE` tag. /// The `DOCTYPE` tag.
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DocumentType { pub struct DocumentType {
node: Node, node: Node,
name: DOMString, name: DOMString,
@ -74,41 +73,40 @@ impl DocumentType {
} }
} }
impl<'a> DocumentTypeMethods for &'a DocumentType { impl DocumentTypeMethods for DocumentType {
// https://dom.spec.whatwg.org/#dom-documenttype-name // https://dom.spec.whatwg.org/#dom-documenttype-name
fn Name(self) -> DOMString { fn Name(&self) -> DOMString {
self.name.clone() self.name.clone()
} }
// https://dom.spec.whatwg.org/#dom-documenttype-publicid // https://dom.spec.whatwg.org/#dom-documenttype-publicid
fn PublicId(self) -> DOMString { fn PublicId(&self) -> DOMString {
self.public_id.clone() self.public_id.clone()
} }
// https://dom.spec.whatwg.org/#dom-documenttype-systemid // https://dom.spec.whatwg.org/#dom-documenttype-systemid
fn SystemId(self) -> DOMString { fn SystemId(&self) -> DOMString {
self.system_id.clone() self.system_id.clone()
} }
// https://dom.spec.whatwg.org/#dom-childnode-before // https://dom.spec.whatwg.org/#dom-childnode-before
fn Before(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn Before(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).before(nodes) NodeCast::from_ref(self).before(nodes)
} }
// https://dom.spec.whatwg.org/#dom-childnode-after // https://dom.spec.whatwg.org/#dom-childnode-after
fn After(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn After(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).after(nodes) NodeCast::from_ref(self).after(nodes)
} }
// https://dom.spec.whatwg.org/#dom-childnode-replacewith // https://dom.spec.whatwg.org/#dom-childnode-replacewith
fn ReplaceWith(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn ReplaceWith(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).replace_with(nodes) NodeCast::from_ref(self).replace_with(nodes)
} }
// https://dom.spec.whatwg.org/#dom-childnode-remove // https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(self) { fn Remove(&self) {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.remove_self(); node.remove_self();
} }
} }

View file

@ -41,7 +41,6 @@ pub enum DOMErrorName {
} }
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DOMException { pub struct DOMException {
reflector_: Reflector, reflector_: Reflector,
code: DOMErrorName, code: DOMErrorName,
@ -60,9 +59,9 @@ impl DOMException {
} }
} }
impl<'a> DOMExceptionMethods for &'a DOMException { impl DOMExceptionMethods for DOMException {
// https://heycam.github.io/webidl/#dfn-DOMException // https://heycam.github.io/webidl/#dfn-DOMException
fn Code(self) -> u16 { fn Code(&self) -> u16 {
match self.code { match self.code {
// https://heycam.github.io/webidl/#dfn-throw // https://heycam.github.io/webidl/#dfn-throw
DOMErrorName::EncodingError => 0, DOMErrorName::EncodingError => 0,
@ -71,12 +70,12 @@ impl<'a> DOMExceptionMethods for &'a DOMException {
} }
// https://heycam.github.io/webidl/#idl-DOMException-error-names // https://heycam.github.io/webidl/#idl-DOMException-error-names
fn Name(self) -> DOMString { fn Name(&self) -> DOMString {
format!("{:?}", self.code) format!("{:?}", self.code)
} }
// https://heycam.github.io/webidl/#error-names // https://heycam.github.io/webidl/#error-names
fn Message(self) -> DOMString { fn Message(&self) -> DOMString {
let message = match self.code { let message = match self.code {
DOMErrorName::IndexSizeError => "The index is not in the allowed range.", DOMErrorName::IndexSizeError => "The index is not in the allowed range.",
DOMErrorName::HierarchyRequestError => "The operation would yield an incorrect node tree.", DOMErrorName::HierarchyRequestError => "The operation would yield an incorrect node tree.",

View file

@ -14,7 +14,7 @@ use dom::bindings::js::{JS, Root};
use dom::bindings::utils::validate_qualified_name; use dom::bindings::utils::validate_qualified_name;
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::document::DocumentSource; use dom::document::DocumentSource;
use dom::document::{Document, DocumentHelpers, IsHTMLDocument}; use dom::document::{Document, IsHTMLDocument};
use dom::documenttype::DocumentType; use dom::documenttype::DocumentType;
use dom::htmlbodyelement::HTMLBodyElement; use dom::htmlbodyelement::HTMLBodyElement;
use dom::htmlheadelement::HTMLHeadElement; use dom::htmlheadelement::HTMLHeadElement;
@ -27,7 +27,6 @@ use std::borrow::ToOwned;
// https://dom.spec.whatwg.org/#domimplementation // https://dom.spec.whatwg.org/#domimplementation
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DOMImplementation { pub struct DOMImplementation {
reflector_: Reflector, reflector_: Reflector,
document: JS<Document>, document: JS<Document>,
@ -50,9 +49,9 @@ impl DOMImplementation {
} }
// https://dom.spec.whatwg.org/#domimplementation // https://dom.spec.whatwg.org/#domimplementation
impl<'a> DOMImplementationMethods for &'a DOMImplementation { impl DOMImplementationMethods for DOMImplementation {
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype // https://dom.spec.whatwg.org/#dom-domimplementation-createdocumenttype
fn CreateDocumentType(self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString) fn CreateDocumentType(&self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString)
-> Fallible<Root<DocumentType>> { -> Fallible<Root<DocumentType>> {
try!(validate_qualified_name(&qualified_name)); try!(validate_qualified_name(&qualified_name));
let document = self.document.root(); let document = self.document.root();
@ -60,7 +59,7 @@ impl<'a> DOMImplementationMethods for &'a DOMImplementation {
} }
// https://dom.spec.whatwg.org/#dom-domimplementation-createdocument // https://dom.spec.whatwg.org/#dom-domimplementation-createdocument
fn CreateDocument(self, namespace: Option<DOMString>, qname: DOMString, fn CreateDocument(&self, namespace: Option<DOMString>, qname: DOMString,
maybe_doctype: Option<&DocumentType>) -> Fallible<Root<Document>> { maybe_doctype: Option<&DocumentType>) -> Fallible<Root<Document>> {
let doc = self.document.root(); let doc = self.document.root();
let doc = doc.r(); let doc = doc.r();
@ -109,7 +108,7 @@ impl<'a> DOMImplementationMethods for &'a DOMImplementation {
} }
// https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
fn CreateHTMLDocument(self, title: Option<DOMString>) -> Root<Document> { fn CreateHTMLDocument(&self, title: Option<DOMString>) -> Root<Document> {
let document = self.document.root(); let document = self.document.root();
let document = document.r(); let document = document.r();
let win = document.window(); let win = document.window();
@ -168,7 +167,7 @@ impl<'a> DOMImplementationMethods for &'a DOMImplementation {
} }
// https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature // https://dom.spec.whatwg.org/#dom-domimplementation-hasfeature
fn HasFeature(self) -> bool { fn HasFeature(&self) -> bool {
true true
} }
} }

View file

@ -13,15 +13,14 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::document::DocumentSource; use dom::document::DocumentSource;
use dom::document::{Document, DocumentHelpers, IsHTMLDocument}; use dom::document::{Document, IsHTMLDocument};
use dom::window::{Window, WindowHelpers}; use dom::window::Window;
use parse::html::{ParseContext, parse_html}; use parse::html::{ParseContext, parse_html};
use util::str::DOMString; use util::str::DOMString;
use std::borrow::ToOwned; use std::borrow::ToOwned;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DOMParser { pub struct DOMParser {
reflector_: Reflector, reflector_: Reflector,
window: JS<Window>, //XXXjdm Document instead? window: JS<Window>, //XXXjdm Document instead?
@ -45,9 +44,9 @@ impl DOMParser {
} }
} }
impl<'a> DOMParserMethods for &'a DOMParser { impl DOMParserMethods for DOMParser {
// https://domparsing.spec.whatwg.org/#the-domparser-interface // https://domparsing.spec.whatwg.org/#the-domparser-interface
fn ParseFromString(self, fn ParseFromString(&self,
s: DOMString, s: DOMString,
ty: DOMParserBinding::SupportedType) ty: DOMParserBinding::SupportedType)
-> Fallible<Root<Document>> { -> Fallible<Root<Document>> {
@ -81,4 +80,3 @@ impl<'a> DOMParserMethods for &'a DOMParser {
} }
} }
} }

View file

@ -12,7 +12,6 @@ use dom::dompointreadonly::{DOMPointReadOnly, DOMPointWriteMethods};
// http://dev.w3.org/fxtf/geometry/Overview.html#dompoint // http://dev.w3.org/fxtf/geometry/Overview.html#dompoint
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DOMPoint { pub struct DOMPoint {
point: DOMPointReadOnly point: DOMPointReadOnly
} }
@ -34,45 +33,44 @@ impl DOMPoint {
} }
} }
impl<'a> DOMPointMethods for &'a DOMPoint { impl DOMPointMethods for DOMPoint {
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-x // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-x
fn X(self) -> f64 { fn X(&self) -> f64 {
self.point.X() self.point.X()
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-x // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-x
fn SetX(self, value: f64) { fn SetX(&self, value: f64) {
self.point.SetX(value); self.point.SetX(value);
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-y // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-y
fn Y(self) -> f64 { fn Y(&self) -> f64 {
self.point.Y() self.point.Y()
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-y // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-y
fn SetY(self, value: f64) { fn SetY(&self, value: f64) {
self.point.SetY(value); self.point.SetY(value);
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-z // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-z
fn Z(self) -> f64 { fn Z(&self) -> f64 {
self.point.Z() self.point.Z()
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-z // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-z
fn SetZ(self, value: f64) { fn SetZ(&self, value: f64) {
self.point.SetZ(value); self.point.SetZ(value);
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-w // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-w
fn W(self) -> f64 { fn W(&self) -> f64 {
self.point.W() self.point.W()
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-w // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-w
fn SetW(self, value: f64) { fn SetW(&self, value: f64) {
self.point.SetW(value); self.point.SetW(value);
} }
} }

View file

@ -11,7 +11,6 @@ use std::cell::Cell;
// http://dev.w3.org/fxtf/geometry/Overview.html#dompointreadonly // http://dev.w3.org/fxtf/geometry/Overview.html#dompointreadonly
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DOMPointReadOnly { pub struct DOMPointReadOnly {
reflector_: Reflector, reflector_: Reflector,
x: Cell<f64>, x: Cell<f64>,
@ -41,49 +40,49 @@ impl DOMPointReadOnly {
} }
} }
impl<'a> DOMPointReadOnlyMethods for &'a DOMPointReadOnly { impl DOMPointReadOnlyMethods for DOMPointReadOnly {
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-x // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-x
fn X(self) -> f64 { fn X(&self) -> f64 {
self.x.get() self.x.get()
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-y // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-y
fn Y(self) -> f64 { fn Y(&self) -> f64 {
self.y.get() self.y.get()
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-z // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-z
fn Z(self) -> f64 { fn Z(&self) -> f64 {
self.z.get() self.z.get()
} }
// https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-w // https://dev.w3.org/fxtf/geometry/Overview.html#dom-dompointreadonly-w
fn W(self) -> f64 { fn W(&self) -> f64 {
self.w.get() self.w.get()
} }
} }
pub trait DOMPointWriteMethods { pub trait DOMPointWriteMethods {
fn SetX(self, value: f64); fn SetX(&self, value: f64);
fn SetY(self, value: f64); fn SetY(&self, value: f64);
fn SetZ(self, value: f64); fn SetZ(&self, value: f64);
fn SetW(self, value: f64); fn SetW(&self, value: f64);
} }
impl<'a> DOMPointWriteMethods for &'a DOMPointReadOnly { impl DOMPointWriteMethods for DOMPointReadOnly {
fn SetX(self, value: f64) { fn SetX(&self, value: f64) {
self.x.set(value); self.x.set(value);
} }
fn SetY(self, value: f64) { fn SetY(&self, value: f64) {
self.y.set(value); self.y.set(value);
} }
fn SetZ(self, value: f64) { fn SetZ(&self, value: f64) {
self.z.set(value); self.z.set(value);
} }
fn SetW(self, value: f64) { fn SetW(&self, value: f64) {
self.w.set(value); self.w.set(value);
} }
} }

View file

@ -12,7 +12,6 @@ use dom::window::Window;
use util::geometry::Au; use util::geometry::Au;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DOMRect { pub struct DOMRect {
reflector_: Reflector, reflector_: Reflector,
top: f32, top: f32,
@ -41,37 +40,36 @@ impl DOMRect {
} }
} }
impl<'a> DOMRectMethods for &'a DOMRect { impl DOMRectMethods for DOMRect {
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-top // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-top
fn Top(self) -> Finite<f32> { fn Top(&self) -> Finite<f32> {
Finite::wrap(self.top) Finite::wrap(self.top)
} }
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-bottom // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-bottom
fn Bottom(self) -> Finite<f32> { fn Bottom(&self) -> Finite<f32> {
Finite::wrap(self.bottom) Finite::wrap(self.bottom)
} }
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-left // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-left
fn Left(self) -> Finite<f32> { fn Left(&self) -> Finite<f32> {
Finite::wrap(self.left) Finite::wrap(self.left)
} }
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-right // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-right
fn Right(self) -> Finite<f32> { fn Right(&self) -> Finite<f32> {
Finite::wrap(self.right) Finite::wrap(self.right)
} }
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-width // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-width
fn Width(self) -> Finite<f32> { fn Width(&self) -> Finite<f32> {
let result = (self.right - self.left).abs(); let result = (self.right - self.left).abs();
Finite::wrap(result) Finite::wrap(result)
} }
// https://drafts.fxtf.org/geometry/#dom-domrectreadonly-height // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-height
fn Height(self) -> Finite<f32> { fn Height(&self) -> Finite<f32> {
let result = (self.bottom - self.top).abs(); let result = (self.bottom - self.top).abs();
Finite::wrap(result) Finite::wrap(result)
} }
} }

View file

@ -11,7 +11,6 @@ use dom::domrect::DOMRect;
use dom::window::Window; use dom::window::Window;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DOMRectList { pub struct DOMRectList {
reflector_: Reflector, reflector_: Reflector,
rects: Vec<JS<DOMRect>>, rects: Vec<JS<DOMRect>>,
@ -33,14 +32,14 @@ impl DOMRectList {
} }
} }
impl<'a> DOMRectListMethods for &'a DOMRectList { impl DOMRectListMethods for DOMRectList {
// https://drafts.fxtf.org/geometry/#dom-domrectlist-length // https://drafts.fxtf.org/geometry/#dom-domrectlist-length
fn Length(self) -> u32 { fn Length(&self) -> u32 {
self.rects.len() as u32 self.rects.len() as u32
} }
// https://drafts.fxtf.org/geometry/#dom-domrectlist-item // https://drafts.fxtf.org/geometry/#dom-domrectlist-item
fn Item(self, index: u32) -> Option<Root<DOMRect>> { fn Item(&self, index: u32) -> Option<Root<DOMRect>> {
let rects = &self.rects; let rects = &self.rects;
if index < rects.len() as u32 { if index < rects.len() as u32 {
Some(rects[index as usize].root()) Some(rects[index as usize].root())
@ -50,9 +49,8 @@ impl<'a> DOMRectListMethods for &'a DOMRectList {
} }
// check-tidy: no specs after this line // check-tidy: no specs after this line
fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<Root<DOMRect>> { fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<DOMRect>> {
*found = index < self.rects.len() as u32; *found = index < self.rects.len() as u32;
self.Item(index) self.Item(index)
} }
} }

View file

@ -8,12 +8,11 @@ use dom::bindings::error::ErrorResult;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::htmlelement::{HTMLElement, HTMLElementCustomAttributeHelpers}; use dom::htmlelement::HTMLElement;
use dom::node::window_from_node; use dom::node::window_from_node;
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DOMStringMap { pub struct DOMStringMap {
reflector_: Reflector, reflector_: Reflector,
element: JS<HTMLElement>, element: JS<HTMLElement>,
@ -35,26 +34,26 @@ impl DOMStringMap {
} }
// https://html.spec.whatwg.org/#domstringmap // https://html.spec.whatwg.org/#domstringmap
impl<'a> DOMStringMapMethods for &'a DOMStringMap { impl DOMStringMapMethods for DOMStringMap {
// https://html.spec.whatwg.org/multipage/#dom-domstringmap-additem // https://html.spec.whatwg.org/multipage/#dom-domstringmap-additem
fn NamedCreator(self, name: DOMString, value: DOMString) -> ErrorResult { fn NamedCreator(&self, name: DOMString, value: DOMString) -> ErrorResult {
self.NamedSetter(name, value) self.NamedSetter(name, value)
} }
// https://html.spec.whatwg.org/multipage/#dom-domstringmap-removeitem // https://html.spec.whatwg.org/multipage/#dom-domstringmap-removeitem
fn NamedDeleter(self, name: DOMString) { fn NamedDeleter(&self, name: DOMString) {
let element = self.element.root(); let element = self.element.root();
element.r().delete_custom_attr(name) element.r().delete_custom_attr(name)
} }
// https://html.spec.whatwg.org/multipage/#dom-domstringmap-setitem // https://html.spec.whatwg.org/multipage/#dom-domstringmap-setitem
fn NamedSetter(self, name: DOMString, value: DOMString) -> ErrorResult { fn NamedSetter(&self, name: DOMString, value: DOMString) -> ErrorResult {
let element = self.element.root(); let element = self.element.root();
element.r().set_custom_attr(name, value) element.r().set_custom_attr(name, value)
} }
// https://html.spec.whatwg.org/multipage/#dom-domstringmap-nameditem // https://html.spec.whatwg.org/multipage/#dom-domstringmap-nameditem
fn NamedGetter(self, name: DOMString, found: &mut bool) -> DOMString { fn NamedGetter(&self, name: DOMString, found: &mut bool) -> DOMString {
let element = self.element.root(); let element = self.element.root();
match element.r().get_custom_attr(name) { match element.r().get_custom_attr(name) {
Some(value) => { Some(value) => {
@ -69,7 +68,7 @@ impl<'a> DOMStringMapMethods for &'a DOMStringMap {
} }
// https://html.spec.whatwg.org/multipage/#domstringmap // https://html.spec.whatwg.org/multipage/#domstringmap
fn SupportedPropertyNames(self) -> Vec<DOMString> { fn SupportedPropertyNames(&self) -> Vec<DOMString> {
// FIXME: unimplemented (https://github.com/servo/servo/issues/7273) // FIXME: unimplemented (https://github.com/servo/servo/issues/7273)
vec![] vec![]
} }

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::attr::{Attr, AttrHelpers}; use dom::attr::Attr;
use dom::bindings::codegen::Bindings::DOMTokenListBinding; use dom::bindings::codegen::Bindings::DOMTokenListBinding;
use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods; use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods;
use dom::bindings::error::Error::{InvalidCharacter, Syntax}; use dom::bindings::error::Error::{InvalidCharacter, Syntax};
@ -10,7 +10,7 @@ use dom::bindings::error::{ErrorResult, Fallible};
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root}; use dom::bindings::js::{JS, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers}; use dom::element::Element;
use dom::node::window_from_node; use dom::node::window_from_node;
use string_cache::Atom; use string_cache::Atom;
@ -19,7 +19,6 @@ use util::str::{DOMString, HTML_SPACE_CHARACTERS, str_join};
use std::borrow::ToOwned; use std::borrow::ToOwned;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct DOMTokenList { pub struct DOMTokenList {
reflector_: Reflector, reflector_: Reflector,
element: JS<Element>, element: JS<Element>,
@ -41,20 +40,13 @@ impl DOMTokenList {
GlobalRef::Window(window.r()), GlobalRef::Window(window.r()),
DOMTokenListBinding::Wrap) DOMTokenListBinding::Wrap)
} }
}
trait PrivateDOMTokenListHelpers { fn attribute(&self) -> Option<Root<Attr>> {
fn attribute(self) -> Option<Root<Attr>>;
fn check_token_exceptions(self, token: &str) -> Fallible<Atom>;
}
impl<'a> PrivateDOMTokenListHelpers for &'a DOMTokenList {
fn attribute(self) -> Option<Root<Attr>> {
let element = self.element.root(); let element = self.element.root();
element.r().get_attribute(&ns!(""), &self.local_name) element.r().get_attribute(&ns!(""), &self.local_name)
} }
fn check_token_exceptions(self, token: &str) -> Fallible<Atom> { fn check_token_exceptions(&self, token: &str) -> Fallible<Atom> {
match token { match token {
"" => Err(Syntax), "" => Err(Syntax),
slice if slice.find(HTML_SPACE_CHARACTERS).is_some() => Err(InvalidCharacter), slice if slice.find(HTML_SPACE_CHARACTERS).is_some() => Err(InvalidCharacter),
@ -64,9 +56,9 @@ impl<'a> PrivateDOMTokenListHelpers for &'a DOMTokenList {
} }
// https://dom.spec.whatwg.org/#domtokenlist // https://dom.spec.whatwg.org/#domtokenlist
impl<'a> DOMTokenListMethods for &'a DOMTokenList { impl DOMTokenListMethods for DOMTokenList {
// https://dom.spec.whatwg.org/#dom-domtokenlist-length // https://dom.spec.whatwg.org/#dom-domtokenlist-length
fn Length(self) -> u32 { fn Length(&self) -> u32 {
self.attribute().map(|attr| { self.attribute().map(|attr| {
let attr = attr.r(); let attr = attr.r();
attr.value().tokens().map(|tokens| tokens.len()).unwrap_or(0) attr.value().tokens().map(|tokens| tokens.len()).unwrap_or(0)
@ -74,7 +66,7 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
} }
// https://dom.spec.whatwg.org/#dom-domtokenlist-item // https://dom.spec.whatwg.org/#dom-domtokenlist-item
fn Item(self, index: u32) -> Option<DOMString> { fn Item(&self, index: u32) -> Option<DOMString> {
self.attribute().and_then(|attr| { self.attribute().and_then(|attr| {
let attr = attr.r(); let attr = attr.r();
attr.value().tokens().and_then(|tokens| { attr.value().tokens().and_then(|tokens| {
@ -84,7 +76,7 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
} }
// https://dom.spec.whatwg.org/#dom-domtokenlist-contains // https://dom.spec.whatwg.org/#dom-domtokenlist-contains
fn Contains(self, token: DOMString) -> Fallible<bool> { fn Contains(&self, token: DOMString) -> Fallible<bool> {
self.check_token_exceptions(&token).map(|token| { self.check_token_exceptions(&token).map(|token| {
self.attribute().map(|attr| { self.attribute().map(|attr| {
let attr = attr.r(); let attr = attr.r();
@ -98,7 +90,7 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
} }
// https://dom.spec.whatwg.org/#dom-domtokenlist-add // https://dom.spec.whatwg.org/#dom-domtokenlist-add
fn Add(self, tokens: Vec<DOMString>) -> ErrorResult { fn Add(&self, tokens: Vec<DOMString>) -> ErrorResult {
let element = self.element.root(); let element = self.element.root();
let mut atoms = element.r().get_tokenlist_attribute(&self.local_name); let mut atoms = element.r().get_tokenlist_attribute(&self.local_name);
for token in &tokens { for token in &tokens {
@ -112,7 +104,7 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
} }
// https://dom.spec.whatwg.org/#dom-domtokenlist-remove // https://dom.spec.whatwg.org/#dom-domtokenlist-remove
fn Remove(self, tokens: Vec<DOMString>) -> ErrorResult { fn Remove(&self, tokens: Vec<DOMString>) -> ErrorResult {
let element = self.element.root(); let element = self.element.root();
let mut atoms = element.r().get_tokenlist_attribute(&self.local_name); let mut atoms = element.r().get_tokenlist_attribute(&self.local_name);
for token in &tokens { for token in &tokens {
@ -126,7 +118,7 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
} }
// https://dom.spec.whatwg.org/#dom-domtokenlist-toggle // https://dom.spec.whatwg.org/#dom-domtokenlist-toggle
fn Toggle(self, token: DOMString, force: Option<bool>) -> Fallible<bool> { fn Toggle(&self, token: DOMString, force: Option<bool>) -> Fallible<bool> {
let element = self.element.root(); let element = self.element.root();
let mut atoms = element.r().get_tokenlist_attribute(&self.local_name); let mut atoms = element.r().get_tokenlist_attribute(&self.local_name);
let token = try!(self.check_token_exceptions(&token)); let token = try!(self.check_token_exceptions(&token));
@ -151,13 +143,13 @@ impl<'a> DOMTokenListMethods for &'a DOMTokenList {
} }
// https://dom.spec.whatwg.org/#stringification-behavior // https://dom.spec.whatwg.org/#stringification-behavior
fn Stringifier(self) -> DOMString { fn Stringifier(&self) -> DOMString {
let tokenlist = self.element.root().r().get_tokenlist_attribute(&self.local_name); let tokenlist = self.element.root().r().get_tokenlist_attribute(&self.local_name);
str_join(&tokenlist, "\x20") str_join(&tokenlist, "\x20")
} }
// check-tidy: no specs after this line // check-tidy: no specs after this line
fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<DOMString> { fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<DOMString> {
let item = self.Item(index); let item = self.Item(index);
*found = item.is_some(); *found = item.is_some();
item item

View file

@ -6,7 +6,7 @@
use dom::activation::Activatable; use dom::activation::Activatable;
use dom::attr::AttrValue; use dom::attr::AttrValue;
use dom::attr::{Attr, AttrSettingType, AttrHelpers, AttrHelpersForLayout}; use dom::attr::{Attr, AttrSettingType, AttrHelpersForLayout};
use dom::bindings::cell::DOMRefCell; use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::Bindings::ElementBinding; use dom::bindings::codegen::Bindings::ElementBinding;
@ -35,27 +35,26 @@ use dom::bindings::js::{Root, RootedReference};
use dom::bindings::trace::RootedVec; use dom::bindings::trace::RootedVec;
use dom::bindings::utils::XMLName::InvalidXMLName; use dom::bindings::utils::XMLName::InvalidXMLName;
use dom::bindings::utils::{namespace_from_domstring, xml_name_type, validate_and_extract}; use dom::bindings::utils::{namespace_from_domstring, xml_name_type, validate_and_extract};
use dom::characterdata::CharacterDataHelpers;
use dom::create::create_element; use dom::create::create_element;
use dom::document::{Document, DocumentHelpers, LayoutDocumentHelpers}; use dom::document::{Document, LayoutDocumentHelpers};
use dom::domrect::DOMRect; use dom::domrect::DOMRect;
use dom::domrectlist::DOMRectList; use dom::domrectlist::DOMRectList;
use dom::domtokenlist::DOMTokenList; use dom::domtokenlist::DOMTokenList;
use dom::event::{Event, EventHelpers}; use dom::event::Event;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlbodyelement::{HTMLBodyElement, HTMLBodyElementHelpers}; use dom::htmlbodyelement::HTMLBodyElement;
use dom::htmlcollection::HTMLCollection; use dom::htmlcollection::HTMLCollection;
use dom::htmlelement::HTMLElementTypeId; use dom::htmlelement::HTMLElementTypeId;
use dom::htmlfontelement::{HTMLFontElement, HTMLFontElementHelpers}; use dom::htmlfontelement::HTMLFontElement;
use dom::htmliframeelement::{HTMLIFrameElement, RawHTMLIFrameElementHelpers}; use dom::htmliframeelement::HTMLIFrameElement;
use dom::htmlinputelement::{HTMLInputElement, RawLayoutHTMLInputElementHelpers, HTMLInputElementHelpers}; use dom::htmlinputelement::{HTMLInputElement, RawLayoutHTMLInputElementHelpers};
use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementHelpers}; use dom::htmltablecellelement::HTMLTableCellElement;
use dom::htmltableelement::{HTMLTableElement, HTMLTableElementHelpers}; use dom::htmltableelement::HTMLTableElement;
use dom::htmltablerowelement::{HTMLTableRowElement, HTMLTableRowElementHelpers}; use dom::htmltablerowelement::HTMLTableRowElement;
use dom::htmltablesectionelement::{HTMLTableSectionElement, HTMLTableSectionElementHelpers}; use dom::htmltablesectionelement::HTMLTableSectionElement;
use dom::htmltextareaelement::{HTMLTextAreaElement, RawLayoutHTMLTextAreaElementHelpers}; use dom::htmltextareaelement::{HTMLTextAreaElement, RawLayoutHTMLTextAreaElementHelpers};
use dom::namednodemap::NamedNodeMap; use dom::namednodemap::NamedNodeMap;
use dom::node::{CLICK_IN_PROGRESS, LayoutNodeHelpers, Node, NodeHelpers, NodeTypeId, SEQUENTIALLY_FOCUSABLE}; use dom::node::{CLICK_IN_PROGRESS, LayoutNodeHelpers, Node, NodeTypeId, SEQUENTIALLY_FOCUSABLE};
use dom::node::{document_from_node, NodeDamage}; use dom::node::{document_from_node, NodeDamage};
use dom::node::{window_from_node}; use dom::node::{window_from_node};
use dom::nodelist::NodeList; use dom::nodelist::NodeList;
@ -92,7 +91,6 @@ use std::mem;
use std::sync::Arc; use std::sync::Arc;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct Element { pub struct Element {
node: Node, node: Node,
local_name: Atom, local_name: Atom,
@ -571,38 +569,18 @@ pub enum StylePriority {
Normal, Normal,
} }
pub trait ElementHelpers<'a> {
fn html_element_in_html_document(self) -> bool;
fn local_name(self) -> &'a Atom;
fn parsed_name(self, name: DOMString) -> Atom;
fn namespace(self) -> &'a Namespace;
fn prefix(self) -> &'a Option<DOMString>;
fn attrs(&self) -> Ref<Vec<JS<Attr>>>;
fn attrs_mut(&self) -> RefMut<Vec<JS<Attr>>>;
fn style_attribute(self) -> &'a DOMRefCell<Option<PropertyDeclarationBlock>>;
fn summarize(self) -> Vec<AttrInfo>;
fn is_void(self) -> bool;
fn remove_inline_style_property(self, property: &str);
fn update_inline_style(self, property_decl: PropertyDeclaration, style_priority: StylePriority);
fn set_inline_style_property_priority(self, properties: &[&str], style_priority: StylePriority);
fn get_inline_style_declaration(self, property: &Atom) -> Option<Ref<'a, PropertyDeclaration>>;
fn get_important_inline_style_declaration(self, property: &Atom) -> Option<Ref<'a, PropertyDeclaration>>;
fn serialize(self, traversal_scope: TraversalScope) -> Fallible<DOMString>;
fn get_root_element(self) -> Root<Element>;
fn lookup_prefix(self, namespace: Namespace) -> Option<DOMString>;
}
impl<'a> ElementHelpers<'a> for &'a Element { impl Element {
fn html_element_in_html_document(self) -> bool { pub fn html_element_in_html_document(&self) -> bool {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
self.namespace == ns!(HTML) && node.is_in_html_doc() self.namespace == ns!(HTML) && node.is_in_html_doc()
} }
fn local_name(self) -> &'a Atom { pub fn local_name(&self) -> &Atom {
&self.local_name &self.local_name
} }
fn parsed_name(self, name: DOMString) -> Atom { pub fn parsed_name(&self, name: DOMString) -> Atom {
if self.html_element_in_html_document() { if self.html_element_in_html_document() {
Atom::from_slice(&name.to_ascii_lowercase()) Atom::from_slice(&name.to_ascii_lowercase())
} else { } else {
@ -610,27 +588,27 @@ impl<'a> ElementHelpers<'a> for &'a Element {
} }
} }
fn namespace(self) -> &'a Namespace { pub fn namespace(&self) -> &Namespace {
&self.namespace &self.namespace
} }
fn prefix(self) -> &'a Option<DOMString> { pub fn prefix(&self) -> &Option<DOMString> {
&self.prefix &self.prefix
} }
fn attrs(&self) -> Ref<Vec<JS<Attr>>> { pub fn attrs(&self) -> Ref<Vec<JS<Attr>>> {
self.attrs.borrow() self.attrs.borrow()
} }
fn attrs_mut(&self) -> RefMut<Vec<JS<Attr>>> { pub fn attrs_mut(&self) -> RefMut<Vec<JS<Attr>>> {
self.attrs.borrow_mut() self.attrs.borrow_mut()
} }
fn style_attribute(self) -> &'a DOMRefCell<Option<PropertyDeclarationBlock>> { pub fn style_attribute(&self) -> &DOMRefCell<Option<PropertyDeclarationBlock>> {
&self.style_attribute &self.style_attribute
} }
fn summarize(self) -> Vec<AttrInfo> { pub fn summarize(&self) -> Vec<AttrInfo> {
let attrs = self.Attributes(); let attrs = self.Attributes();
let mut summarized = vec!(); let mut summarized = vec!();
for i in 0..attrs.r().Length() { for i in 0..attrs.r().Length() {
@ -640,7 +618,7 @@ impl<'a> ElementHelpers<'a> for &'a Element {
summarized summarized
} }
fn is_void(self) -> bool { pub fn is_void(&self) -> bool {
if self.namespace != ns!(HTML) { if self.namespace != ns!(HTML) {
return false return false
} }
@ -654,7 +632,7 @@ impl<'a> ElementHelpers<'a> for &'a Element {
} }
} }
fn remove_inline_style_property(self, property: &str) { pub fn remove_inline_style_property(&self, property: &str) {
let mut inline_declarations = self.style_attribute.borrow_mut(); let mut inline_declarations = self.style_attribute.borrow_mut();
if let &mut Some(ref mut declarations) = &mut *inline_declarations { if let &mut Some(ref mut declarations) = &mut *inline_declarations {
let index = declarations.normal let index = declarations.normal
@ -675,7 +653,7 @@ impl<'a> ElementHelpers<'a> for &'a Element {
} }
} }
fn update_inline_style(self, property_decl: PropertyDeclaration, style_priority: StylePriority) { pub fn update_inline_style(&self, property_decl: PropertyDeclaration, style_priority: StylePriority) {
let mut inline_declarations = self.style_attribute().borrow_mut(); let mut inline_declarations = self.style_attribute().borrow_mut();
if let &mut Some(ref mut declarations) = &mut *inline_declarations { if let &mut Some(ref mut declarations) = &mut *inline_declarations {
let existing_declarations = if style_priority == StylePriority::Important { let existing_declarations = if style_priority == StylePriority::Important {
@ -709,7 +687,7 @@ impl<'a> ElementHelpers<'a> for &'a Element {
}); });
} }
fn set_inline_style_property_priority(self, properties: &[&str], style_priority: StylePriority) { pub fn set_inline_style_property_priority(&self, properties: &[&str], style_priority: StylePriority) {
let mut inline_declarations = self.style_attribute().borrow_mut(); let mut inline_declarations = self.style_attribute().borrow_mut();
if let &mut Some(ref mut declarations) = &mut *inline_declarations { if let &mut Some(ref mut declarations) = &mut *inline_declarations {
let (from, to) = if style_priority == StylePriority::Important { let (from, to) = if style_priority == StylePriority::Important {
@ -734,7 +712,7 @@ impl<'a> ElementHelpers<'a> for &'a Element {
} }
} }
fn get_inline_style_declaration(self, property: &Atom) -> Option<Ref<'a, PropertyDeclaration>> { pub fn get_inline_style_declaration(&self, property: &Atom) -> Option<Ref<PropertyDeclaration>> {
Ref::filter_map(self.style_attribute.borrow(), |inline_declarations| { Ref::filter_map(self.style_attribute.borrow(), |inline_declarations| {
inline_declarations.as_ref().and_then(|declarations| { inline_declarations.as_ref().and_then(|declarations| {
declarations.normal declarations.normal
@ -745,7 +723,8 @@ impl<'a> ElementHelpers<'a> for &'a Element {
}) })
} }
fn get_important_inline_style_declaration(self, property: &Atom) -> Option<Ref<'a, PropertyDeclaration>> { pub fn get_important_inline_style_declaration(&self, property: &Atom)
-> Option<Ref<PropertyDeclaration>> {
Ref::filter_map(self.style_attribute.borrow(), |inline_declarations| { Ref::filter_map(self.style_attribute.borrow(), |inline_declarations| {
inline_declarations.as_ref().and_then(|declarations| { inline_declarations.as_ref().and_then(|declarations| {
declarations.important declarations.important
@ -755,7 +734,7 @@ impl<'a> ElementHelpers<'a> for &'a Element {
}) })
} }
fn serialize(self, traversal_scope: TraversalScope) -> Fallible<DOMString> { pub fn serialize(&self, traversal_scope: TraversalScope) -> Fallible<DOMString> {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let mut writer = vec![]; let mut writer = vec![];
match serialize(&mut writer, &node, match serialize(&mut writer, &node,
@ -769,7 +748,7 @@ impl<'a> ElementHelpers<'a> for &'a Element {
} }
// https://html.spec.whatwg.org/multipage/#root-element // https://html.spec.whatwg.org/multipage/#root-element
fn get_root_element(self) -> Root<Element> { pub fn get_root_element(&self) -> Root<Element> {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.inclusive_ancestors() node.inclusive_ancestors()
.filter_map(ElementCast::to_root) .filter_map(ElementCast::to_root)
@ -778,7 +757,7 @@ impl<'a> ElementHelpers<'a> for &'a Element {
} }
// https://dom.spec.whatwg.org/#locate-a-namespace-prefix // https://dom.spec.whatwg.org/#locate-a-namespace-prefix
fn lookup_prefix(self, namespace: Namespace) -> Option<DOMString> { pub fn lookup_prefix(&self, namespace: Namespace) -> Option<DOMString> {
for node in NodeCast::from_ref(self).inclusive_ancestors() { for node in NodeCast::from_ref(self).inclusive_ancestors() {
match ElementCast::to_ref(node.r()) { match ElementCast::to_ref(node.r()) {
Some(element) => { Some(element) => {
@ -806,16 +785,9 @@ impl<'a> ElementHelpers<'a> for &'a Element {
} }
} }
pub trait FocusElementHelpers {
/// https://html.spec.whatwg.org/multipage/#focusable-area
fn is_focusable_area(self) -> bool;
/// https://html.spec.whatwg.org/multipage/#concept-element-disabled impl Element {
fn is_actually_disabled(self) -> bool; pub fn is_focusable_area(&self) -> bool {
}
impl<'a> FocusElementHelpers for &'a Element {
fn is_focusable_area(self) -> bool {
if self.is_actually_disabled() { if self.is_actually_disabled() {
return false; return false;
} }
@ -836,7 +808,7 @@ impl<'a> FocusElementHelpers for &'a Element {
} }
} }
fn is_actually_disabled(self) -> bool { pub fn is_actually_disabled(&self) -> bool {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
match node.type_id() { match node.type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) | NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) |
@ -855,58 +827,9 @@ impl<'a> FocusElementHelpers for &'a Element {
} }
} }
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<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<Root<Attr>>;
fn get_attributes(self, local_name: &Atom, attributes: &mut RootedVec<JS<Attr>>);
fn set_attribute_from_parser(self,
name: QualName,
value: DOMString,
prefix: Option<Atom>);
fn set_attribute(self, name: &Atom, value: AttrValue);
fn set_custom_attribute(self, name: DOMString, value: DOMString) -> ErrorResult;
fn do_set_attribute<F>(self, local_name: Atom, value: AttrValue,
name: Atom, namespace: Namespace,
prefix: Option<Atom>, cb: F)
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 impl Element {
/// name, if any. pub fn get_attribute(&self, namespace: &Namespace, local_name: &Atom) -> Option<Root<Attr>> {
fn remove_attribute(self, namespace: &Namespace, local_name: &Atom)
-> Option<Root<Attr>>;
/// Removes the first attribute with any namespace and given case-sensitive name.
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<Root<Attr>>
where F: Fn(&Attr) -> bool;
fn has_class(self, name: &Atom) -> bool;
fn set_atomic_attribute(self, local_name: &Atom, value: DOMString);
// https://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
fn has_attribute(self, local_name: &Atom) -> bool;
fn set_bool_attribute(self, local_name: &Atom, value: bool);
fn get_url_attribute(self, local_name: &Atom) -> DOMString;
fn set_url_attribute(self, local_name: &Atom, value: DOMString);
fn get_string_attribute(self, local_name: &Atom) -> DOMString;
fn set_string_attribute(self, local_name: &Atom, value: DOMString);
fn get_tokenlist_attribute(self, local_name: &Atom) -> Vec<Atom>;
fn set_tokenlist_attribute(self, local_name: &Atom, value: DOMString);
fn set_atomic_tokenlist_attribute(self, local_name: &Atom, tokens: Vec<Atom>);
fn get_uint_attribute(self, local_name: &Atom, default: u32) -> u32;
fn set_uint_attribute(self, local_name: &Atom, value: u32);
}
impl<'a> AttributeHandlers for &'a Element {
fn get_attribute(self, namespace: &Namespace, local_name: &Atom) -> Option<Root<Attr>> {
let mut attributes = RootedVec::new(); let mut attributes = RootedVec::new();
self.get_attributes(local_name, &mut attributes); self.get_attributes(local_name, &mut attributes);
attributes.r().iter() attributes.r().iter()
@ -915,14 +838,14 @@ impl<'a> AttributeHandlers for &'a Element {
} }
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name // https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
fn get_attribute_by_name(self, name: DOMString) -> Option<Root<Attr>> { pub fn get_attribute_by_name(&self, name: DOMString) -> Option<Root<Attr>> {
let name = &self.parsed_name(name); let name = &self.parsed_name(name);
self.attrs.borrow().iter().map(|attr| attr.root()) self.attrs.borrow().iter().map(|attr| attr.root())
.find(|a| a.r().name() == name) .find(|a| a.r().name() == name)
} }
// https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name // https://dom.spec.whatwg.org/#concept-element-attributes-get-by-name
fn get_attributes(self, local_name: &Atom, attributes: &mut RootedVec<JS<Attr>>) { pub fn get_attributes(&self, local_name: &Atom, attributes: &mut RootedVec<JS<Attr>>) {
for ref attr in self.attrs.borrow().iter() { for ref attr in self.attrs.borrow().iter() {
let attr = attr.root(); let attr = attr.root();
if attr.r().local_name() == local_name { if attr.r().local_name() == local_name {
@ -931,7 +854,7 @@ impl<'a> AttributeHandlers for &'a Element {
} }
} }
fn set_attribute_from_parser(self, pub fn set_attribute_from_parser(&self,
qname: QualName, qname: QualName,
value: DOMString, value: DOMString,
prefix: Option<Atom>) { prefix: Option<Atom>) {
@ -952,7 +875,7 @@ impl<'a> AttributeHandlers for &'a Element {
self.do_set_attribute(qname.local, value, name, qname.ns, prefix, |_| false) self.do_set_attribute(qname.local, value, name, qname.ns, prefix, |_| false)
} }
fn set_attribute(self, name: &Atom, value: AttrValue) { pub fn set_attribute(&self, name: &Atom, value: AttrValue) {
assert!(&**name == name.to_ascii_lowercase()); assert!(&**name == name.to_ascii_lowercase());
assert!(!name.contains(":")); assert!(!name.contains(":"));
@ -961,7 +884,7 @@ impl<'a> AttributeHandlers for &'a Element {
} }
// https://html.spec.whatwg.org/multipage/#attr-data-* // https://html.spec.whatwg.org/multipage/#attr-data-*
fn set_custom_attribute(self, name: DOMString, value: DOMString) -> ErrorResult { pub fn set_custom_attribute(&self, name: DOMString, value: DOMString) -> ErrorResult {
// Step 1. // Step 1.
match xml_name_type(&name) { match xml_name_type(&name) {
InvalidXMLName => return Err(InvalidCharacter), InvalidXMLName => return Err(InvalidCharacter),
@ -977,7 +900,7 @@ impl<'a> AttributeHandlers for &'a Element {
Ok(()) Ok(())
} }
fn do_set_attribute<F>(self, pub fn do_set_attribute<F>(&self,
local_name: Atom, local_name: Atom,
value: AttrValue, value: AttrValue,
name: Atom, name: Atom,
@ -1003,7 +926,7 @@ impl<'a> AttributeHandlers for &'a Element {
(*self.attrs.borrow())[idx].root().r().set_value(set_type, value, self); (*self.attrs.borrow())[idx].root().r().set_value(set_type, value, self);
} }
fn parse_attribute(self, namespace: &Namespace, local_name: &Atom, pub fn parse_attribute(&self, namespace: &Namespace, local_name: &Atom,
value: DOMString) -> AttrValue { value: DOMString) -> AttrValue {
if *namespace == ns!("") { if *namespace == ns!("") {
vtable_for(&NodeCast::from_ref(self)) vtable_for(&NodeCast::from_ref(self))
@ -1013,18 +936,18 @@ impl<'a> AttributeHandlers for &'a Element {
} }
} }
fn remove_attribute(self, namespace: &Namespace, local_name: &Atom) pub fn remove_attribute(&self, namespace: &Namespace, local_name: &Atom)
-> Option<Root<Attr>> { -> Option<Root<Attr>> {
self.do_remove_attribute(|attr| { self.do_remove_attribute(|attr| {
attr.namespace() == namespace && attr.local_name() == local_name attr.namespace() == namespace && attr.local_name() == local_name
}) })
} }
fn remove_attribute_by_name(self, name: &Atom) -> Option<Root<Attr>> { pub fn remove_attribute_by_name(&self, name: &Atom) -> Option<Root<Attr>> {
self.do_remove_attribute(|attr| attr.name() == name) self.do_remove_attribute(|attr| attr.name() == name)
} }
fn do_remove_attribute<F>(self, find: F) -> Option<Root<Attr>> pub fn do_remove_attribute<F>(&self, find: F) -> Option<Root<Attr>>
where F: Fn(&Attr) -> bool where F: Fn(&Attr) -> bool
{ {
let idx = self.attrs.borrow().iter() let idx = self.attrs.borrow().iter()
@ -1057,7 +980,7 @@ impl<'a> AttributeHandlers for &'a Element {
}) })
} }
fn has_class(self, name: &Atom) -> bool { pub fn has_class(&self, name: &Atom) -> bool {
let quirks_mode = { let quirks_mode = {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let owner_doc = node.owner_doc(); let owner_doc = node.owner_doc();
@ -1074,20 +997,20 @@ impl<'a> AttributeHandlers for &'a Element {
}).unwrap_or(false) }).unwrap_or(false)
} }
fn set_atomic_attribute(self, local_name: &Atom, value: DOMString) { pub fn set_atomic_attribute(&self, local_name: &Atom, value: DOMString) {
assert!(&**local_name == local_name.to_ascii_lowercase()); assert!(&**local_name == local_name.to_ascii_lowercase());
let value = AttrValue::from_atomic(value); let value = AttrValue::from_atomic(value);
self.set_attribute(local_name, value); self.set_attribute(local_name, value);
} }
fn has_attribute(self, local_name: &Atom) -> bool { pub fn has_attribute(&self, local_name: &Atom) -> bool {
assert!(local_name.bytes().all(|b| b.to_ascii_lowercase() == b)); assert!(local_name.bytes().all(|b| b.to_ascii_lowercase() == b));
self.attrs.borrow().iter().map(|attr| attr.root()).any(|attr| { self.attrs.borrow().iter().map(|attr| attr.root()).any(|attr| {
attr.r().local_name() == local_name && attr.r().namespace() == &ns!("") attr.r().local_name() == local_name && attr.r().namespace() == &ns!("")
}) })
} }
fn set_bool_attribute(self, local_name: &Atom, value: bool) { pub fn set_bool_attribute(&self, local_name: &Atom, value: bool) {
if self.has_attribute(local_name) == value { return; } if self.has_attribute(local_name) == value { return; }
if value { if value {
self.set_string_attribute(local_name, String::new()); self.set_string_attribute(local_name, String::new());
@ -1096,7 +1019,7 @@ impl<'a> AttributeHandlers for &'a Element {
} }
} }
fn get_url_attribute(self, local_name: &Atom) -> DOMString { pub fn get_url_attribute(&self, local_name: &Atom) -> DOMString {
assert!(&**local_name == local_name.to_ascii_lowercase()); assert!(&**local_name == local_name.to_ascii_lowercase());
if !self.has_attribute(local_name) { if !self.has_attribute(local_name) {
return "".to_owned(); return "".to_owned();
@ -1111,22 +1034,22 @@ impl<'a> AttributeHandlers for &'a Element {
Err(_) => "".to_owned() Err(_) => "".to_owned()
} }
} }
fn set_url_attribute(self, local_name: &Atom, value: DOMString) { pub fn set_url_attribute(&self, local_name: &Atom, value: DOMString) {
self.set_string_attribute(local_name, value); self.set_string_attribute(local_name, value);
} }
fn get_string_attribute(self, local_name: &Atom) -> DOMString { pub fn get_string_attribute(&self, local_name: &Atom) -> DOMString {
match self.get_attribute(&ns!(""), local_name) { match self.get_attribute(&ns!(""), local_name) {
Some(x) => x.r().Value(), Some(x) => x.r().Value(),
None => "".to_owned() None => "".to_owned()
} }
} }
fn set_string_attribute(self, local_name: &Atom, value: DOMString) { pub fn set_string_attribute(&self, local_name: &Atom, value: DOMString) {
assert!(&**local_name == local_name.to_ascii_lowercase()); assert!(&**local_name == local_name.to_ascii_lowercase());
self.set_attribute(local_name, AttrValue::String(value)); self.set_attribute(local_name, AttrValue::String(value));
} }
fn get_tokenlist_attribute(self, local_name: &Atom) -> Vec<Atom> { pub fn get_tokenlist_attribute(&self, local_name: &Atom) -> Vec<Atom> {
self.get_attribute(&ns!(""), local_name).map(|attr| { self.get_attribute(&ns!(""), local_name).map(|attr| {
attr.r() attr.r()
.value() .value()
@ -1136,17 +1059,17 @@ impl<'a> AttributeHandlers for &'a Element {
}).unwrap_or(vec!()) }).unwrap_or(vec!())
} }
fn set_tokenlist_attribute(self, local_name: &Atom, value: DOMString) { pub fn set_tokenlist_attribute(&self, local_name: &Atom, value: DOMString) {
assert!(&**local_name == local_name.to_ascii_lowercase()); assert!(&**local_name == local_name.to_ascii_lowercase());
self.set_attribute(local_name, AttrValue::from_serialized_tokenlist(value)); self.set_attribute(local_name, AttrValue::from_serialized_tokenlist(value));
} }
fn set_atomic_tokenlist_attribute(self, local_name: &Atom, tokens: Vec<Atom>) { pub fn set_atomic_tokenlist_attribute(&self, local_name: &Atom, tokens: Vec<Atom>) {
assert!(&**local_name == local_name.to_ascii_lowercase()); assert!(&**local_name == local_name.to_ascii_lowercase());
self.set_attribute(local_name, AttrValue::from_atomic_tokens(tokens)); self.set_attribute(local_name, AttrValue::from_atomic_tokens(tokens));
} }
fn get_uint_attribute(self, local_name: &Atom, default: u32) -> u32 { pub fn get_uint_attribute(&self, local_name: &Atom, default: u32) -> u32 {
assert!(local_name.chars().all(|ch| { assert!(local_name.chars().all(|ch| {
!ch.is_ascii() || ch.to_ascii_lowercase() == ch !ch.is_ascii() || ch.to_ascii_lowercase() == ch
})); }));
@ -1162,30 +1085,30 @@ impl<'a> AttributeHandlers for &'a Element {
None => default, None => default,
} }
} }
fn set_uint_attribute(self, local_name: &Atom, value: u32) { pub fn set_uint_attribute(&self, local_name: &Atom, value: u32) {
assert!(&**local_name == local_name.to_ascii_lowercase()); assert!(&**local_name == local_name.to_ascii_lowercase());
self.set_attribute(local_name, AttrValue::UInt(value.to_string(), value)); self.set_attribute(local_name, AttrValue::UInt(value.to_string(), value));
} }
} }
impl<'a> ElementMethods for &'a Element { impl ElementMethods for Element {
// https://dom.spec.whatwg.org/#dom-element-namespaceuri // https://dom.spec.whatwg.org/#dom-element-namespaceuri
fn GetNamespaceURI(self) -> Option<DOMString> { fn GetNamespaceURI(&self) -> Option<DOMString> {
Node::namespace_to_string(self.namespace.clone()) Node::namespace_to_string(self.namespace.clone())
} }
// https://dom.spec.whatwg.org/#dom-element-localname // https://dom.spec.whatwg.org/#dom-element-localname
fn LocalName(self) -> DOMString { fn LocalName(&self) -> DOMString {
(*self.local_name).to_owned() (*self.local_name).to_owned()
} }
// https://dom.spec.whatwg.org/#dom-element-prefix // https://dom.spec.whatwg.org/#dom-element-prefix
fn GetPrefix(self) -> Option<DOMString> { fn GetPrefix(&self) -> Option<DOMString> {
self.prefix.clone() self.prefix.clone()
} }
// https://dom.spec.whatwg.org/#dom-element-tagname // https://dom.spec.whatwg.org/#dom-element-tagname
fn TagName(self) -> DOMString { fn TagName(&self) -> DOMString {
let qualified_name = match self.prefix { let qualified_name = match self.prefix {
Some(ref prefix) => { Some(ref prefix) => {
Cow::Owned(format!("{}:{}", &**prefix, &*self.local_name)) Cow::Owned(format!("{}:{}", &**prefix, &*self.local_name))
@ -1200,32 +1123,32 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://dom.spec.whatwg.org/#dom-element-id // https://dom.spec.whatwg.org/#dom-element-id
fn Id(self) -> DOMString { fn Id(&self) -> DOMString {
self.get_string_attribute(&atom!("id")) self.get_string_attribute(&atom!("id"))
} }
// https://dom.spec.whatwg.org/#dom-element-id // https://dom.spec.whatwg.org/#dom-element-id
fn SetId(self, id: DOMString) { fn SetId(&self, id: DOMString) {
self.set_atomic_attribute(&atom!("id"), id); self.set_atomic_attribute(&atom!("id"), id);
} }
// https://dom.spec.whatwg.org/#dom-element-classname // https://dom.spec.whatwg.org/#dom-element-classname
fn ClassName(self) -> DOMString { fn ClassName(&self) -> DOMString {
self.get_string_attribute(&atom!("class")) self.get_string_attribute(&atom!("class"))
} }
// https://dom.spec.whatwg.org/#dom-element-classname // https://dom.spec.whatwg.org/#dom-element-classname
fn SetClassName(self, class: DOMString) { fn SetClassName(&self, class: DOMString) {
self.set_tokenlist_attribute(&atom!("class"), class); self.set_tokenlist_attribute(&atom!("class"), class);
} }
// https://dom.spec.whatwg.org/#dom-element-classlist // https://dom.spec.whatwg.org/#dom-element-classlist
fn ClassList(self) -> Root<DOMTokenList> { fn ClassList(&self) -> Root<DOMTokenList> {
self.class_list.or_init(|| DOMTokenList::new(self, &atom!("class"))) self.class_list.or_init(|| DOMTokenList::new(self, &atom!("class")))
} }
// https://dom.spec.whatwg.org/#dom-element-attributes // https://dom.spec.whatwg.org/#dom-element-attributes
fn Attributes(self) -> Root<NamedNodeMap> { fn Attributes(&self) -> Root<NamedNodeMap> {
self.attr_list.or_init(|| { self.attr_list.or_init(|| {
let doc = { let doc = {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
@ -1237,13 +1160,13 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://dom.spec.whatwg.org/#dom-element-getattribute // https://dom.spec.whatwg.org/#dom-element-getattribute
fn GetAttribute(self, name: DOMString) -> Option<DOMString> { fn GetAttribute(&self, name: DOMString) -> Option<DOMString> {
self.get_attribute_by_name(name) self.get_attribute_by_name(name)
.map(|s| s.r().Value()) .map(|s| s.r().Value())
} }
// https://dom.spec.whatwg.org/#dom-element-getattributens // https://dom.spec.whatwg.org/#dom-element-getattributens
fn GetAttributeNS(self, fn GetAttributeNS(&self,
namespace: Option<DOMString>, namespace: Option<DOMString>,
local_name: DOMString) -> Option<DOMString> { local_name: DOMString) -> Option<DOMString> {
let namespace = &namespace_from_domstring(namespace); let namespace = &namespace_from_domstring(namespace);
@ -1252,7 +1175,7 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://dom.spec.whatwg.org/#dom-element-setattribute // https://dom.spec.whatwg.org/#dom-element-setattribute
fn SetAttribute(self, fn SetAttribute(&self,
name: DOMString, name: DOMString,
value: DOMString) -> ErrorResult { value: DOMString) -> ErrorResult {
// Step 1. // Step 1.
@ -1272,7 +1195,7 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://dom.spec.whatwg.org/#dom-element-setattributens // https://dom.spec.whatwg.org/#dom-element-setattributens
fn SetAttributeNS(self, fn SetAttributeNS(&self,
namespace: Option<DOMString>, namespace: Option<DOMString>,
qualified_name: DOMString, qualified_name: DOMString,
value: DOMString) -> ErrorResult { value: DOMString) -> ErrorResult {
@ -1289,13 +1212,13 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://dom.spec.whatwg.org/#dom-element-removeattribute // https://dom.spec.whatwg.org/#dom-element-removeattribute
fn RemoveAttribute(self, name: DOMString) { fn RemoveAttribute(&self, name: DOMString) {
let name = self.parsed_name(name); let name = self.parsed_name(name);
self.remove_attribute_by_name(&name); self.remove_attribute_by_name(&name);
} }
// https://dom.spec.whatwg.org/#dom-element-removeattributens // https://dom.spec.whatwg.org/#dom-element-removeattributens
fn RemoveAttributeNS(self, fn RemoveAttributeNS(&self,
namespace: Option<DOMString>, namespace: Option<DOMString>,
local_name: DOMString) { local_name: DOMString) {
let namespace = namespace_from_domstring(namespace); let namespace = namespace_from_domstring(namespace);
@ -1304,38 +1227,38 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://dom.spec.whatwg.org/#dom-element-hasattribute // https://dom.spec.whatwg.org/#dom-element-hasattribute
fn HasAttribute(self, name: DOMString) -> bool { fn HasAttribute(&self, name: DOMString) -> bool {
self.GetAttribute(name).is_some() self.GetAttribute(name).is_some()
} }
// https://dom.spec.whatwg.org/#dom-element-hasattributens // https://dom.spec.whatwg.org/#dom-element-hasattributens
fn HasAttributeNS(self, fn HasAttributeNS(&self,
namespace: Option<DOMString>, namespace: Option<DOMString>,
local_name: DOMString) -> bool { local_name: DOMString) -> bool {
self.GetAttributeNS(namespace, local_name).is_some() self.GetAttributeNS(namespace, local_name).is_some()
} }
// https://dom.spec.whatwg.org/#dom-element-getelementsbytagname // https://dom.spec.whatwg.org/#dom-element-getelementsbytagname
fn GetElementsByTagName(self, localname: DOMString) -> Root<HTMLCollection> { fn GetElementsByTagName(&self, localname: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self); let window = window_from_node(self);
HTMLCollection::by_tag_name(window.r(), NodeCast::from_ref(self), localname) HTMLCollection::by_tag_name(window.r(), NodeCast::from_ref(self), localname)
} }
// https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens // https://dom.spec.whatwg.org/#dom-element-getelementsbytagnamens
fn GetElementsByTagNameNS(self, maybe_ns: Option<DOMString>, fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>,
localname: DOMString) -> Root<HTMLCollection> { localname: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self); let window = window_from_node(self);
HTMLCollection::by_tag_name_ns(window.r(), NodeCast::from_ref(self), localname, maybe_ns) HTMLCollection::by_tag_name_ns(window.r(), NodeCast::from_ref(self), localname, maybe_ns)
} }
// https://dom.spec.whatwg.org/#dom-element-getelementsbyclassname // https://dom.spec.whatwg.org/#dom-element-getelementsbyclassname
fn GetElementsByClassName(self, classes: DOMString) -> Root<HTMLCollection> { fn GetElementsByClassName(&self, classes: DOMString) -> Root<HTMLCollection> {
let window = window_from_node(self); let window = window_from_node(self);
HTMLCollection::by_class_name(window.r(), NodeCast::from_ref(self), classes) HTMLCollection::by_class_name(window.r(), NodeCast::from_ref(self), classes)
} }
// https://drafts.csswg.org/cssom-view/#dom-element-getclientrects // https://drafts.csswg.org/cssom-view/#dom-element-getclientrects
fn GetClientRects(self) -> Root<DOMRectList> { fn GetClientRects(&self) -> Root<DOMRectList> {
let win = window_from_node(self); let win = window_from_node(self);
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let raw_rects = node.get_content_boxes(); let raw_rects = node.get_content_boxes();
@ -1348,7 +1271,7 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://drafts.csswg.org/cssom-view/#dom-element-getboundingclientrect // https://drafts.csswg.org/cssom-view/#dom-element-getboundingclientrect
fn GetBoundingClientRect(self) -> Root<DOMRect> { fn GetBoundingClientRect(&self) -> Root<DOMRect> {
let win = window_from_node(self); let win = window_from_node(self);
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let rect = node.get_bounding_content_box(); let rect = node.get_bounding_content_box();
@ -1361,37 +1284,37 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://drafts.csswg.org/cssom-view/#dom-element-clienttop // https://drafts.csswg.org/cssom-view/#dom-element-clienttop
fn ClientTop(self) -> i32 { fn ClientTop(&self) -> i32 {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_client_rect().origin.y node.get_client_rect().origin.y
} }
// https://drafts.csswg.org/cssom-view/#dom-element-clientleft // https://drafts.csswg.org/cssom-view/#dom-element-clientleft
fn ClientLeft(self) -> i32 { fn ClientLeft(&self) -> i32 {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_client_rect().origin.x node.get_client_rect().origin.x
} }
// https://drafts.csswg.org/cssom-view/#dom-element-clientwidth // https://drafts.csswg.org/cssom-view/#dom-element-clientwidth
fn ClientWidth(self) -> i32 { fn ClientWidth(&self) -> i32 {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_client_rect().size.width node.get_client_rect().size.width
} }
// https://drafts.csswg.org/cssom-view/#dom-element-clientheight // https://drafts.csswg.org/cssom-view/#dom-element-clientheight
fn ClientHeight(self) -> i32 { fn ClientHeight(&self) -> i32 {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_client_rect().size.height node.get_client_rect().size.height
} }
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML
fn GetInnerHTML(self) -> Fallible<DOMString> { fn GetInnerHTML(&self) -> Fallible<DOMString> {
//XXX TODO: XML case //XXX TODO: XML case
self.serialize(ChildrenOnly) self.serialize(ChildrenOnly)
} }
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-innerHTML
fn SetInnerHTML(self, value: DOMString) -> Fallible<()> { fn SetInnerHTML(&self, value: DOMString) -> Fallible<()> {
let context_node = NodeCast::from_ref(self); let context_node = NodeCast::from_ref(self);
// Step 1. // Step 1.
let frag = try!(context_node.parse_fragment(value)); let frag = try!(context_node.parse_fragment(value));
@ -1401,12 +1324,12 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML
fn GetOuterHTML(self) -> Fallible<DOMString> { fn GetOuterHTML(&self) -> Fallible<DOMString> {
self.serialize(IncludeNode) self.serialize(IncludeNode)
} }
// https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML
fn SetOuterHTML(self, value: DOMString) -> Fallible<()> { fn SetOuterHTML(&self, value: DOMString) -> Fallible<()> {
let context_document = document_from_node(self); let context_document = document_from_node(self);
let context_node = NodeCast::from_ref(self); let context_node = NodeCast::from_ref(self);
// Step 1. // Step 1.
@ -1441,83 +1364,83 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling // https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-previouselementsibling
fn GetPreviousElementSibling(self) -> Option<Root<Element>> { fn GetPreviousElementSibling(&self) -> Option<Root<Element>> {
NodeCast::from_ref(self).preceding_siblings() NodeCast::from_ref(self).preceding_siblings()
.filter_map(ElementCast::to_root).next() .filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling // https://dom.spec.whatwg.org/#dom-nondocumenttypechildnode-nextelementsibling
fn GetNextElementSibling(self) -> Option<Root<Element>> { fn GetNextElementSibling(&self) -> Option<Root<Element>> {
NodeCast::from_ref(self).following_siblings() NodeCast::from_ref(self).following_siblings()
.filter_map(ElementCast::to_root).next() .filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-children // https://dom.spec.whatwg.org/#dom-parentnode-children
fn Children(self) -> Root<HTMLCollection> { fn Children(&self) -> Root<HTMLCollection> {
let window = window_from_node(self); let window = window_from_node(self);
HTMLCollection::children(window.r(), NodeCast::from_ref(self)) HTMLCollection::children(window.r(), NodeCast::from_ref(self))
} }
// https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild // https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild
fn GetFirstElementChild(self) -> Option<Root<Element>> { fn GetFirstElementChild(&self) -> Option<Root<Element>> {
NodeCast::from_ref(self).child_elements().next() NodeCast::from_ref(self).child_elements().next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild // https://dom.spec.whatwg.org/#dom-parentnode-lastelementchild
fn GetLastElementChild(self) -> Option<Root<Element>> { fn GetLastElementChild(&self) -> Option<Root<Element>> {
NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next() NodeCast::from_ref(self).rev_children().filter_map(ElementCast::to_root).next()
} }
// https://dom.spec.whatwg.org/#dom-parentnode-childelementcount // https://dom.spec.whatwg.org/#dom-parentnode-childelementcount
fn ChildElementCount(self) -> u32 { fn ChildElementCount(&self) -> u32 {
NodeCast::from_ref(self).child_elements().count() as u32 NodeCast::from_ref(self).child_elements().count() as u32
} }
// https://dom.spec.whatwg.org/#dom-parentnode-prepend // https://dom.spec.whatwg.org/#dom-parentnode-prepend
fn Prepend(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn Prepend(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).prepend(nodes) NodeCast::from_ref(self).prepend(nodes)
} }
// https://dom.spec.whatwg.org/#dom-parentnode-append // https://dom.spec.whatwg.org/#dom-parentnode-append
fn Append(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn Append(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).append(nodes) NodeCast::from_ref(self).append(nodes)
} }
// https://dom.spec.whatwg.org/#dom-parentnode-queryselector // https://dom.spec.whatwg.org/#dom-parentnode-queryselector
fn QuerySelector(self, selectors: DOMString) -> Fallible<Option<Root<Element>>> { fn QuerySelector(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
let root = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
root.query_selector(selectors) root.query_selector(selectors)
} }
// https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall // https://dom.spec.whatwg.org/#dom-parentnode-queryselectorall
fn QuerySelectorAll(self, selectors: DOMString) -> Fallible<Root<NodeList>> { fn QuerySelectorAll(&self, selectors: DOMString) -> Fallible<Root<NodeList>> {
let root = NodeCast::from_ref(self); let root = NodeCast::from_ref(self);
root.query_selector_all(selectors) root.query_selector_all(selectors)
} }
// https://dom.spec.whatwg.org/#dom-childnode-before // https://dom.spec.whatwg.org/#dom-childnode-before
fn Before(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn Before(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).before(nodes) NodeCast::from_ref(self).before(nodes)
} }
// https://dom.spec.whatwg.org/#dom-childnode-after // https://dom.spec.whatwg.org/#dom-childnode-after
fn After(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn After(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).after(nodes) NodeCast::from_ref(self).after(nodes)
} }
// https://dom.spec.whatwg.org/#dom-childnode-replacewith // https://dom.spec.whatwg.org/#dom-childnode-replacewith
fn ReplaceWith(self, nodes: Vec<NodeOrString>) -> ErrorResult { fn ReplaceWith(&self, nodes: Vec<NodeOrString>) -> ErrorResult {
NodeCast::from_ref(self).replace_with(nodes) NodeCast::from_ref(self).replace_with(nodes)
} }
// https://dom.spec.whatwg.org/#dom-childnode-remove // https://dom.spec.whatwg.org/#dom-childnode-remove
fn Remove(self) { fn Remove(&self) {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.remove_self(); node.remove_self();
} }
// https://dom.spec.whatwg.org/#dom-element-matches // https://dom.spec.whatwg.org/#dom-element-matches
fn Matches(self, selectors: DOMString) -> Fallible<bool> { fn Matches(&self, selectors: DOMString) -> Fallible<bool> {
match parse_author_origin_selector_list_from_str(&selectors) { match parse_author_origin_selector_list_from_str(&selectors) {
Err(()) => Err(Syntax), Err(()) => Err(Syntax),
Ok(ref selectors) => { Ok(ref selectors) => {
@ -1527,7 +1450,7 @@ impl<'a> ElementMethods for &'a Element {
} }
// https://dom.spec.whatwg.org/#dom-element-closest // https://dom.spec.whatwg.org/#dom-element-closest
fn Closest(self, selectors: DOMString) -> Fallible<Option<Root<Element>>> { fn Closest(&self, selectors: DOMString) -> Fallible<Option<Root<Element>>> {
match parse_author_origin_selector_list_from_str(&selectors) { match parse_author_origin_selector_list_from_str(&selectors) {
Err(()) => Err(Syntax), Err(()) => Err(Syntax),
Ok(ref selectors) => { Ok(ref selectors) => {
@ -1545,9 +1468,9 @@ impl<'a> ElementMethods for &'a Element {
} }
} }
impl<'a> VirtualMethods for &'a Element { impl VirtualMethods for Element {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let node: &&Node = NodeCast::from_borrowed_ref(self); let node: &Node = NodeCast::from_ref(self);
Some(node as &VirtualMethods) Some(node as &VirtualMethods)
} }
@ -1556,11 +1479,11 @@ impl<'a> VirtualMethods for &'a Element {
s.after_set_attr(attr); s.after_set_attr(attr);
} }
let node = NodeCast::from_ref(*self); let node = NodeCast::from_ref(self);
match attr.local_name() { match attr.local_name() {
&atom!("style") => { &atom!("style") => {
// Modifying the `style` attribute might change style. // Modifying the `style` attribute might change style.
let doc = document_from_node(*self); let doc = document_from_node(self);
let base_url = doc.r().base_url(); let base_url = doc.r().base_url();
let value = attr.value(); let value = attr.value();
let style = Some(parse_style_attribute(&value, &base_url)); let style = Some(parse_style_attribute(&value, &base_url));
@ -1573,7 +1496,7 @@ impl<'a> VirtualMethods for &'a Element {
&atom!("class") => { &atom!("class") => {
// Modifying a class can change style. // Modifying a class can change style.
if node.is_in_doc() { if node.is_in_doc() {
let document = document_from_node(*self); let document = document_from_node(self);
document.r().content_changed(node, NodeDamage::NodeStyleDamaged); document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
} }
} }
@ -1581,10 +1504,10 @@ impl<'a> VirtualMethods for &'a Element {
// Modifying an ID might change style. // Modifying an ID might change style.
let value = attr.value(); let value = attr.value();
if node.is_in_doc() { if node.is_in_doc() {
let doc = document_from_node(*self); let doc = document_from_node(self);
if !value.is_empty() { if !value.is_empty() {
let value = value.atom().unwrap().clone(); let value = value.atom().unwrap().clone();
doc.r().register_named_element(*self, value); doc.r().register_named_element(self, value);
} }
doc.r().content_changed(node, NodeDamage::NodeStyleDamaged); doc.r().content_changed(node, NodeDamage::NodeStyleDamaged);
} }
@ -1592,7 +1515,7 @@ impl<'a> VirtualMethods for &'a Element {
_ => { _ => {
// Modifying any other attribute might change arbitrary things. // Modifying any other attribute might change arbitrary things.
if node.is_in_doc() { if node.is_in_doc() {
let document = document_from_node(*self); let document = document_from_node(self);
document.r().content_changed(node, NodeDamage::OtherNodeDamage); document.r().content_changed(node, NodeDamage::OtherNodeDamage);
} }
} }
@ -1604,14 +1527,14 @@ impl<'a> VirtualMethods for &'a Element {
s.before_remove_attr(attr); s.before_remove_attr(attr);
} }
let node = NodeCast::from_ref(*self); let node = NodeCast::from_ref(self);
match attr.local_name() { match attr.local_name() {
&atom!("style") => { &atom!("style") => {
// Modifying the `style` attribute might change style. // Modifying the `style` attribute might change style.
*self.style_attribute.borrow_mut() = None; *self.style_attribute.borrow_mut() = None;
if node.is_in_doc() { if node.is_in_doc() {
let doc = document_from_node(*self); let doc = document_from_node(self);
doc.r().content_changed(node, NodeDamage::NodeStyleDamaged); doc.r().content_changed(node, NodeDamage::NodeStyleDamaged);
} }
} }
@ -1619,10 +1542,10 @@ impl<'a> VirtualMethods for &'a Element {
// Modifying an ID can change style. // Modifying an ID can change style.
let value = attr.value(); let value = attr.value();
if node.is_in_doc() { if node.is_in_doc() {
let doc = document_from_node(*self); let doc = document_from_node(self);
if !value.is_empty() { if !value.is_empty() {
let value = value.atom().unwrap().clone(); let value = value.atom().unwrap().clone();
doc.r().unregister_named_element(*self, value); doc.r().unregister_named_element(self, value);
} }
doc.r().content_changed(node, NodeDamage::NodeStyleDamaged); doc.r().content_changed(node, NodeDamage::NodeStyleDamaged);
} }
@ -1630,14 +1553,14 @@ impl<'a> VirtualMethods for &'a Element {
&atom!("class") => { &atom!("class") => {
// Modifying a class can change style. // Modifying a class can change style.
if node.is_in_doc() { if node.is_in_doc() {
let document = document_from_node(*self); let document = document_from_node(self);
document.r().content_changed(node, NodeDamage::NodeStyleDamaged); document.r().content_changed(node, NodeDamage::NodeStyleDamaged);
} }
} }
_ => { _ => {
// Modifying any other attribute might change arbitrary things. // Modifying any other attribute might change arbitrary things.
if node.is_in_doc() { if node.is_in_doc() {
let doc = document_from_node(*self); let doc = document_from_node(self);
doc.r().content_changed(node, NodeDamage::OtherNodeDamage); doc.r().content_changed(node, NodeDamage::OtherNodeDamage);
} }
} }
@ -1660,11 +1583,11 @@ impl<'a> VirtualMethods for &'a Element {
if !tree_in_doc { return; } if !tree_in_doc { return; }
if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) { if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) {
let doc = document_from_node(*self); let doc = document_from_node(self);
let value = attr.r().Value(); let value = attr.r().Value();
if !value.is_empty() { if !value.is_empty() {
let value = Atom::from_slice(&value); let value = Atom::from_slice(&value);
doc.r().register_named_element(*self, value); doc.r().register_named_element(self, value);
} }
} }
} }
@ -1677,11 +1600,11 @@ impl<'a> VirtualMethods for &'a Element {
if !tree_in_doc { return; } if !tree_in_doc { return; }
if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) { if let Some(ref attr) = self.get_attribute(&ns!(""), &atom!("id")) {
let doc = document_from_node(*self); let doc = document_from_node(self);
let value = attr.r().Value(); let value = attr.r().Value();
if !value.is_empty() { if !value.is_empty() {
let value = Atom::from_slice(&value); let value = Atom::from_slice(&value);
doc.r().unregister_named_element(*self, value); doc.r().unregister_named_element(self, value);
} }
} }
} }
@ -1747,7 +1670,7 @@ impl<'a> ::selectors::Element for Root<Element> {
} }
fn get_local_name<'b>(&'b self) -> &'b Atom { fn get_local_name<'b>(&'b self) -> &'b Atom {
ElementHelpers::local_name(&**self) self.local_name()
} }
fn get_namespace<'b>(&'b self) -> &'b Namespace { fn get_namespace<'b>(&'b self) -> &'b Namespace {
self.namespace() self.namespace()
@ -1798,7 +1721,7 @@ impl<'a> ::selectors::Element for Root<Element> {
} }
} }
fn has_class(&self, name: &Atom) -> bool { fn has_class(&self, name: &Atom) -> bool {
AttributeHandlers::has_class(&**self, name) Element::has_class(&**self, name)
} }
fn each_class<F>(&self, mut callback: F) fn each_class<F>(&self, mut callback: F)
where F: FnMut(&Atom) where F: FnMut(&Atom)
@ -1859,24 +1782,17 @@ impl<'a> ::selectors::Element for Root<Element> {
} }
} }
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<Root<Element>>;
fn authentic_click_activation<'b>(self, event: &'b Event);
}
impl<'a> ActivationElementHelpers<'a> for &'a Element { impl Element {
fn as_maybe_activatable(&'a self) -> Option<&'a (Activatable + 'a)> { pub fn as_maybe_activatable<'a>(&'a self) -> Option<&'a (Activatable + 'a)> {
let node = NodeCast::from_ref(*self); let node = NodeCast::from_ref(self);
let element = match node.type_id() { let element = match node.type_id() {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => { NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => {
let element = HTMLInputElementCast::to_borrowed_ref(self).unwrap(); let element = HTMLInputElementCast::to_ref(self).unwrap();
Some(element as &'a (Activatable + 'a)) Some(element as &'a (Activatable + 'a))
}, },
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement)) => { NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement)) => {
let element = HTMLAnchorElementCast::to_borrowed_ref(self).unwrap(); let element = HTMLAnchorElementCast::to_ref(self).unwrap();
Some(element as &'a (Activatable + 'a)) Some(element as &'a (Activatable + 'a))
}, },
_ => { _ => {
@ -1892,18 +1808,18 @@ impl<'a> ActivationElementHelpers<'a> for &'a Element {
}) })
} }
fn click_in_progress(self) -> bool { pub fn click_in_progress(&self) -> bool {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.get_flag(CLICK_IN_PROGRESS) node.get_flag(CLICK_IN_PROGRESS)
} }
fn set_click_in_progress(self, click: bool) { pub fn set_click_in_progress(&self, click: bool) {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.set_flag(CLICK_IN_PROGRESS, click) node.set_flag(CLICK_IN_PROGRESS, click)
} }
// https://html.spec.whatwg.org/multipage/#nearest-activatable-element // https://html.spec.whatwg.org/multipage/#nearest-activatable-element
fn nearest_activable_element(self) -> Option<Root<Element>> { pub fn nearest_activable_element(&self) -> Option<Root<Element>> {
match self.as_maybe_activatable() { match self.as_maybe_activatable() {
Some(el) => Some(Root::from_ref(el.as_element())), Some(el) => Some(Root::from_ref(el.as_element())),
None => { None => {
@ -1926,7 +1842,7 @@ impl<'a> ActivationElementHelpers<'a> for &'a Element {
/// ///
/// Use an element's synthetic click activation (or handle_event) for any script-triggered clicks. /// Use an element's synthetic click activation (or handle_event) for any script-triggered clicks.
/// If the spec says otherwise, check with Manishearth first /// If the spec says otherwise, check with Manishearth first
fn authentic_click_activation<'b>(self, event: &'b Event) { pub fn authentic_click_activation<'b>(&self, event: &'b Event) {
// Not explicitly part of the spec, however this helps enforce the invariants // Not explicitly part of the spec, however this helps enforce the invariants
// required to save state between pre-activation and post-activation // required to save state between pre-activation and post-activation
// since we cannot nest authentic clicks (unlike synthetic click activation, where // since we cannot nest authentic clicks (unlike synthetic click activation, where
@ -1953,10 +1869,10 @@ impl<'a> ActivationElementHelpers<'a> for &'a Element {
} }
} }
// Step 6 // Step 6
None => {event.fire(target);} None => { event.fire(target); }
}, },
// Step 6 // Step 6
None => {event.fire(target);} None => { event.fire(target); }
} }
// Step 7 // Step 7
self.set_click_in_progress(false); self.set_click_in_progress(false);

View file

@ -22,7 +22,6 @@ use std::borrow::ToOwned;
use std::cell::Cell; use std::cell::Cell;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct ErrorEvent { pub struct ErrorEvent {
event: Event, event: Event,
message: DOMRefCell<DOMString>, message: DOMRefCell<DOMString>,
@ -115,29 +114,29 @@ impl ErrorEvent {
} }
impl<'a> ErrorEventMethods for &'a ErrorEvent { impl ErrorEventMethods for ErrorEvent {
// https://html.spec.whatwg.org/multipage/#dom-errorevent-lineno // https://html.spec.whatwg.org/multipage/#dom-errorevent-lineno
fn Lineno(self) -> u32 { fn Lineno(&self) -> u32 {
self.lineno.get() self.lineno.get()
} }
// https://html.spec.whatwg.org/multipage/#dom-errorevent-colno // https://html.spec.whatwg.org/multipage/#dom-errorevent-colno
fn Colno(self) -> u32 { fn Colno(&self) -> u32 {
self.colno.get() self.colno.get()
} }
// https://html.spec.whatwg.org/multipage/#dom-errorevent-message // https://html.spec.whatwg.org/multipage/#dom-errorevent-message
fn Message(self) -> DOMString { fn Message(&self) -> DOMString {
self.message.borrow().clone() self.message.borrow().clone()
} }
// https://html.spec.whatwg.org/multipage/#dom-errorevent-filename // https://html.spec.whatwg.org/multipage/#dom-errorevent-filename
fn Filename(self) -> DOMString { fn Filename(&self) -> DOMString {
self.filename.borrow().clone() self.filename.borrow().clone()
} }
// https://html.spec.whatwg.org/multipage/#dom-errorevent-error // https://html.spec.whatwg.org/multipage/#dom-errorevent-error
fn Error(self, _cx: *mut JSContext) -> JSVal { fn Error(&self, _cx: *mut JSContext) -> JSVal {
self.error.get() self.error.get()
} }

View file

@ -9,7 +9,7 @@ use dom::bindings::error::Fallible;
use dom::bindings::global::GlobalRef; use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::eventtarget::{EventTarget, EventTargetHelpers}; use dom::eventtarget::EventTarget;
use dom::uievent::{UIEventTypeId}; use dom::uievent::{UIEventTypeId};
use util::str::DOMString; use util::str::DOMString;
@ -54,7 +54,6 @@ pub enum EventCancelable {
} }
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct Event { pub struct Event {
reflector_: Reflector, reflector_: Reflector,
type_id: EventTypeId, type_id: EventTypeId,
@ -173,67 +172,67 @@ impl Event {
} }
} }
impl<'a> EventMethods for &'a Event { impl EventMethods for Event {
// https://dom.spec.whatwg.org/#dom-event-eventphase // https://dom.spec.whatwg.org/#dom-event-eventphase
fn EventPhase(self) -> u16 { fn EventPhase(&self) -> u16 {
self.phase.get() as u16 self.phase.get() as u16
} }
// https://dom.spec.whatwg.org/#dom-event-type // https://dom.spec.whatwg.org/#dom-event-type
fn Type(self) -> DOMString { fn Type(&self) -> DOMString {
self.type_.borrow().clone() self.type_.borrow().clone()
} }
// https://dom.spec.whatwg.org/#dom-event-target // https://dom.spec.whatwg.org/#dom-event-target
fn GetTarget(self) -> Option<Root<EventTarget>> { fn GetTarget(&self) -> Option<Root<EventTarget>> {
self.target.get().map(Root::from_rooted) self.target.get().map(Root::from_rooted)
} }
// https://dom.spec.whatwg.org/#dom-event-currenttarget // https://dom.spec.whatwg.org/#dom-event-currenttarget
fn GetCurrentTarget(self) -> Option<Root<EventTarget>> { fn GetCurrentTarget(&self) -> Option<Root<EventTarget>> {
self.current_target.get().map(Root::from_rooted) self.current_target.get().map(Root::from_rooted)
} }
// https://dom.spec.whatwg.org/#dom-event-defaultprevented // https://dom.spec.whatwg.org/#dom-event-defaultprevented
fn DefaultPrevented(self) -> bool { fn DefaultPrevented(&self) -> bool {
self.canceled.get() self.canceled.get()
} }
// https://dom.spec.whatwg.org/#dom-event-preventdefault // https://dom.spec.whatwg.org/#dom-event-preventdefault
fn PreventDefault(self) { fn PreventDefault(&self) {
if self.cancelable.get() { if self.cancelable.get() {
self.canceled.set(true) self.canceled.set(true)
} }
} }
// https://dom.spec.whatwg.org/#dom-event-stoppropagation // https://dom.spec.whatwg.org/#dom-event-stoppropagation
fn StopPropagation(self) { fn StopPropagation(&self) {
self.stop_propagation.set(true); self.stop_propagation.set(true);
} }
// https://dom.spec.whatwg.org/#dom-event-stopimmediatepropagation // https://dom.spec.whatwg.org/#dom-event-stopimmediatepropagation
fn StopImmediatePropagation(self) { fn StopImmediatePropagation(&self) {
self.stop_immediate.set(true); self.stop_immediate.set(true);
self.stop_propagation.set(true); self.stop_propagation.set(true);
} }
// https://dom.spec.whatwg.org/#dom-event-bubbles // https://dom.spec.whatwg.org/#dom-event-bubbles
fn Bubbles(self) -> bool { fn Bubbles(&self) -> bool {
self.bubbles.get() self.bubbles.get()
} }
// https://dom.spec.whatwg.org/#dom-event-cancelable // https://dom.spec.whatwg.org/#dom-event-cancelable
fn Cancelable(self) -> bool { fn Cancelable(&self) -> bool {
self.cancelable.get() self.cancelable.get()
} }
// https://dom.spec.whatwg.org/#dom-event-timestamp // https://dom.spec.whatwg.org/#dom-event-timestamp
fn TimeStamp(self) -> u64 { fn TimeStamp(&self) -> u64 {
self.timestamp self.timestamp
} }
// https://dom.spec.whatwg.org/#dom-event-initevent // https://dom.spec.whatwg.org/#dom-event-initevent
fn InitEvent(self, fn InitEvent(&self,
type_: DOMString, type_: DOMString,
bubbles: bool, bubbles: bool,
cancelable: bool) { cancelable: bool) {
@ -253,23 +252,19 @@ impl<'a> EventMethods for &'a Event {
} }
// https://dom.spec.whatwg.org/#dom-event-istrusted // https://dom.spec.whatwg.org/#dom-event-istrusted
fn IsTrusted(self) -> bool { fn IsTrusted(&self) -> bool {
self.trusted.get() self.trusted.get()
} }
} }
pub trait EventHelpers {
fn set_trusted(self, trusted: bool);
fn fire(self, target: &EventTarget) -> bool;
}
impl<'a> EventHelpers for &'a Event { impl Event {
fn set_trusted(self, trusted: bool) { pub fn set_trusted(&self, trusted: bool) {
self.trusted.set(trusted); self.trusted.set(trusted);
} }
// https://html.spec.whatwg.org/multipage/#fire-a-simple-event // https://html.spec.whatwg.org/multipage/#fire-a-simple-event
fn fire(self, target: &EventTarget) -> bool { pub fn fire(&self, target: &EventTarget) -> bool {
self.set_trusted(true); self.set_trusted(true);
target.dispatch_event(self) target.dispatch_event(self)
} }

View file

@ -9,7 +9,7 @@ use dom::bindings::js::JS;
use dom::bindings::trace::RootedVec; use dom::bindings::trace::RootedVec;
use dom::event::{Event, EventPhase}; use dom::event::{Event, EventPhase};
use dom::eventtarget::{EventTarget, ListenerPhase}; use dom::eventtarget::{EventTarget, ListenerPhase};
use dom::node::{Node, NodeHelpers}; use dom::node::Node;
use dom::virtualmethods::vtable_for; use dom::virtualmethods::vtable_for;
// See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm // See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm

View file

@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods;
use dom::bindings::error::Error::InvalidState; use dom::bindings::error::Error::InvalidState;
use dom::bindings::error::{Fallible, report_pending_exception}; use dom::bindings::error::{Fallible, report_pending_exception};
use dom::bindings::utils::{Reflectable, Reflector}; use dom::bindings::utils::{Reflectable, Reflector};
use dom::event::{Event, EventHelpers}; use dom::event::Event;
use dom::eventdispatcher::dispatch_event; use dom::eventdispatcher::dispatch_event;
use dom::node::NodeTypeId; use dom::node::NodeTypeId;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
@ -130,7 +130,6 @@ pub struct EventListenerEntry {
} }
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct EventTarget { pub struct EventTarget {
reflector_: Reflector, reflector_: Reflector,
type_id: EventTargetTypeId, type_id: EventTargetTypeId,
@ -164,42 +163,18 @@ impl EventTarget {
pub fn type_id<'a>(&'a self) -> &'a EventTargetTypeId { pub fn type_id<'a>(&'a self) -> &'a EventTargetTypeId {
&self.type_id &self.type_id
} }
}
pub trait EventTargetHelpers { pub fn dispatch_event_with_target(&self,
fn dispatch_event_with_target(self,
target: &EventTarget,
event: &Event) -> bool;
fn dispatch_event(self, event: &Event) -> bool;
fn set_inline_event_listener(self,
ty: DOMString,
listener: Option<Rc<EventHandler>>);
fn get_inline_event_listener(self, ty: DOMString) -> Option<Rc<EventHandler>>;
fn set_event_handler_uncompiled(self,
cx: *mut JSContext,
url: Url,
scope: HandleObject,
ty: &str,
source: DOMString);
fn set_event_handler_common<T: CallbackContainer>(self, ty: &str,
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 &'a EventTarget {
fn dispatch_event_with_target(self,
target: &EventTarget, target: &EventTarget,
event: &Event) -> bool { event: &Event) -> bool {
dispatch_event(self, Some(target), event) dispatch_event(self, Some(target), event)
} }
fn dispatch_event(self, event: &Event) -> bool { pub fn dispatch_event(&self, event: &Event) -> bool {
dispatch_event(self, None, event) dispatch_event(self, None, event)
} }
fn set_inline_event_listener(self, pub fn set_inline_event_listener(&self,
ty: DOMString, ty: DOMString,
listener: Option<Rc<EventHandler>>) { listener: Option<Rc<EventHandler>>) {
let mut handlers = self.handlers.borrow_mut(); let mut handlers = self.handlers.borrow_mut();
@ -235,7 +210,7 @@ impl<'a> EventTargetHelpers for &'a EventTarget {
} }
} }
fn get_inline_event_listener(self, ty: DOMString) -> Option<Rc<EventHandler>> { pub fn get_inline_event_listener(&self, ty: DOMString) -> Option<Rc<EventHandler>> {
let handlers = self.handlers.borrow(); let handlers = self.handlers.borrow();
let entries = handlers.get(&ty); let entries = handlers.get(&ty);
entries.and_then(|entries| entries.iter().filter_map(|entry| { entries.and_then(|entries| entries.iter().filter_map(|entry| {
@ -247,7 +222,7 @@ impl<'a> EventTargetHelpers for &'a EventTarget {
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn set_event_handler_uncompiled(self, pub fn set_event_handler_uncompiled(&self,
cx: *mut JSContext, cx: *mut JSContext,
url: Url, url: Url,
scope: HandleObject, scope: HandleObject,
@ -288,27 +263,27 @@ impl<'a> EventTargetHelpers for &'a EventTarget {
self.set_event_handler_common(ty, Some(EventHandlerNonNull::new(funobj))); self.set_event_handler_common(ty, Some(EventHandlerNonNull::new(funobj)));
} }
fn set_event_handler_common<T: CallbackContainer>( pub fn set_event_handler_common<T: CallbackContainer>(
self, ty: &str, listener: Option<Rc<T>>) &self, ty: &str, listener: Option<Rc<T>>)
{ {
let event_listener = listener.map(|listener| let event_listener = listener.map(|listener|
EventHandlerNonNull::new(listener.callback())); EventHandlerNonNull::new(listener.callback()));
self.set_inline_event_listener(ty.to_owned(), event_listener); self.set_inline_event_listener(ty.to_owned(), event_listener);
} }
fn get_event_handler_common<T: CallbackContainer>(self, ty: &str) -> Option<Rc<T>> { pub fn get_event_handler_common<T: CallbackContainer>(&self, ty: &str) -> Option<Rc<T>> {
let listener = self.get_inline_event_listener(ty.to_owned()); let listener = self.get_inline_event_listener(ty.to_owned());
listener.map(|listener| CallbackContainer::new(listener.parent.callback())) listener.map(|listener| CallbackContainer::new(listener.parent.callback()))
} }
fn has_handlers(self) -> bool { pub fn has_handlers(&self) -> bool {
!self.handlers.borrow().is_empty() !self.handlers.borrow().is_empty()
} }
} }
impl<'a> EventTargetMethods for &'a EventTarget { impl EventTargetMethods for EventTarget {
// https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener // https://dom.spec.whatwg.org/#dom-eventtarget-addeventlistener
fn AddEventListener(self, fn AddEventListener(&self,
ty: DOMString, ty: DOMString,
listener: Option<Rc<EventListener>>, listener: Option<Rc<EventListener>>,
capture: bool) { capture: bool) {
@ -334,7 +309,7 @@ impl<'a> EventTargetMethods for &'a EventTarget {
} }
// https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener // https://dom.spec.whatwg.org/#dom-eventtarget-removeeventlistener
fn RemoveEventListener(self, fn RemoveEventListener(&self,
ty: DOMString, ty: DOMString,
listener: Option<Rc<EventListener>>, listener: Option<Rc<EventListener>>,
capture: bool) { capture: bool) {
@ -358,7 +333,7 @@ impl<'a> EventTargetMethods for &'a EventTarget {
} }
// https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent // https://dom.spec.whatwg.org/#dom-eventtarget-dispatchevent
fn DispatchEvent(self, event: &Event) -> Fallible<bool> { fn DispatchEvent(&self, event: &Event) -> Fallible<bool> {
if event.dispatching() || !event.initialized() { if event.dispatching() || !event.initialized() {
return Err(InvalidState); return Err(InvalidState);
} }
@ -367,7 +342,7 @@ impl<'a> EventTargetMethods for &'a EventTarget {
} }
} }
impl<'a> VirtualMethods for &'a EventTarget { impl VirtualMethods for EventTarget {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
None None
} }

View file

@ -11,7 +11,6 @@ use dom::blob::{Blob, BlobTypeId};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct File { pub struct File {
blob: Blob, blob: Blob,
name: DOMString, name: DOMString,
@ -40,10 +39,9 @@ impl File {
} }
} }
impl<'a> FileMethods for &'a File { impl FileMethods for File {
// https://w3c.github.io/FileAPI/#dfn-name // https://w3c.github.io/FileAPI/#dfn-name
fn Name(self) -> DOMString { fn Name(&self) -> DOMString {
self.name.clone() self.name.clone()
} }
} }

View file

@ -12,7 +12,6 @@ use dom::window::Window;
// https://w3c.github.io/FileAPI/#dfn-filelist // https://w3c.github.io/FileAPI/#dfn-filelist
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct FileList { pub struct FileList {
reflector_: Reflector, reflector_: Reflector,
list: Vec<JS<File>> list: Vec<JS<File>>
@ -31,22 +30,21 @@ impl FileList {
} }
} }
impl<'a> FileListMethods for &'a FileList { impl FileListMethods for FileList {
// https://w3c.github.io/FileAPI/#dfn-length // https://w3c.github.io/FileAPI/#dfn-length
fn Length(self) -> u32 { fn Length(&self) -> u32 {
self.list.len() as u32 self.list.len() as u32
} }
// https://w3c.github.io/FileAPI/#dfn-item // https://w3c.github.io/FileAPI/#dfn-item
fn Item(self, index: u32) -> Option<Root<File>> { fn Item(&self, index: u32) -> Option<Root<File>> {
Some(self.list[index as usize].root()) Some(self.list[index as usize].root())
} }
// check-tidy: no specs after this line // check-tidy: no specs after this line
fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<Root<File>> { fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<File>> {
let item = self.Item(index); let item = self.Item(index);
*found = item.is_some(); *found = item.is_some();
item item
} }
} }

View file

@ -12,16 +12,17 @@ use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{Root, JS, MutNullableHeap}; use dom::bindings::js::{Root, JS, MutNullableHeap};
use dom::bindings::refcounted::Trusted; use dom::bindings::refcounted::Trusted;
use dom::bindings::utils::{reflect_dom_object, Reflectable}; use dom::bindings::utils::{reflect_dom_object, Reflectable};
use dom::blob::{Blob, BlobHelpers}; use dom::blob::Blob;
use dom::domexception::{DOMException, DOMErrorName}; use dom::domexception::{DOMException, DOMErrorName};
use dom::event::{EventHelpers, EventCancelable, EventBubbles}; use dom::event::{EventCancelable, EventBubbles};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::progressevent::ProgressEvent; use dom::progressevent::ProgressEvent;
use encoding::all::UTF_8; use encoding::all::UTF_8;
use encoding::label::encoding_from_whatwg_label; use encoding::label::encoding_from_whatwg_label;
use encoding::types::{EncodingRef, DecoderTrap}; use encoding::types::{EncodingRef, DecoderTrap};
use hyper::mime::{Mime, Attr}; use hyper::mime::{Mime, Attr};
use rustc_serialize::base64::{Config, ToBase64, CharacterSet, Newline}; use rustc_serialize::base64::{Config, ToBase64, CharacterSet, Newline};
use script_task::ScriptTaskEventCategory::FileRead;
use script_task::{ScriptChan, Runnable, ScriptPort, CommonScriptMsg}; use script_task::{ScriptChan, Runnable, ScriptPort, CommonScriptMsg};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::sync::mpsc; use std::sync::mpsc;
@ -67,7 +68,6 @@ pub enum FileReaderReadyState {
} }
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct FileReader { pub struct FileReader {
eventtarget: EventTarget, eventtarget: EventTarget,
global: GlobalField, global: GlobalField,
@ -252,27 +252,38 @@ impl FileReader {
} }
} }
impl<'a> FileReaderMethods for &'a FileReader { impl FileReaderMethods for FileReader {
// https://w3c.github.io/FileAPI/#dfn-onloadstart
event_handler!(loadstart, GetOnloadstart, SetOnloadstart); event_handler!(loadstart, GetOnloadstart, SetOnloadstart);
// https://w3c.github.io/FileAPI/#dfn-onprogress
event_handler!(progress, GetOnprogress, SetOnprogress); event_handler!(progress, GetOnprogress, SetOnprogress);
// https://w3c.github.io/FileAPI/#dfn-onload
event_handler!(load, GetOnload, SetOnload); event_handler!(load, GetOnload, SetOnload);
// https://w3c.github.io/FileAPI/#dfn-onabort
event_handler!(abort, GetOnabort, SetOnabort); event_handler!(abort, GetOnabort, SetOnabort);
// https://w3c.github.io/FileAPI/#dfn-onerror
event_handler!(error, GetOnerror, SetOnerror); event_handler!(error, GetOnerror, SetOnerror);
// https://w3c.github.io/FileAPI/#dfn-onloadend
event_handler!(loadend, GetOnloadend, SetOnloadend); event_handler!(loadend, GetOnloadend, SetOnloadend);
//TODO https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer //TODO https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer
// https://w3c.github.io/FileAPI/#dfn-readAsDataURL // https://w3c.github.io/FileAPI/#dfn-readAsDataURL
fn ReadAsDataURL(self, blob: &Blob) -> ErrorResult { fn ReadAsDataURL(&self, blob: &Blob) -> ErrorResult {
self.read(FileReaderFunction::ReadAsDataUrl, blob, None) self.read(FileReaderFunction::ReadAsDataUrl, blob, None)
} }
// https://w3c.github.io/FileAPI/#dfn-readAsText // https://w3c.github.io/FileAPI/#dfn-readAsText
fn ReadAsText(self, blob: &Blob, label: Option<DOMString>) -> ErrorResult { fn ReadAsText(&self, blob: &Blob, label: Option<DOMString>) -> ErrorResult {
self.read(FileReaderFunction::ReadAsText, blob, label) self.read(FileReaderFunction::ReadAsText, blob, label)
} }
// https://w3c.github.io/FileAPI/#dfn-abort // https://w3c.github.io/FileAPI/#dfn-abort
fn Abort(self) { fn Abort(&self) {
// Step 2 // Step 2
if self.ready_state.get() == FileReaderReadyState::Loading { if self.ready_state.get() == FileReaderReadyState::Loading {
self.change_ready_state(FileReaderReadyState::Done); self.change_ready_state(FileReaderReadyState::Done);
@ -291,30 +302,24 @@ impl<'a> FileReaderMethods for &'a FileReader {
} }
// https://w3c.github.io/FileAPI/#dfn-error // https://w3c.github.io/FileAPI/#dfn-error
fn GetError(self) -> Option<Root<DOMException>> { fn GetError(&self) -> Option<Root<DOMException>> {
self.error.get().map(|error| error.root()) self.error.get().map(|error| error.root())
} }
// https://w3c.github.io/FileAPI/#dfn-result // https://w3c.github.io/FileAPI/#dfn-result
fn GetResult(self) -> Option<DOMString> { fn GetResult(&self) -> Option<DOMString> {
self.result.borrow().clone() self.result.borrow().clone()
} }
// https://w3c.github.io/FileAPI/#dfn-readyState // https://w3c.github.io/FileAPI/#dfn-readyState
fn ReadyState(self) -> u16 { fn ReadyState(&self) -> u16 {
self.ready_state.get() as u16 self.ready_state.get() as u16
} }
} }
trait PrivateFileReaderHelpers {
fn dispatch_progress_event(self, type_: DOMString, loaded: u64, total: Option<u64>);
fn terminate_ongoing_reading(self);
fn read(self, function: FileReaderFunction, blob: &Blob, label: Option<DOMString>) -> ErrorResult;
fn change_ready_state(self, state: FileReaderReadyState);
}
impl<'a> PrivateFileReaderHelpers for &'a FileReader { impl FileReader {
fn dispatch_progress_event(self, type_: DOMString, loaded: u64, total: Option<u64>) { fn dispatch_progress_event(&self, type_: DOMString, loaded: u64, total: Option<u64>) {
let global = self.global.root(); let global = self.global.root();
let progressevent = ProgressEvent::new(global.r(), let progressevent = ProgressEvent::new(global.r(),
@ -326,12 +331,12 @@ impl<'a> PrivateFileReaderHelpers for &'a FileReader {
event.fire(target); event.fire(target);
} }
fn terminate_ongoing_reading(self) { fn terminate_ongoing_reading(&self) {
let GenerationId(prev_id) = self.generation_id.get(); let GenerationId(prev_id) = self.generation_id.get();
self.generation_id.set(GenerationId(prev_id + 1)); self.generation_id.set(GenerationId(prev_id + 1));
} }
fn read(self, function: FileReaderFunction, blob: &Blob, label: Option<DOMString>) -> ErrorResult { fn read(&self, function: FileReaderFunction, blob: &Blob, label: Option<DOMString>) -> ErrorResult {
let root = self.global.root(); let root = self.global.root();
let global = root.r(); let global = root.r();
// Step 1 // Step 1
@ -369,7 +374,7 @@ impl<'a> PrivateFileReaderHelpers for &'a FileReader {
Ok(()) Ok(())
} }
fn change_ready_state(self, state: FileReaderReadyState) { fn change_ready_state(&self, state: FileReaderReadyState) {
self.ready_state.set(state); self.ready_state.set(state);
} }
} }
@ -408,22 +413,22 @@ fn perform_annotated_read_operation(gen_id: GenerationId, data: ReadMetaData, bl
let chan = &script_chan; let chan = &script_chan;
// Step 4 // Step 4
let task = box FileReaderEvent::ProcessRead(filereader.clone(), gen_id); let task = box FileReaderEvent::ProcessRead(filereader.clone(), gen_id);
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
let task = box FileReaderEvent::ProcessReadData(filereader.clone(), let task = box FileReaderEvent::ProcessReadData(filereader.clone(),
gen_id, DOMString::new()); gen_id, DOMString::new());
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
let bytes = match blob_contents.recv() { let bytes = match blob_contents.recv() {
Ok(bytes) => bytes, Ok(bytes) => bytes,
Err(_) => { Err(_) => {
let task = box FileReaderEvent::ProcessReadError(filereader, let task = box FileReaderEvent::ProcessReadError(filereader,
gen_id, DOMErrorName::NotFoundError); gen_id, DOMErrorName::NotFoundError);
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
return; return;
} }
}; };
let task = box FileReaderEvent::ProcessReadEOF(filereader, gen_id, data, bytes); let task = box FileReaderEvent::ProcessReadEOF(filereader, gen_id, data, bytes);
chan.send(CommonScriptMsg::RunnableMsg(task)).unwrap(); chan.send(CommonScriptMsg::RunnableMsg(FileRead, task)).unwrap();
} }

View file

@ -30,7 +30,6 @@ pub enum FormDatum {
} }
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct FormData { pub struct FormData {
reflector_: Reflector, reflector_: Reflector,
data: DOMRefCell<HashMap<DOMString, Vec<FormDatum>>>, data: DOMRefCell<HashMap<DOMString, Vec<FormDatum>>>,
@ -58,10 +57,10 @@ impl FormData {
} }
} }
impl<'a> FormDataMethods for &'a FormData { impl FormDataMethods for FormData {
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
// https://xhr.spec.whatwg.org/#dom-formdata-append // https://xhr.spec.whatwg.org/#dom-formdata-append
fn Append(self, name: DOMString, value: &Blob, filename: Option<DOMString>) { fn Append(&self, name: DOMString, value: &Blob, filename: Option<DOMString>) {
let file = FormDatum::FileData(JS::from_rooted(&self.get_file_from_blob(value, filename))); let file = FormDatum::FileData(JS::from_rooted(&self.get_file_from_blob(value, filename)));
let mut data = self.data.borrow_mut(); let mut data = self.data.borrow_mut();
match data.entry(name) { match data.entry(name) {
@ -73,7 +72,7 @@ impl<'a> FormDataMethods for &'a FormData {
} }
// https://xhr.spec.whatwg.org/#dom-formdata-append // https://xhr.spec.whatwg.org/#dom-formdata-append
fn Append_(self, name: DOMString, value: DOMString) { fn Append_(&self, name: DOMString, value: DOMString) {
let mut data = self.data.borrow_mut(); let mut data = self.data.borrow_mut();
match data.entry(name) { match data.entry(name) {
Occupied(entry) => entry.into_mut().push(FormDatum::StringData(value)), Occupied(entry) => entry.into_mut().push(FormDatum::StringData(value)),
@ -82,51 +81,41 @@ impl<'a> FormDataMethods for &'a FormData {
} }
// https://xhr.spec.whatwg.org/#dom-formdata-delete // https://xhr.spec.whatwg.org/#dom-formdata-delete
fn Delete(self, name: DOMString) { fn Delete(&self, name: DOMString) {
self.data.borrow_mut().remove(&name); self.data.borrow_mut().remove(&name);
} }
#[allow(unsafe_code)]
// https://xhr.spec.whatwg.org/#dom-formdata-get // https://xhr.spec.whatwg.org/#dom-formdata-get
fn Get(self, name: DOMString) -> Option<FileOrString> { fn Get(&self, name: DOMString) -> Option<FileOrString> {
// FIXME(https://github.com/rust-lang/rust/issues/23338) self.data.borrow()
let data = self.data.borrow(); .get(&name)
if data.contains_key(&name) { .map(|entry| match entry[0] {
match data[&name][0].clone() { FormDatum::StringData(ref s) => eString(s.clone()),
FormDatum::StringData(ref s) => Some(eString(s.clone())), FormDatum::FileData(ref f) => eFile(f.root()),
FormDatum::FileData(ref f) => { })
Some(eFile(f.root()))
}
}
} else {
None
}
} }
// https://xhr.spec.whatwg.org/#dom-formdata-has // https://xhr.spec.whatwg.org/#dom-formdata-has
fn Has(self, name: DOMString) -> bool { fn Has(&self, name: DOMString) -> bool {
self.data.borrow().contains_key(&name) self.data.borrow().contains_key(&name)
} }
// https://xhr.spec.whatwg.org/#dom-formdata-set // https://xhr.spec.whatwg.org/#dom-formdata-set
fn Set_(self, name: DOMString, value: DOMString) { fn Set_(&self, name: DOMString, value: DOMString) {
self.data.borrow_mut().insert(name, vec!(FormDatum::StringData(value))); self.data.borrow_mut().insert(name, vec!(FormDatum::StringData(value)));
} }
#[allow(unrooted_must_root)] #[allow(unrooted_must_root)]
// https://xhr.spec.whatwg.org/#dom-formdata-set // https://xhr.spec.whatwg.org/#dom-formdata-set
fn Set(self, name: DOMString, value: &Blob, filename: Option<DOMString>) { fn Set(&self, name: DOMString, value: &Blob, filename: Option<DOMString>) {
let file = FormDatum::FileData(JS::from_rooted(&self.get_file_from_blob(value, filename))); let file = FormDatum::FileData(JS::from_rooted(&self.get_file_from_blob(value, filename)));
self.data.borrow_mut().insert(name, vec!(file)); self.data.borrow_mut().insert(name, vec!(file));
} }
} }
trait PrivateFormDataHelpers {
fn get_file_from_blob(self, value: &Blob, filename: Option<DOMString>) -> Root<File>;
}
impl<'a> PrivateFormDataHelpers for &'a FormData { impl FormData {
fn get_file_from_blob(self, value: &Blob, filename: Option<DOMString>) -> Root<File> { fn get_file_from_blob(&self, value: &Blob, filename: Option<DOMString>) -> Root<File> {
let global = self.global.root(); let global = self.global.root();
let f: Option<&File> = FileCast::to_ref(value); let f: Option<&File> = FileCast::to_ref(value);
let name = filename.unwrap_or(f.map(|inner| inner.name().clone()).unwrap_or("blob".to_owned())); let name = filename.unwrap_or(f.map(|inner| inner.name().clone()).unwrap_or("blob".to_owned()));

View file

@ -14,15 +14,14 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLImageElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementDerived, HTMLImageElementDerived};
use dom::bindings::codegen::InheritTypes::{MouseEventCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{MouseEventCast, NodeCast};
use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::document::{Document, DocumentHelpers}; use dom::document::Document;
use dom::domtokenlist::DOMTokenList; use dom::domtokenlist::DOMTokenList;
use dom::element::{Element, AttributeHandlers, ElementTypeId}; use dom::element::{Element, ElementTypeId};
use dom::event::Event; use dom::event::Event;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{Node, NodeHelpers, NodeTypeId, document_from_node, window_from_node}; use dom::node::{Node, NodeTypeId, document_from_node, window_from_node};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;
use util::str::DOMString; use util::str::DOMString;
@ -33,7 +32,6 @@ use url::UrlParser;
use std::default::Default; use std::default::Default;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLAnchorElement { pub struct HTMLAnchorElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
rel_list: MutNullableHeap<JS<DOMTokenList>>, rel_list: MutNullableHeap<JS<DOMTokenList>>,
@ -67,9 +65,9 @@ impl HTMLAnchorElement {
} }
} }
impl<'a> VirtualMethods for &'a HTMLAnchorElement { impl VirtualMethods for HTMLAnchorElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &HTMLElement = HTMLElementCast::from_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
@ -81,30 +79,30 @@ impl<'a> VirtualMethods for &'a HTMLAnchorElement {
} }
} }
impl<'a> HTMLAnchorElementMethods for &'a HTMLAnchorElement { impl HTMLAnchorElementMethods for HTMLAnchorElement {
// https://html.spec.whatwg.org/multipage/#dom-a-text // https://html.spec.whatwg.org/multipage/#dom-a-text
fn Text(self) -> DOMString { fn Text(&self) -> DOMString {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.GetTextContent().unwrap() node.GetTextContent().unwrap()
} }
// https://html.spec.whatwg.org/multipage/#dom-a-text // https://html.spec.whatwg.org/multipage/#dom-a-text
fn SetText(self, value: DOMString) { fn SetText(&self, value: DOMString) {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
node.SetTextContent(Some(value)) node.SetTextContent(Some(value))
} }
// https://html.spec.whatwg.org/multipage/#dom-a-rellist // https://html.spec.whatwg.org/multipage/#dom-a-rellist
fn RelList(self) -> Root<DOMTokenList> { fn RelList(&self) -> Root<DOMTokenList> {
self.rel_list.or_init(|| { self.rel_list.or_init(|| {
DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel")) DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel"))
}) })
} }
} }
impl<'a> Activatable for &'a HTMLAnchorElement { impl Activatable for HTMLAnchorElement {
fn as_element<'b>(&'b self) -> &'b Element { fn as_element<'b>(&'b self) -> &'b Element {
ElementCast::from_ref(*self) ElementCast::from_ref(self)
} }
fn is_instance_activatable(&self) -> bool { fn is_instance_activatable(&self) -> bool {
@ -113,7 +111,7 @@ impl<'a> Activatable for &'a HTMLAnchorElement {
// hyperlink" // hyperlink"
// https://html.spec.whatwg.org/multipage/#the-a-element // https://html.spec.whatwg.org/multipage/#the-a-element
// "The activation behaviour of a elements *that create hyperlinks*" // "The activation behaviour of a elements *that create hyperlinks*"
ElementCast::from_ref(*self).has_attribute(&atom!("href")) ElementCast::from_ref(self).has_attribute(&atom!("href"))
} }
@ -129,13 +127,13 @@ impl<'a> Activatable for &'a HTMLAnchorElement {
//https://html.spec.whatwg.org/multipage/#the-a-element:activation-behaviour //https://html.spec.whatwg.org/multipage/#the-a-element:activation-behaviour
fn activation_behavior(&self, event: &Event, target: &EventTarget) { fn activation_behavior(&self, event: &Event, target: &EventTarget) {
//Step 1. If the node document is not fully active, abort. //Step 1. If the node document is not fully active, abort.
let doc = document_from_node(*self); let doc = document_from_node(self);
if !doc.r().is_fully_active() { if !doc.r().is_fully_active() {
return; return;
} }
//TODO: Step 2. Check if browsing context is specified and act accordingly. //TODO: Step 2. Check if browsing context is specified and act accordingly.
//Step 3. Handle <img ismap/>. //Step 3. Handle <img ismap/>.
let element = ElementCast::from_ref(*self); let element = ElementCast::from_ref(self);
let mouse_event = MouseEventCast::to_ref(event).unwrap(); let mouse_event = MouseEventCast::to_ref(event).unwrap();
let mut ismap_suffix = None; let mut ismap_suffix = None;
if let Some(element) = ElementCast::to_ref(target) { if let Some(element) = ElementCast::to_ref(target) {

View file

@ -10,7 +10,7 @@ use dom::bindings::codegen::InheritTypes::HTMLAppletElementDerived;
use dom::bindings::codegen::InheritTypes::HTMLElementCast; use dom::bindings::codegen::InheritTypes::HTMLElementCast;
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::{AttributeHandlers, ElementTypeId}; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{Node, NodeTypeId}; use dom::node::{Node, NodeTypeId};
@ -20,7 +20,6 @@ use string_cache::Atom;
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLAppletElement { pub struct HTMLAppletElement {
htmlelement: HTMLElement htmlelement: HTMLElement
} }
@ -52,15 +51,17 @@ impl HTMLAppletElement {
} }
} }
impl<'a> HTMLAppletElementMethods for &'a HTMLAppletElement { impl HTMLAppletElementMethods for HTMLAppletElement {
// https://html.spec.whatwg.org/#the-applet-element:dom-applet-name // https://html.spec.whatwg.org/#the-applet-element:dom-applet-name
make_getter!(Name); make_getter!(Name);
// https://html.spec.whatwg.org/#the-applet-element:dom-applet-name
make_atomic_setter!(SetName, "name"); make_atomic_setter!(SetName, "name");
} }
impl<'a> VirtualMethods for &'a HTMLAppletElement { impl VirtualMethods for HTMLAppletElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
Some(HTMLElementCast::from_borrowed_ref(self) as &VirtualMethods) Some(HTMLElementCast::from_ref(self) as &VirtualMethods)
} }
fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue { fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {

View file

@ -14,7 +14,7 @@ use dom::domtokenlist::DOMTokenList;
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{Node, NodeHelpers, NodeTypeId}; use dom::node::{Node, NodeTypeId};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use std::default::Default; use std::default::Default;
@ -22,7 +22,6 @@ use string_cache::Atom;
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLAreaElement { pub struct HTMLAreaElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
rel_list: MutNullableHeap<JS<DOMTokenList>>, rel_list: MutNullableHeap<JS<DOMTokenList>>,
@ -53,9 +52,9 @@ impl HTMLAreaElement {
} }
} }
impl<'a> VirtualMethods for &'a HTMLAreaElement { impl VirtualMethods for HTMLAreaElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &HTMLElement = HTMLElementCast::from_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
@ -67,9 +66,9 @@ impl<'a> VirtualMethods for &'a HTMLAreaElement {
} }
} }
impl<'a> HTMLAreaElementMethods for &'a HTMLAreaElement { impl HTMLAreaElementMethods for HTMLAreaElement {
// https://html.spec.whatwg.org/multipage/#dom-area-rellist // https://html.spec.whatwg.org/multipage/#dom-area-rellist
fn RelList(self) -> Root<DOMTokenList> { fn RelList(&self) -> Root<DOMTokenList> {
self.rel_list.or_init(|| { self.rel_list.or_init(|| {
DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel")) DOMTokenList::new(ElementCast::from_ref(self), &atom!("rel"))
}) })

View file

@ -14,7 +14,6 @@ use dom::node::{Node, NodeTypeId};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLAudioElement { pub struct HTMLAudioElement {
htmlmediaelement: HTMLMediaElement htmlmediaelement: HTMLMediaElement
} }
@ -46,4 +45,3 @@ impl HTMLAudioElement {
Node::reflect_node(box element, document, HTMLAudioElementBinding::Wrap) Node::reflect_node(box element, document, HTMLAudioElementBinding::Wrap)
} }
} }

View file

@ -2,14 +2,14 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::attr::{Attr, AttrHelpers}; use dom::attr::Attr;
use dom::bindings::codegen::Bindings::HTMLBaseElementBinding; use dom::bindings::codegen::Bindings::HTMLBaseElementBinding;
use dom::bindings::codegen::InheritTypes::ElementCast; use dom::bindings::codegen::InheritTypes::ElementCast;
use dom::bindings::codegen::InheritTypes::HTMLBaseElementDerived; use dom::bindings::codegen::InheritTypes::HTMLBaseElementDerived;
use dom::bindings::codegen::InheritTypes::HTMLElementCast; use dom::bindings::codegen::InheritTypes::HTMLElementCast;
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::document::{Document, DocumentHelpers}; use dom::document::Document;
use dom::element::{ElementTypeId, AttributeHandlers}; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{Node, NodeTypeId, document_from_node}; use dom::node::{Node, NodeTypeId, document_from_node};
@ -19,7 +19,6 @@ use util::str::DOMString;
use url::{Url, UrlParser}; use url::{Url, UrlParser};
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLBaseElement { pub struct HTMLBaseElement {
htmlelement: HTMLElement htmlelement: HTMLElement
} }
@ -80,9 +79,9 @@ impl HTMLBaseElement {
} }
} }
impl<'a> VirtualMethods for &'a HTMLBaseElement { impl VirtualMethods for HTMLBaseElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
Some(HTMLElementCast::from_borrowed_ref(self) as &VirtualMethods) Some(HTMLElementCast::from_ref(self) as &VirtualMethods)
} }
fn after_set_attr(&self, attr: &Attr) { fn after_set_attr(&self, attr: &Attr) {

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::attr::{Attr, AttrHelpers}; use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell; use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{self, HTMLBodyElementMethods}; use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{self, HTMLBodyElementMethods};
@ -11,13 +11,12 @@ use dom::bindings::codegen::InheritTypes::{EventTargetCast};
use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLElementCast}; use dom::bindings::codegen::InheritTypes::{HTMLBodyElementDerived, HTMLElementCast};
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
use dom::document::{Document, DocumentHelpers}; use dom::document::Document;
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId, EventTargetHelpers}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{Node, NodeTypeId, window_from_node, document_from_node}; use dom::node::{Node, NodeTypeId, window_from_node, document_from_node};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;
use msg::constellation_msg::ConstellationChan; use msg::constellation_msg::ConstellationChan;
use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::Msg as ConstellationMsg;
@ -35,7 +34,6 @@ use time;
const INITIAL_REFLOW_DELAY: u64 = 200_000_000; const INITIAL_REFLOW_DELAY: u64 = 200_000_000;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLBodyElement { pub struct HTMLBodyElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
background_color: Cell<Option<RGBA>>, background_color: Cell<Option<RGBA>>,
@ -70,45 +68,43 @@ impl HTMLBodyElement {
} }
} }
impl<'a> HTMLBodyElementMethods for &'a HTMLBodyElement { impl HTMLBodyElementMethods for HTMLBodyElement {
// https://html.spec.whatwg.org/multipage#dom-body-bgcolor // https://html.spec.whatwg.org/multipage#dom-body-bgcolor
make_getter!(BgColor, "bgcolor"); make_getter!(BgColor, "bgcolor");
// https://html.spec.whatwg.org/multipage#dom-body-bgcolor
make_setter!(SetBgColor, "bgcolor"); make_setter!(SetBgColor, "bgcolor");
// https://html.spec.whatwg.org/multipage/#the-body-element // https://html.spec.whatwg.org/multipage/#the-body-element
fn GetOnunload(self) -> Option<Rc<EventHandlerNonNull>> { fn GetOnunload(&self) -> Option<Rc<EventHandlerNonNull>> {
let win = window_from_node(self); let win = window_from_node(self);
win.r().GetOnunload() win.r().GetOnunload()
} }
// https://html.spec.whatwg.org/multipage/#the-body-element // https://html.spec.whatwg.org/multipage/#the-body-element
fn SetOnunload(self, listener: Option<Rc<EventHandlerNonNull>>) { fn SetOnunload(&self, listener: Option<Rc<EventHandlerNonNull>>) {
let win = window_from_node(self); let win = window_from_node(self);
win.r().SetOnunload(listener) win.r().SetOnunload(listener)
} }
} }
pub trait HTMLBodyElementHelpers {
fn get_background_color(self) -> Option<RGBA>;
fn get_background(self) -> Option<Url>;
}
impl<'a> HTMLBodyElementHelpers for &'a HTMLBodyElement { impl HTMLBodyElement {
fn get_background_color(self) -> Option<RGBA> { pub fn get_background_color(&self) -> Option<RGBA> {
self.background_color.get() self.background_color.get()
} }
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn get_background(self) -> Option<Url> { pub fn get_background(&self) -> Option<Url> {
unsafe { unsafe {
self.background.borrow_for_layout().clone() self.background.borrow_for_layout().clone()
} }
} }
} }
impl<'a> VirtualMethods for &'a HTMLBodyElement { impl VirtualMethods for HTMLBodyElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let element: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self); let element: &HTMLElement = HTMLElementCast::from_ref(self);
Some(element as &VirtualMethods) Some(element as &VirtualMethods)
} }
@ -121,7 +117,7 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
return return
} }
let window = window_from_node(*self); let window = window_from_node(self);
let document = window.r().Document(); let document = window.r().Document();
document.r().set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY); document.r().set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY);
let ConstellationChan(ref chan) = window.r().constellation_chan(); let ConstellationChan(ref chan) = window.r().constellation_chan();
@ -141,7 +137,7 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
"onbeforeunload", "onhashchange", "onlanguagechange", "onmessage", "onbeforeunload", "onhashchange", "onlanguagechange", "onmessage",
"onoffline", "ononline", "onpagehide", "onpageshow", "onpopstate", "onoffline", "ononline", "onpagehide", "onpageshow", "onpopstate",
"onstorage", "onresize", "onunload", "onerror"]; "onstorage", "onresize", "onunload", "onerror"];
let window = window_from_node(*self); let window = window_from_node(self);
let (cx, url, reflector) = (window.r().get_cx(), let (cx, url, reflector) = (window.r().get_cx(),
window.r().get_url(), window.r().get_url(),
window.r().reflector().get_jsobject()); window.r().reflector().get_jsobject());
@ -149,7 +145,7 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
if FORWARDED_EVENTS.iter().any(|&event| &**name == event) { if FORWARDED_EVENTS.iter().any(|&event| &**name == event) {
EventTargetCast::from_ref(window.r()) EventTargetCast::from_ref(window.r())
} else { } else {
EventTargetCast::from_ref(*self) EventTargetCast::from_ref(self)
}; };
evtarget.set_event_handler_uncompiled(cx, url, reflector, evtarget.set_event_handler_uncompiled(cx, url, reflector,
&name[2..], &name[2..],
@ -161,7 +157,7 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
self.background_color.set(str::parse_legacy_color(&attr.value()).ok()) self.background_color.set(str::parse_legacy_color(&attr.value()).ok())
} }
&atom!("background") => { &atom!("background") => {
let doc = document_from_node(*self); let doc = document_from_node(self);
let base = doc.r().url(); let base = doc.r().url();
*self.background.borrow_mut() = UrlParser::new().base_url(&base).parse(&attr.value()).ok(); *self.background.borrow_mut() = UrlParser::new().base_url(&base).parse(&attr.value()).ok();
@ -183,4 +179,3 @@ impl<'a> VirtualMethods for &'a HTMLBodyElement {
} }
} }
} }

View file

@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLBRElement { pub struct HTMLBRElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
} }
@ -41,4 +40,3 @@ impl HTMLBRElement {
Node::reflect_node(box element, document, HTMLBRElementBinding::Wrap) Node::reflect_node(box element, document, HTMLBRElementBinding::Wrap)
} }
} }

View file

@ -4,21 +4,19 @@
use dom::activation::Activatable; use dom::activation::Activatable;
use dom::attr::Attr; use dom::attr::Attr;
use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding; use dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods; use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLButtonElementCast, NodeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLButtonElementCast, NodeCast};
use dom::bindings::codegen::InheritTypes::{HTMLButtonElementDerived, HTMLFieldSetElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLButtonElementDerived, HTMLFieldSetElementDerived};
use dom::bindings::js::Root; use dom::bindings::js::Root;
use dom::document::Document; use dom::document::Document;
use dom::element::ActivationElementHelpers; use dom::element::{Element, ElementTypeId};
use dom::element::{AttributeHandlers, Element, ElementTypeId};
use dom::event::Event; use dom::event::Event;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::htmlformelement::{FormSubmitter, FormControl, HTMLFormElementHelpers}; use dom::htmlformelement::{FormSubmitter, FormControl};
use dom::htmlformelement::{SubmittedFrom}; use dom::htmlformelement::{SubmittedFrom};
use dom::node::{DisabledStateHelpers, Node, NodeHelpers, NodeTypeId, document_from_node, window_from_node}; use dom::node::{Node, NodeTypeId, document_from_node, window_from_node};
use dom::validitystate::ValidityState; use dom::validitystate::ValidityState;
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
@ -38,7 +36,6 @@ enum ButtonType {
} }
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLButtonElement { pub struct HTMLButtonElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
button_type: Cell<ButtonType> button_type: Cell<ButtonType>
@ -73,9 +70,9 @@ impl HTMLButtonElement {
} }
} }
impl<'a> HTMLButtonElementMethods for &'a HTMLButtonElement { impl HTMLButtonElementMethods for HTMLButtonElement {
// https://html.spec.whatwg.org/multipage/#dom-cva-validity // https://html.spec.whatwg.org/multipage/#dom-cva-validity
fn Validity(self) -> Root<ValidityState> { fn Validity(&self) -> Root<ValidityState> {
let window = window_from_node(self); let window = window_from_node(self);
ValidityState::new(window.r()) ValidityState::new(window.r())
} }
@ -87,7 +84,7 @@ impl<'a> HTMLButtonElementMethods for &'a HTMLButtonElement {
make_bool_setter!(SetDisabled, "disabled"); make_bool_setter!(SetDisabled, "disabled");
// https://html.spec.whatwg.org/multipage/#dom-button-type // https://html.spec.whatwg.org/multipage/#dom-button-type
fn Type(self) -> DOMString { fn Type(&self) -> DOMString {
let elem = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
let mut ty = elem.get_string_attribute(&atom!("type")); let mut ty = elem.get_string_attribute(&atom!("type"));
ty.make_ascii_lowercase(); ty.make_ascii_lowercase();
@ -101,22 +98,29 @@ impl<'a> HTMLButtonElementMethods for &'a HTMLButtonElement {
// https://html.spec.whatwg.org/multipage/#dom-button-type // https://html.spec.whatwg.org/multipage/#dom-button-type
make_setter!(SetType, "type"); make_setter!(SetType, "type");
// https://html.spec.whatwg.org/multipage/#htmlbuttonelement // https://html.spec.whatwg.org/multipage/#dom-fs-formaction
make_url_or_base_getter!(FormAction); make_url_or_base_getter!(FormAction);
// https://html.spec.whatwg.org/multipage/#dom-fs-formaction
make_setter!(SetFormAction, "formaction"); make_setter!(SetFormAction, "formaction");
// https://html.spec.whatwg.org/multipage/#dom-fs-formenctype
make_enumerated_getter!( make_enumerated_getter!(
FormEnctype, "application/x-www-form-urlencoded", ("text/plain") | ("multipart/form-data")); FormEnctype, "application/x-www-form-urlencoded", ("text/plain") | ("multipart/form-data"));
// https://html.spec.whatwg.org/multipage/#dom-fs-formenctype
make_setter!(SetFormEnctype, "formenctype"); make_setter!(SetFormEnctype, "formenctype");
// https://html.spec.whatwg.org/multipage/#dom-fs-formmethod
make_enumerated_getter!(FormMethod, "get", ("post") | ("dialog")); make_enumerated_getter!(FormMethod, "get", ("post") | ("dialog"));
// https://html.spec.whatwg.org/multipage/#dom-fs-formmethod
make_setter!(SetFormMethod, "formmethod"); make_setter!(SetFormMethod, "formmethod");
// https://html.spec.whatwg.org/multipage/#dom-fs-formtarget
make_getter!(FormTarget); make_getter!(FormTarget);
// https://html.spec.whatwg.org/multipage/#dom-fs-formtarget
make_setter!(SetFormTarget, "formtarget"); make_setter!(SetFormTarget, "formtarget");
// https://html.spec.whatwg.org/multipage/#dom-fe-name // https://html.spec.whatwg.org/multipage/#dom-fe-name
@ -132,9 +136,9 @@ impl<'a> HTMLButtonElementMethods for &'a HTMLButtonElement {
make_setter!(SetValue, "value"); make_setter!(SetValue, "value");
} }
impl<'a> VirtualMethods for &'a HTMLButtonElement { impl VirtualMethods for HTMLButtonElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self); let htmlelement: &HTMLElement = HTMLElementCast::from_ref(self);
Some(htmlelement as &VirtualMethods) Some(htmlelement as &VirtualMethods)
} }
@ -145,7 +149,7 @@ impl<'a> VirtualMethods for &'a HTMLButtonElement {
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node = NodeCast::from_ref(*self); let node = NodeCast::from_ref(self);
node.set_disabled_state(true); node.set_disabled_state(true);
node.set_enabled_state(false); node.set_enabled_state(false);
}, },
@ -160,7 +164,7 @@ impl<'a> VirtualMethods for &'a HTMLButtonElement {
match attr.local_name() { match attr.local_name() {
&atom!("disabled") => { &atom!("disabled") => {
let node = NodeCast::from_ref(*self); let node = NodeCast::from_ref(self);
node.set_disabled_state(false); node.set_disabled_state(false);
node.set_enabled_state(true); node.set_enabled_state(true);
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
@ -174,7 +178,7 @@ impl<'a> VirtualMethods for &'a HTMLButtonElement {
s.bind_to_tree(tree_in_doc); s.bind_to_tree(tree_in_doc);
} }
let node = NodeCast::from_ref(*self); let node = NodeCast::from_ref(self);
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} }
@ -183,7 +187,7 @@ impl<'a> VirtualMethods for &'a HTMLButtonElement {
s.unbind_from_tree(tree_in_doc); s.unbind_from_tree(tree_in_doc);
} }
let node = NodeCast::from_ref(*self); let node = NodeCast::from_ref(self);
if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) { if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) {
node.check_ancestors_disabled_state_for_form_control(); node.check_ancestors_disabled_state_for_form_control();
} else { } else {
@ -253,4 +257,3 @@ impl<'a> Activatable for &'a HTMLButtonElement {
} }
} }
} }

View file

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::attr::Attr; use dom::attr::Attr;
use dom::attr::AttrHelpers;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
@ -15,7 +14,6 @@ use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, HeapGCValue, Root};
use dom::bindings::utils::{Reflectable}; use dom::bindings::utils::{Reflectable};
use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
use dom::document::Document; use dom::document::Document;
use dom::element::AttributeHandlers;
use dom::element::ElementTypeId; use dom::element::ElementTypeId;
use dom::eventtarget::{EventTarget, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId}; use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
@ -47,7 +45,6 @@ pub enum CanvasContext {
impl HeapGCValue for CanvasContext {} impl HeapGCValue for CanvasContext {}
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLCanvasElement { pub struct HTMLCanvasElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
context: MutNullableHeap<CanvasContext>, context: MutNullableHeap<CanvasContext>,
@ -154,17 +151,9 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> {
} }
} }
pub trait HTMLCanvasElementHelpers {
fn get_or_init_2d_context(self) -> Option<Root<CanvasRenderingContext2D>>;
fn get_or_init_webgl_context(self,
cx: *mut JSContext,
attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>>;
fn is_valid(self) -> bool; impl HTMLCanvasElement {
} pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> {
impl<'a> HTMLCanvasElementHelpers for &'a HTMLCanvasElement {
fn get_or_init_2d_context(self) -> Option<Root<CanvasRenderingContext2D>> {
if self.context.get().is_none() { if self.context.get().is_none() {
let window = window_from_node(self); let window = window_from_node(self);
let size = self.get_size(); let size = self.get_size();
@ -178,7 +167,7 @@ impl<'a> HTMLCanvasElementHelpers for &'a HTMLCanvasElement {
} }
} }
fn get_or_init_webgl_context(self, pub fn get_or_init_webgl_context(&self,
cx: *mut JSContext, cx: *mut JSContext,
attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> {
if self.context.get().is_none() { if self.context.get().is_none() {
@ -211,36 +200,36 @@ impl<'a> HTMLCanvasElementHelpers for &'a HTMLCanvasElement {
} }
} }
fn is_valid(self) -> bool { pub fn is_valid(&self) -> bool {
self.height.get() != 0 && self.width.get() != 0 self.height.get() != 0 && self.width.get() != 0
} }
} }
impl<'a> HTMLCanvasElementMethods for &'a HTMLCanvasElement { impl HTMLCanvasElementMethods for HTMLCanvasElement {
// https://html.spec.whatwg.org/multipage/#dom-canvas-width // https://html.spec.whatwg.org/multipage/#dom-canvas-width
fn Width(self) -> u32 { fn Width(&self) -> u32 {
self.width.get() self.width.get()
} }
// https://html.spec.whatwg.org/multipage/#dom-canvas-width // https://html.spec.whatwg.org/multipage/#dom-canvas-width
fn SetWidth(self, width: u32) { fn SetWidth(&self, width: u32) {
let elem = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
elem.set_uint_attribute(&atom!("width"), width) elem.set_uint_attribute(&atom!("width"), width)
} }
// https://html.spec.whatwg.org/multipage/#dom-canvas-height // https://html.spec.whatwg.org/multipage/#dom-canvas-height
fn Height(self) -> u32 { fn Height(&self) -> u32 {
self.height.get() self.height.get()
} }
// https://html.spec.whatwg.org/multipage/#dom-canvas-height // https://html.spec.whatwg.org/multipage/#dom-canvas-height
fn SetHeight(self, height: u32) { fn SetHeight(&self, height: u32) {
let elem = ElementCast::from_ref(self); let elem = ElementCast::from_ref(self);
elem.set_uint_attribute(&atom!("height"), height) elem.set_uint_attribute(&atom!("height"), height)
} }
// https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext
fn GetContext(self, fn GetContext(&self,
cx: *mut JSContext, cx: *mut JSContext,
id: DOMString, id: DOMString,
attributes: Vec<HandleValue>) attributes: Vec<HandleValue>)
@ -261,9 +250,9 @@ impl<'a> HTMLCanvasElementMethods for &'a HTMLCanvasElement {
} }
} }
impl<'a> VirtualMethods for &'a HTMLCanvasElement { impl VirtualMethods for HTMLCanvasElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let element: &&HTMLElement = HTMLElementCast::from_borrowed_ref(self); let element: &HTMLElement = HTMLElementCast::from_ref(self);
Some(element as &VirtualMethods) Some(element as &VirtualMethods)
} }
@ -340,4 +329,3 @@ pub mod utils {
result.image_response result.image_response
} }
} }

View file

@ -9,8 +9,8 @@ use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, Root}; use dom::bindings::js::{JS, Root};
use dom::bindings::trace::JSTraceable; use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::{namespace_from_domstring, Reflector, reflect_dom_object}; use dom::bindings::utils::{namespace_from_domstring, Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers, ElementHelpers}; use dom::element::Element;
use dom::node::{Node, NodeHelpers, TreeIterator}; use dom::node::{Node, TreeIterator};
use dom::window::Window; use dom::window::Window;
use util::str::{DOMString, split_html_space_chars}; use util::str::{DOMString, split_html_space_chars};
@ -26,7 +26,6 @@ pub trait CollectionFilter : JSTraceable {
pub struct Collection(JS<Node>, Box<CollectionFilter + 'static>); pub struct Collection(JS<Node>, Box<CollectionFilter + 'static>);
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLCollection { pub struct HTMLCollection {
reflector_: Reflector, reflector_: Reflector,
#[ignore_heap_size_of = "Contains a trait object; can't measure due to #6870"] #[ignore_heap_size_of = "Contains a trait object; can't measure due to #6870"]
@ -45,9 +44,7 @@ impl HTMLCollection {
reflect_dom_object(box HTMLCollection::new_inherited(collection), reflect_dom_object(box HTMLCollection::new_inherited(collection),
GlobalRef::Window(window), HTMLCollectionBinding::Wrap) GlobalRef::Window(window), HTMLCollectionBinding::Wrap)
} }
}
impl HTMLCollection {
pub fn create(window: &Window, root: &Node, pub fn create(window: &Window, root: &Node,
filter: Box<CollectionFilter + 'static>) -> Root<HTMLCollection> { filter: Box<CollectionFilter + 'static>) -> Root<HTMLCollection> {
HTMLCollection::new(window, Collection(JS::from_ref(root), filter)) HTMLCollection::new(window, Collection(JS::from_ref(root), filter))
@ -67,7 +64,7 @@ impl HTMLCollection {
} }
} }
} }
let filter = AllElementFilter {namespace_filter: namespace_filter}; let filter = AllElementFilter { namespace_filter: namespace_filter };
HTMLCollection::create(window, root, box filter) HTMLCollection::create(window, root, box filter)
} }
@ -193,19 +190,19 @@ impl<'a> Iterator for HTMLCollectionElementsIter<'a> {
} }
} }
impl<'a> HTMLCollectionMethods for &'a HTMLCollection { impl HTMLCollectionMethods for HTMLCollection {
// https://dom.spec.whatwg.org/#dom-htmlcollection-length // https://dom.spec.whatwg.org/#dom-htmlcollection-length
fn Length(self) -> u32 { fn Length(&self) -> u32 {
self.elements_iter().count() as u32 self.elements_iter().count() as u32
} }
// https://dom.spec.whatwg.org/#dom-htmlcollection-item // https://dom.spec.whatwg.org/#dom-htmlcollection-item
fn Item(self, index: u32) -> Option<Root<Element>> { fn Item(&self, index: u32) -> Option<Root<Element>> {
self.elements_iter().nth(index as usize) self.elements_iter().nth(index as usize)
} }
// https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem // https://dom.spec.whatwg.org/#dom-htmlcollection-nameditem
fn NamedItem(self, key: DOMString) -> Option<Root<Element>> { fn NamedItem(&self, key: DOMString) -> Option<Root<Element>> {
// Step 1. // Step 1.
if key.is_empty() { if key.is_empty() {
return None; return None;
@ -219,21 +216,21 @@ impl<'a> HTMLCollectionMethods for &'a HTMLCollection {
} }
// https://dom.spec.whatwg.org/#dom-htmlcollection-item // https://dom.spec.whatwg.org/#dom-htmlcollection-item
fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<Root<Element>> { fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Element>> {
let maybe_elem = self.Item(index); let maybe_elem = self.Item(index);
*found = maybe_elem.is_some(); *found = maybe_elem.is_some();
maybe_elem maybe_elem
} }
// check-tidy: no specs after this line // check-tidy: no specs after this line
fn NamedGetter(self, name: DOMString, found: &mut bool) -> Option<Root<Element>> { fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<Root<Element>> {
let maybe_elem = self.NamedItem(name); let maybe_elem = self.NamedItem(name);
*found = maybe_elem.is_some(); *found = maybe_elem.is_some();
maybe_elem maybe_elem
} }
// https://dom.spec.whatwg.org/#interface-htmlcollection // https://dom.spec.whatwg.org/#interface-htmlcollection
fn SupportedPropertyNames(self) -> Vec<DOMString> { fn SupportedPropertyNames(&self) -> Vec<DOMString> {
// Step 1 // Step 1
let mut result = vec![]; let mut result = vec![];

View file

@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLDataElement { pub struct HTMLDataElement {
htmlelement: HTMLElement htmlelement: HTMLElement
} }
@ -43,4 +42,3 @@ impl HTMLDataElement {
Node::reflect_node(box element, document, HTMLDataElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDataElementBinding::Wrap)
} }
} }

View file

@ -17,7 +17,6 @@ use dom::node::{Node, NodeTypeId, window_from_node};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLDataListElement { pub struct HTMLDataListElement {
htmlelement: HTMLElement htmlelement: HTMLElement
} }
@ -49,9 +48,9 @@ impl HTMLDataListElement {
} }
} }
impl<'a> HTMLDataListElementMethods for &'a HTMLDataListElement { impl HTMLDataListElementMethods for HTMLDataListElement {
// https://html.spec.whatwg.org/multipage/#dom-datalist-options // https://html.spec.whatwg.org/multipage/#dom-datalist-options
fn Options(self) -> Root<HTMLCollection> { fn Options(&self) -> Root<HTMLCollection> {
#[derive(JSTraceable, HeapSizeOf)] #[derive(JSTraceable, HeapSizeOf)]
struct HTMLDataListOptionsFilter; struct HTMLDataListOptionsFilter;
impl CollectionFilter for HTMLDataListOptionsFilter { impl CollectionFilter for HTMLDataListOptionsFilter {
@ -65,4 +64,3 @@ impl<'a> HTMLDataListElementMethods for &'a HTMLDataListElement {
HTMLCollection::create(window.r(), node, filter) HTMLCollection::create(window.r(), node, filter)
} }
} }

View file

@ -18,7 +18,6 @@ use util::str::DOMString;
use std::borrow::ToOwned; use std::borrow::ToOwned;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLDialogElement { pub struct HTMLDialogElement {
htmlelement: HTMLElement, htmlelement: HTMLElement,
return_value: DOMRefCell<DOMString>, return_value: DOMRefCell<DOMString>,
@ -52,7 +51,7 @@ impl HTMLDialogElement {
} }
} }
impl<'a> HTMLDialogElementMethods for &'a HTMLDialogElement { impl HTMLDialogElementMethods for HTMLDialogElement {
// https://html.spec.whatwg.org/multipage/#dom-dialog-open // https://html.spec.whatwg.org/multipage/#dom-dialog-open
make_bool_getter!(Open); make_bool_getter!(Open);
@ -60,13 +59,13 @@ impl<'a> HTMLDialogElementMethods for &'a HTMLDialogElement {
make_bool_setter!(SetOpen, "open"); make_bool_setter!(SetOpen, "open");
// https://html.spec.whatwg.org/multipage/#dom-dialog-returnvalue // https://html.spec.whatwg.org/multipage/#dom-dialog-returnvalue
fn ReturnValue(self) -> DOMString { fn ReturnValue(&self) -> DOMString {
let return_value = self.return_value.borrow(); let return_value = self.return_value.borrow();
return_value.clone() return_value.clone()
} }
// https://html.spec.whatwg.org/multipage/#dom-dialog-returnvalue // https://html.spec.whatwg.org/multipage/#dom-dialog-returnvalue
fn SetReturnValue(self, return_value: DOMString) { fn SetReturnValue(&self, return_value: DOMString) {
*self.return_value.borrow_mut() = return_value; *self.return_value.borrow_mut() = return_value;
} }
} }

View file

@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLDirectoryElement { pub struct HTMLDirectoryElement {
htmlelement: HTMLElement htmlelement: HTMLElement
} }
@ -44,4 +43,3 @@ impl HTMLDirectoryElement {
Node::reflect_node(box element, document, HTMLDirectoryElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDirectoryElementBinding::Wrap)
} }
} }

View file

@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLDivElement { pub struct HTMLDivElement {
htmlelement: HTMLElement htmlelement: HTMLElement
} }
@ -43,4 +42,3 @@ impl HTMLDivElement {
Node::reflect_node(box element, document, HTMLDivElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDivElementBinding::Wrap)
} }
} }

View file

@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLDListElement { pub struct HTMLDListElement {
htmlelement: HTMLElement htmlelement: HTMLElement
} }
@ -42,4 +41,3 @@ impl HTMLDListElement {
Node::reflect_node(box element, document, HTMLDListElementBinding::Wrap) Node::reflect_node(box element, document, HTMLDListElementBinding::Wrap)
} }
} }

View file

@ -3,7 +3,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::attr::Attr; use dom::attr::Attr;
use dom::attr::AttrHelpers;
use dom::attr::AttrValue; use dom::attr::AttrValue;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::HTMLElementBinding; use dom::bindings::codegen::Bindings::HTMLElementBinding;
@ -18,16 +17,15 @@ use dom::bindings::error::ErrorResult;
use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::js::{JS, MutNullableHeap, Root};
use dom::bindings::utils::Reflectable; use dom::bindings::utils::Reflectable;
use dom::cssstyledeclaration::{CSSStyleDeclaration, CSSModificationAccess}; use dom::cssstyledeclaration::{CSSStyleDeclaration, CSSModificationAccess};
use dom::document::{Document, DocumentHelpers}; use dom::document::Document;
use dom::domstringmap::DOMStringMap; use dom::domstringmap::DOMStringMap;
use dom::element::{Element, ElementTypeId, ActivationElementHelpers, AttributeHandlers}; use dom::element::{Element, ElementTypeId};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId}; use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlinputelement::HTMLInputElement; use dom::htmlinputelement::HTMLInputElement;
use dom::htmlmediaelement::HTMLMediaElementTypeId; use dom::htmlmediaelement::HTMLMediaElementTypeId;
use dom::htmltablecellelement::HTMLTableCellElementTypeId; use dom::htmltablecellelement::HTMLTableCellElementTypeId;
use dom::node::{Node, NodeHelpers, NodeTypeId, document_from_node, window_from_node, SEQUENTIALLY_FOCUSABLE}; use dom::node::{Node, NodeTypeId, document_from_node, window_from_node, SEQUENTIALLY_FOCUSABLE};
use dom::virtualmethods::VirtualMethods; use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;
use msg::constellation_msg::FocusType; use msg::constellation_msg::FocusType;
use util::str::DOMString; use util::str::DOMString;
@ -40,7 +38,6 @@ use std::intrinsics;
use std::rc::Rc; use std::rc::Rc;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLElement { pub struct HTMLElement {
element: Element, element: Element,
style_decl: MutNullableHeap<JS<CSSStyleDeclaration>>, style_decl: MutNullableHeap<JS<CSSStyleDeclaration>>,
@ -80,20 +77,13 @@ impl HTMLElement {
let element = HTMLElement::new_inherited(HTMLElementTypeId::HTMLElement, localName, prefix, document); let element = HTMLElement::new_inherited(HTMLElementTypeId::HTMLElement, localName, prefix, document);
Node::reflect_node(box element, document, HTMLElementBinding::Wrap) Node::reflect_node(box element, document, HTMLElementBinding::Wrap)
} }
}
trait PrivateHTMLElementHelpers { fn is_body_or_frameset(&self) -> bool {
fn is_body_or_frameset(self) -> bool;
fn update_sequentially_focusable_status(self);
}
impl<'a> PrivateHTMLElementHelpers for &'a HTMLElement {
fn is_body_or_frameset(self) -> bool {
let eventtarget = EventTargetCast::from_ref(self); let eventtarget = EventTargetCast::from_ref(self);
eventtarget.is_htmlbodyelement() || eventtarget.is_htmlframesetelement() eventtarget.is_htmlbodyelement() || eventtarget.is_htmlframesetelement()
} }
fn update_sequentially_focusable_status(self) { fn update_sequentially_focusable_status(&self) {
let element = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
if element.has_attribute(&atom!("tabindex")) { if element.has_attribute(&atom!("tabindex")) {
@ -131,34 +121,40 @@ impl<'a> PrivateHTMLElementHelpers for &'a HTMLElement {
} }
} }
impl<'a> HTMLElementMethods for &'a HTMLElement { impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#the-style-attribute // https://html.spec.whatwg.org/multipage/#the-style-attribute
fn Style(self) -> Root<CSSStyleDeclaration> { fn Style(&self) -> Root<CSSStyleDeclaration> {
self.style_decl.or_init(|| { self.style_decl.or_init(|| {
let global = window_from_node(self); let global = window_from_node(self);
CSSStyleDeclaration::new(global.r(), ElementCast::from_ref(self), None, CSSModificationAccess::ReadWrite) CSSStyleDeclaration::new(global.r(), ElementCast::from_ref(self), None, CSSModificationAccess::ReadWrite)
}) })
} }
// https://html.spec.whatwg.org/multipage/#attr-title
make_getter!(Title); make_getter!(Title);
// https://html.spec.whatwg.org/multipage/#attr-title
make_setter!(SetTitle, "title"); make_setter!(SetTitle, "title");
// https://html.spec.whatwg.org/multipage/#attr-lang
make_getter!(Lang); make_getter!(Lang);
// https://html.spec.whatwg.org/multipage/#attr-lang
make_setter!(SetLang, "lang"); make_setter!(SetLang, "lang");
// https://html.spec.whatwg.org/multipage/#dom-hidden // https://html.spec.whatwg.org/multipage/#dom-hidden
make_bool_getter!(Hidden); make_bool_getter!(Hidden);
// https://html.spec.whatwg.org/multipage/#dom-hidden
make_bool_setter!(SetHidden, "hidden"); make_bool_setter!(SetHidden, "hidden");
// https://html.spec.whatwg.org/multipage/#globaleventhandlers
global_event_handlers!(NoOnload); global_event_handlers!(NoOnload);
// https://html.spec.whatwg.org/multipage/#dom-dataset // https://html.spec.whatwg.org/multipage/#dom-dataset
fn Dataset(self) -> Root<DOMStringMap> { fn Dataset(&self) -> Root<DOMStringMap> {
self.dataset.or_init(|| DOMStringMap::new(self)) self.dataset.or_init(|| DOMStringMap::new(self))
} }
// https://html.spec.whatwg.org/multipage/#handler-onload // https://html.spec.whatwg.org/multipage/#handler-onload
fn GetOnload(self) -> Option<Rc<EventHandlerNonNull>> { fn GetOnload(&self) -> Option<Rc<EventHandlerNonNull>> {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
let win = window_from_node(self); let win = window_from_node(self);
win.r().GetOnload() win.r().GetOnload()
@ -169,7 +165,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://html.spec.whatwg.org/multipage/#handler-onload // https://html.spec.whatwg.org/multipage/#handler-onload
fn SetOnload(self, listener: Option<Rc<EventHandlerNonNull>>) { fn SetOnload(&self, listener: Option<Rc<EventHandlerNonNull>>) {
if self.is_body_or_frameset() { if self.is_body_or_frameset() {
let win = window_from_node(self); let win = window_from_node(self);
win.r().SetOnload(listener) win.r().SetOnload(listener)
@ -180,7 +176,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-click // https://html.spec.whatwg.org/multipage/#dom-click
fn Click(self) { fn Click(&self) {
let maybe_input: Option<&HTMLInputElement> = HTMLInputElementCast::to_ref(self); let maybe_input: Option<&HTMLInputElement> = HTMLInputElementCast::to_ref(self);
if let Some(i) = maybe_input { if let Some(i) = maybe_input {
if i.Disabled() { if i.Disabled() {
@ -193,7 +189,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-focus // https://html.spec.whatwg.org/multipage/#dom-focus
fn Focus(self) { fn Focus(&self) {
// TODO: Mark the element as locked for focus and run the focusing steps. // TODO: Mark the element as locked for focus and run the focusing steps.
// https://html.spec.whatwg.org/multipage/#focusing-steps // https://html.spec.whatwg.org/multipage/#focusing-steps
let element = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
@ -205,7 +201,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://html.spec.whatwg.org/multipage/#dom-blur // https://html.spec.whatwg.org/multipage/#dom-blur
fn Blur(self) { fn Blur(&self) {
// TODO: Run the unfocusing steps. // TODO: Run the unfocusing steps.
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
if !node.get_focus_state() { if !node.get_focus_state() {
@ -219,7 +215,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
fn GetOffsetParent(self) -> Option<Root<Element>> { fn GetOffsetParent(&self) -> Option<Root<Element>> {
if self.is_htmlbodyelement() || self.is_htmlhtmlelement() { if self.is_htmlbodyelement() || self.is_htmlhtmlelement() {
return None; return None;
} }
@ -232,7 +228,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
fn OffsetTop(self) -> i32 { fn OffsetTop(&self) -> i32 {
if self.is_htmlbodyelement() { if self.is_htmlbodyelement() {
return 0; return 0;
} }
@ -245,7 +241,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
fn OffsetLeft(self) -> i32 { fn OffsetLeft(&self) -> i32 {
if self.is_htmlbodyelement() { if self.is_htmlbodyelement() {
return 0; return 0;
} }
@ -258,7 +254,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
fn OffsetWidth(self) -> i32 { fn OffsetWidth(&self) -> i32 {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let window = window_from_node(self); let window = window_from_node(self);
let (_, rect) = window.offset_parent_query(node.to_trusted_node_address()); let (_, rect) = window.offset_parent_query(node.to_trusted_node_address());
@ -267,7 +263,7 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface // https://drafts.csswg.org/cssom-view/#extensions-to-the-htmlelement-interface
fn OffsetHeight(self) -> i32 { fn OffsetHeight(&self) -> i32 {
let node = NodeCast::from_ref(self); let node = NodeCast::from_ref(self);
let window = window_from_node(self); let window = window_from_node(self);
let (_, rect) = window.offset_parent_query(node.to_trusted_node_address()); let (_, rect) = window.offset_parent_query(node.to_trusted_node_address());
@ -277,11 +273,6 @@ impl<'a> HTMLElementMethods for &'a HTMLElement {
} }
// https://html.spec.whatwg.org/#attr-data-* // https://html.spec.whatwg.org/#attr-data-*
pub trait HTMLElementCustomAttributeHelpers {
fn set_custom_attr(self, name: DOMString, value: DOMString) -> ErrorResult;
fn get_custom_attr(self, name: DOMString) -> Option<DOMString>;
fn delete_custom_attr(self, name: DOMString);
}
fn to_snake_case(name: DOMString) -> DOMString { fn to_snake_case(name: DOMString) -> DOMString {
let mut attr_name = "data-".to_owned(); let mut attr_name = "data-".to_owned();
@ -296,8 +287,8 @@ fn to_snake_case(name: DOMString) -> DOMString {
attr_name attr_name
} }
impl<'a> HTMLElementCustomAttributeHelpers for &'a HTMLElement { impl HTMLElement {
fn set_custom_attr(self, name: DOMString, value: DOMString) -> ErrorResult { pub fn set_custom_attr(&self, name: DOMString, value: DOMString) -> ErrorResult {
if name.chars() if name.chars()
.skip_while(|&ch| ch != '\u{2d}') .skip_while(|&ch| ch != '\u{2d}')
.nth(1).map_or(false, |ch| ch >= 'a' && ch <= 'z') { .nth(1).map_or(false, |ch| ch >= 'a' && ch <= 'z') {
@ -307,7 +298,7 @@ impl<'a> HTMLElementCustomAttributeHelpers for &'a HTMLElement {
element.set_custom_attribute(to_snake_case(name), value) element.set_custom_attribute(to_snake_case(name), value)
} }
fn get_custom_attr(self, local_name: DOMString) -> Option<DOMString> { pub fn get_custom_attr(&self, local_name: DOMString) -> Option<DOMString> {
let element = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
let local_name = Atom::from_slice(&to_snake_case(local_name)); let local_name = Atom::from_slice(&to_snake_case(local_name));
element.get_attribute(&ns!(""), &local_name).map(|attr| { element.get_attribute(&ns!(""), &local_name).map(|attr| {
@ -315,16 +306,16 @@ impl<'a> HTMLElementCustomAttributeHelpers for &'a HTMLElement {
}) })
} }
fn delete_custom_attr(self, local_name: DOMString) { pub fn delete_custom_attr(&self, local_name: DOMString) {
let element = ElementCast::from_ref(self); let element = ElementCast::from_ref(self);
let local_name = Atom::from_slice(&to_snake_case(local_name)); let local_name = Atom::from_slice(&to_snake_case(local_name));
element.remove_attribute(&ns!(""), &local_name); element.remove_attribute(&ns!(""), &local_name);
} }
} }
impl<'a> VirtualMethods for &'a HTMLElement { impl VirtualMethods for HTMLElement {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> { fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let element: &&Element = ElementCast::from_borrowed_ref(self); let element: &Element = ElementCast::from_ref(self);
Some(element as &VirtualMethods) Some(element as &VirtualMethods)
} }
@ -348,11 +339,11 @@ impl<'a> VirtualMethods for &'a HTMLElement {
let name = attr.local_name(); let name = attr.local_name();
if name.starts_with("on") { if name.starts_with("on") {
let window = window_from_node(*self); let window = window_from_node(self);
let (cx, url, reflector) = (window.r().get_cx(), let (cx, url, reflector) = (window.r().get_cx(),
window.r().get_url(), window.r().get_url(),
window.r().reflector().get_jsobject()); window.r().reflector().get_jsobject());
let evtarget = EventTargetCast::from_ref(*self); let evtarget = EventTargetCast::from_ref(self);
evtarget.set_event_handler_uncompiled(cx, url, reflector, evtarget.set_event_handler_uncompiled(cx, url, reflector,
&name[2..], &name[2..],
(**attr.value()).to_owned()); (**attr.value()).to_owned());

View file

@ -13,7 +13,6 @@ use dom::node::{Node, NodeTypeId};
use util::str::DOMString; use util::str::DOMString;
#[dom_struct] #[dom_struct]
#[derive(HeapSizeOf)]
pub struct HTMLEmbedElement { pub struct HTMLEmbedElement {
htmlelement: HTMLElement htmlelement: HTMLElement
} }
@ -41,4 +40,3 @@ impl HTMLEmbedElement {
Node::reflect_node(box element, document, HTMLEmbedElementBinding::Wrap) Node::reflect_node(box element, document, HTMLEmbedElementBinding::Wrap)
} }
} }

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